ui: fix channel contributor being able to "send message" without relays (#7139)

This commit is contained in:
spaced4ndy
2026-06-27 12:12:47 +01:00
committed by GitHub
parent e979b7efdc
commit 894e44b8ed
4 changed files with 68 additions and 36 deletions
@@ -1660,9 +1660,6 @@ sealed class ChatInfo: SomeChat, NamedChat {
if (groupInfo.membership.memberActive) {
when (groupChatScope) {
null -> {
if (allRelaysBroken && groupInfo.useRelays) {
return generalGetString(MR.strings.cant_broadcast_message) to null
}
if (groupInfo.membership.memberPending) {
return generalGetString(MR.strings.reviewed_by_admins) to generalGetString(MR.strings.observer_cant_send_message_desc)
}
@@ -1673,6 +1670,9 @@ sealed class ChatInfo: SomeChat, NamedChat {
generalGetString(MR.strings.observer_cant_send_message_title) to generalGetString(MR.strings.observer_cant_send_message_desc)
}
}
if (allRelaysBroken && groupInfo.useRelays) {
return generalGetString(MR.strings.cant_broadcast_message) to null
}
return null
}
is GroupChatScopeInfo.MemberSupport ->
@@ -1203,8 +1203,9 @@ fun ComposeView(
}
val ownerRelayState = ownerRelayState(chat, chatModel)
val subscriberRelayState = subscriberRelayState(chat, chatModel)
val userCantSendReason = rememberUpdatedState(chat.chatInfo.userCantSendReason(ownerRelayState?.noActiveRelays == true))
val userCantSendReason = rememberUpdatedState(chat.chatInfo.userCantSendReason((ownerRelayState?.noActiveRelays ?: subscriberRelayState?.noActiveRelays) == true))
val sendMsgEnabled = rememberUpdatedState(userCantSendReason.value == null)
val nextSendGrpInv = rememberUpdatedState(chat.nextSendGrpInv)
@@ -1575,18 +1576,12 @@ fun ComposeView(
}
}
} else {
val hostnames = (chatModel.channelRelayHostnames[gInfo.groupId] ?: emptyList()).sorted()
val relayMembers = chatModel.groupMembers.value
.filter { it.memberRole == GroupMemberRole.Relay && it.memberStatus !in listOf(GroupMemberStatus.MemRemoved, GroupMemberStatus.MemGroupDeleted) }
.sortedBy { hostFromRelayLink(it.relayLink ?: "") }
val showProgress = !gInfo.nextConnectPrepared || composeState.value.inProgress
val removedCount = relayMembers.count { relayMemberRemoved(it.memberStatus) }
val connectedCount = relayMembers.count { !relayMemberRemoved(it.memberStatus) && it.activeConn?.connStatus == ConnStatus.Ready && it.activeConn?.connFailedErr == null }
val failedCount = relayMembers.count { !relayMemberRemoved(it.memberStatus) && it.activeConn?.connFailedErr != null }
val resolvedCount = connectedCount + removedCount + failedCount
val total = if (relayMembers.isNotEmpty()) relayMembers.size else hostnames.size
if (total == 0 || removedCount + failedCount > 0 || resolvedCount < total) {
SubscriberChannelRelayBar(hostnames, relayMembers, connectedCount, removedCount, failedCount, total, showProgress, relayListExpanded)
subscriberRelayState?.let { s ->
val showProgress = !gInfo.nextConnectPrepared || composeState.value.inProgress
val resolvedCount = s.connectedCount + s.removedCount + s.failedCount
if (s.total == 0 || s.removedCount + s.failedCount > 0 || resolvedCount < s.total) {
SubscriberChannelRelayBar(s.hostnames, s.relayMembers, s.connectedCount, s.removedCount, s.failedCount, s.total, showProgress, relayListExpanded)
}
}
}
}
@@ -2052,6 +2047,33 @@ private data class OwnerRelayState(
val noActiveRelays: Boolean
)
private fun subscriberRelayState(chat: Chat, chatModel: ChatModel): SubscriberRelayState? {
val gInfo = (chat.chatInfo as? ChatInfo.Group)?.groupInfo ?: return null
if (!gInfo.useRelays || gInfo.membership.memberRole == GroupMemberRole.Owner ||
gInfo.membership.memberStatus in listOf(GroupMemberStatus.MemRejected, GroupMemberStatus.MemLeft, GroupMemberStatus.MemRemoved, GroupMemberStatus.MemGroupDeleted)
) return null
val hostnames = (chatModel.channelRelayHostnames[gInfo.groupId] ?: emptyList()).sorted()
val relayMembers = chatModel.groupMembers.value
.filter { it.memberRole == GroupMemberRole.Relay && it.memberStatus !in listOf(GroupMemberStatus.MemRemoved, GroupMemberStatus.MemGroupDeleted) }
.sortedBy { hostFromRelayLink(it.relayLink ?: "") }
val removedCount = relayMembers.count { relayMemberRemoved(it.memberStatus) }
val connectedCount = relayMembers.count { !relayMemberRemoved(it.memberStatus) && it.activeConn?.connStatus == ConnStatus.Ready && it.activeConn?.connFailedErr == null }
val failedCount = relayMembers.count { !relayMemberRemoved(it.memberStatus) && it.activeConn?.connFailedErr != null }
val total = if (relayMembers.isNotEmpty()) relayMembers.size else hostnames.size
val noActiveRelays = connectedCount == 0 && (removedCount + failedCount) == total
return SubscriberRelayState(hostnames, relayMembers, connectedCount, removedCount, failedCount, total, noActiveRelays)
}
private data class SubscriberRelayState(
val hostnames: List<String>,
val relayMembers: List<GroupMember>,
val connectedCount: Int,
val removedCount: Int,
val failedCount: Int,
val total: Int,
val noActiveRelays: Boolean
)
private fun relayMemberRemoved(status: GroupMemberStatus?): Boolean =
status in listOf(GroupMemberStatus.MemLeft, GroupMemberStatus.MemRemoved, GroupMemberStatus.MemGroupDeleted)