mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 06:32:59 +00:00
ui: channel owners can make subscribers moderators, and moderators see the subscriber list
Core already lets a channel owner make a subscriber a moderator; the role picker offered only subscriber and contributor. It now offers moderator too (not admin, by decision). Moderators see the full member list the owner sees, so they can reach the subscribers they may block (subscribers can't post, so there was no other way to reach them), and member info is headed Moderator or Contributor instead of Subscriber for those roles. Run: 001-channel-signing-moderators, slice 4
This commit is contained in:
1 parent
ff09510b09
commit
b0aba71547
9 files changed
+15
-15
No files matched your search
@@ -26,7 +26,7 @@ struct ChannelMembersView: View {
|
||||
.sorted { $0.wrapped.memberRole > $1.wrapped.memberRole }
|
||||
let subscriberCount = groupInfo.groupSummary.publicMemberCount ?? Int64(members.count + 1)
|
||||
let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase
|
||||
if groupInfo.isOwner {
|
||||
if groupInfo.canModerate {
|
||||
List {
|
||||
Section(header: Text(subscriberCountStr(subscriberCount)).foregroundColor(theme.colors.secondary)) {
|
||||
searchFieldView(text: $searchText, focussed: $searchFocussed, theme.colors.onBackground, theme.colors.secondary)
|
||||
|
||||
@@ -125,7 +125,7 @@ struct GroupChatInfoView: View {
|
||||
Label("Share via chat", systemImage: "arrowshape.turn.up.forward")
|
||||
}
|
||||
}
|
||||
if groupInfo.isOwner || members.contains(where: { $0.wrapped.memberRole >= .owner }) {
|
||||
if groupInfo.canModerate || members.contains(where: { $0.wrapped.memberRole >= .owner }) {
|
||||
channelMembersButton()
|
||||
}
|
||||
if groupInfo.membership.memberRole >= .moderator {
|
||||
@@ -734,7 +734,7 @@ struct GroupChatInfoView: View {
|
||||
}
|
||||
|
||||
private func channelMembersButton() -> some View {
|
||||
let label: LocalizedStringKey = groupInfo.isOwner ? "Subscribers" : "Owners & contributors"
|
||||
let label: LocalizedStringKey = groupInfo.canModerate ? "Subscribers" : "Owners & contributors"
|
||||
return NavigationLink {
|
||||
ChannelMembersView(chat: chat, groupInfo: groupInfo)
|
||||
.navigationTitle(label)
|
||||
|
||||
@@ -38,6 +38,8 @@ struct GroupMemberInfoView: View {
|
||||
switch groupMember.wrapped.memberRole {
|
||||
case .relay: "Relay"
|
||||
case .owner: "Owner"
|
||||
case .moderator: "Moderator"
|
||||
case .member: "Contributor"
|
||||
default: "Subscriber"
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -3414,10 +3414,7 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
|
||||
if groupInfo.useRelays && !groupInfo.isOwner { return nil }
|
||||
let userRole = groupInfo.membership.memberRole
|
||||
if groupInfo.useRelays {
|
||||
// TODO [relays]: for now owners can only set observer/member in channels.
|
||||
// Restore the full Owner-excluded picker when moderator/admin promotion is supported:
|
||||
// return GroupMemberRole.supportedRoles.filter { $0 <= userRole && $0 != .owner }
|
||||
return [.observer, .member]
|
||||
return [.observer, .member, .moderator]
|
||||
} else {
|
||||
return GroupMemberRole.supportedRoles.filter { $0 <= userRole }
|
||||
}
|
||||
|
||||
+1
-4
@@ -2987,10 +2987,7 @@ data class GroupMember (
|
||||
else if (groupInfo.useRelays && !groupInfo.isOwner) null
|
||||
else groupInfo.membership.memberRole.let { userRole ->
|
||||
if (groupInfo.useRelays)
|
||||
// TODO [relays]: for now owners can only set observer/member in channels.
|
||||
// Restore the full Owner-excluded picker when moderator/admin promotion is supported:
|
||||
// GroupMemberRole.selectableRoles.filter { it <= userRole && it != GroupMemberRole.Owner }
|
||||
listOf(GroupMemberRole.Observer, GroupMemberRole.Member)
|
||||
listOf(GroupMemberRole.Observer, GroupMemberRole.Member, GroupMemberRole.Moderator)
|
||||
else
|
||||
GroupMemberRole.selectableRoles.filter { it <= userRole }
|
||||
}
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ fun ModalData.ChannelMembersView(
|
||||
val s = searchText.value.text.trim().lowercase()
|
||||
val subscriberCount = groupInfo.groupSummary.publicMemberCount ?: (members.size + 1).toLong()
|
||||
val oneHandUI = remember { ChatController.appPrefs.oneHandUI.state }
|
||||
val title = if (groupInfo.isOwner) {
|
||||
val title = if (groupInfo.canModerate) {
|
||||
generalGetString(MR.strings.channel_members_title_subscribers)
|
||||
} else {
|
||||
generalGetString(MR.strings.channel_members_section_owners)
|
||||
@@ -57,7 +57,7 @@ fun ModalData.ChannelMembersView(
|
||||
item {
|
||||
AppBarTitle(title)
|
||||
}
|
||||
if (groupInfo.isOwner) {
|
||||
if (groupInfo.canModerate) {
|
||||
val showSearch = members.size > 8
|
||||
item {
|
||||
SectionView(title = subscriberCountStr(subscriberCount)) {
|
||||
|
||||
+2
-2
@@ -651,7 +651,7 @@ fun ModalData.GroupChatInfoLayout(
|
||||
ModalManager.closeAllModalsEverywhere()
|
||||
}
|
||||
}
|
||||
if (groupInfo.isOwner || activeSortedMembers.any { it.memberRole >= GroupMemberRole.Owner }) {
|
||||
if (groupInfo.canModerate || activeSortedMembers.any { it.memberRole >= GroupMemberRole.Owner }) {
|
||||
anyTopSectionRowShow = true
|
||||
ChannelMembersButton(chat.remoteHostId, groupInfo, showMemberInfo)
|
||||
}
|
||||
@@ -1295,7 +1295,7 @@ private fun ShareViaChatButton(onClick: () -> Unit) {
|
||||
|
||||
@Composable
|
||||
private fun ChannelMembersButton(rhId: Long?, groupInfo: GroupInfo, showMemberInfo: (GroupMember, GroupRelay?) -> Unit) {
|
||||
val title = if (groupInfo.isOwner) {
|
||||
val title = if (groupInfo.canModerate) {
|
||||
stringResource(MR.strings.channel_members_title_subscribers)
|
||||
} else {
|
||||
stringResource(MR.strings.channel_members_section_owners)
|
||||
|
||||
+2
@@ -594,6 +594,8 @@ fun GroupMemberInfoLayout(
|
||||
when (member.memberRole) {
|
||||
GroupMemberRole.Relay -> stringResource(MR.strings.member_info_section_title_relay)
|
||||
GroupMemberRole.Owner -> stringResource(MR.strings.member_info_section_title_owner)
|
||||
GroupMemberRole.Moderator -> stringResource(MR.strings.member_info_section_title_moderator)
|
||||
GroupMemberRole.Member -> stringResource(MR.strings.member_info_section_title_contributor)
|
||||
else -> stringResource(MR.strings.member_info_section_title_subscriber)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -3090,6 +3090,8 @@
|
||||
<!-- GroupMemberInfoView.kt channel-related -->
|
||||
<string name="member_info_section_title_relay">Relay</string>
|
||||
<string name="member_info_section_title_owner">Owner</string>
|
||||
<string name="member_info_section_title_moderator">Moderator</string>
|
||||
<string name="member_info_section_title_contributor">Contributor</string>
|
||||
<string name="member_info_section_title_subscriber">Subscriber</string>
|
||||
<string name="info_row_channel">Channel</string>
|
||||
<string name="info_row_relay_link">Relay link</string>
|
||||
|
||||
Reference in new issue
Block a user