core, ui: load only members with support chats for the support chats list

This commit is contained in:
Narasimha-sc committed 2026-09-27 21:21:19 +00:00
1 parent d781beb30b
commit 9edf0ca436
10 files changed
+72 -6

No files matched your search

@@ -168,6 +168,7 @@ object ChatModel {
val groupMembers = mutableStateOf<List<GroupMember>>(emptyList())
val groupMembersIndexes = mutableStateOf<Map<Long, Int>>(emptyMap())
val membersLoaded = mutableStateOf(false)
val supportMembersLoaded = mutableStateOf(false)
// Runtime-only relay hostnames for pre-join channel display, not persisted — lost on app restart.
// APIConnectPreparedGroup re-fetches fresh relays at connect time, so stale data doesn't affect join.
val channelRelayHostnames = mutableStateMapOf<Long, List<String>>()
@@ -969,6 +970,7 @@ object ChatModel {
channelRelayHostnames.remove(groupId)
}
membersLoaded.value = false
supportMembersLoaded.value = false
}
}
@@ -985,6 +987,7 @@ object ChatModel {
groupMembers.value = emptyList()
groupMembersIndexes.value = emptyMap()
membersLoaded.value = false
supportMembersLoaded.value = false
}
val memberIndex = groupMembersIndexes.value[member.groupMemberId]
val updated = chatItems.value.map {
@@ -2495,6 +2495,13 @@ object ChatController {
return null
}
suspend fun apiListSupportMembers(rh: Long?, groupId: Long): List<GroupMember>? {
val r = sendCmd(rh, CC.ApiListSupportMembers(groupId))
if (r is API.Result && r.res is CR.GroupMembers) return r.res.group.members
Log.e(TAG, "apiListSupportMembers bad response: ${r.responseType} ${r.details}")
return null
}
suspend fun apiUpdateGroup(rh: Long?, groupId: Long, groupProfile: GroupProfile, isChannel: Boolean): GroupInfo? {
val r = sendCmd(rh, CC.ApiUpdateGroupProfile(groupId, groupProfile))
val errorTitle = if (isChannel) MR.strings.error_saving_channel_profile else MR.strings.error_saving_group_profile
@@ -3959,6 +3966,7 @@ sealed class CC {
class ApiRemoveMembers(val groupId: Long, val memberIds: List<Long>, val withMessages: Boolean): CC()
class ApiLeaveGroup(val groupId: Long): CC()
class ApiListMembers(val groupId: Long): CC()
class ApiListSupportMembers(val groupId: Long): CC()
class ApiUpdateGroupProfile(val groupId: Long, val groupProfile: GroupProfile): CC()
class ApiSetPublicGroupAccess(val groupId: Long, val access: PublicGroupAccess): CC()
class APICreateGroupLink(val groupId: Long, val memberRole: GroupMemberRole): CC()
@@ -4175,6 +4183,7 @@ sealed class CC {
is ApiRemoveMembers -> "/_remove #$groupId ${memberIds.joinToString(",")} messages=${onOff(withMessages)}"
is ApiLeaveGroup -> "/_leave #$groupId"
is ApiListMembers -> "/_members #$groupId"
is ApiListSupportMembers -> "/_members support #$groupId"
is ApiUpdateGroupProfile -> "/_group_profile #$groupId ${json.encodeToString(groupProfile)}"
is APICreateGroupLink -> "/_create link #$groupId ${memberRole.name.lowercase()}"
is APIGroupLinkMemberRole -> "/_set link role #$groupId ${memberRole.name.lowercase()}"
@@ -4370,6 +4379,7 @@ sealed class CC {
is ApiRemoveMembers -> "apiRemoveMembers"
is ApiLeaveGroup -> "apiLeaveGroup"
is ApiListMembers -> "apiListMembers"
is ApiListSupportMembers -> "apiListSupportMembers"
is ApiUpdateGroupProfile -> "apiUpdateGroupProfile"
is APICreateGroupLink -> "apiCreateGroupLink"
is APIGroupLinkMemberRole -> "apiGroupLinkMemberRole"
@@ -174,6 +174,7 @@ fun ChatView(
chatModel.groupMembers.value = emptyList()
chatModel.groupMembersIndexes.value = emptyMap()
chatModel.membersLoaded.value = false
chatModel.supportMembersLoaded.value = false
}
showSearch.value = false
searchText.value = ""
@@ -385,6 +386,7 @@ fun ChatView(
chatModel.groupMembers.value = emptyList()
chatModel.groupMembersIndexes.value = emptyMap()
chatModel.membersLoaded.value = false
chatModel.supportMembersLoaded.value = false
ChannelRelaysModel.reset()
},
info = {
@@ -42,12 +42,12 @@ fun ModalData.MemberSupportView(
ModalManager.end.closeModals()
}
val membersLoading = remember { stateGetOrPut("membersLoading") { false } }
LaunchedEffect(chatModel.membersLoaded.value) {
if (!chatModel.membersLoaded.value && chatModel.chatId.value == groupInfo.id && !membersLoading.value) {
LaunchedEffect(chatModel.membersLoaded.value, chatModel.supportMembersLoaded.value) {
if (!chatModel.membersLoaded.value && !chatModel.supportMembersLoaded.value && chatModel.chatId.value == groupInfo.id && !membersLoading.value) {
membersLoading.value = true
withBGApi {
try {
setGroupMembers(rhId, groupInfo, chatModel)
setSupportMembers(rhId, groupInfo, chatModel)
} finally {
membersLoading.value = false
}
@@ -274,6 +274,28 @@ suspend fun setGroupMembers(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatMo
}
}
suspend fun setSupportMembers(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel) = coroutineScope {
val supportMembers = chatModel.controller.apiListSupportMembers(rhId, groupInfo.groupId)
?: return@coroutineScope setGroupMembers(rhId, groupInfo, chatModel)
withContext(Dispatchers.Main) {
if (chatModel.chatId.value != groupInfo.id) return@withContext
val membersById = LinkedHashMap<Long, GroupMember>()
chatModel.groupMembers.value.forEach { if (it.groupId == groupInfo.groupId) membersById[it.groupMemberId] = it }
supportMembers.forEach { member ->
val currentStats = membersById[member.groupMemberId]?.activeConn?.connectionStats
val memberConn = member.activeConn
membersById[member.groupMemberId] = if (currentStats != null && memberConn != null && memberConn.connectionStats == null) {
member.copy(activeConn = memberConn.copy(connectionStats = currentStats))
} else {
member
}
}
chatModel.groupMembers.value = membersById.values.toList()
chatModel.populateGroupMembersIndexes()
chatModel.supportMembersLoaded.value = true
}
}
@Composable
fun ContactMenuItems(chat: Chat, contact: Contact, chatModel: ChatModel, showMenu: MutableState<Boolean>, showMarkRead: Boolean) {
if (contact.nextAcceptContactRequest) {