mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-11-04 06:32:59 +00:00
ui: include support chats that need attention in the chat list unread filter
A group whose support chats need attention - for a member, unread replies in their own "Chat with admins"; for a moderator, members waiting on them - is flagged on its chat list row, but the unread filter did not list it. chatStats.unreadCount is filled by a query scoped to the main conversation (group_scope_tag IS NULL), so, except for a pending member's own support chat, unreadTag cannot see support scopes at all. Match on Chat.hasUnread, which adds supportUnreadCount to unreadTag, gated on the chat not being muted to "mute all" - so a support chat waiting in a fully muted group does not put it in the filter, matching what the profile's unread count does with that group. Marking such a chat unread by hand still lists it, through unreadTag's unreadChat branch. On iOS, updateChatInfo changes the chat in place, so it now publishes when hasUnread changes, for the filter to update. supportUnreadCount is the same value the row's flag shows. For a moderator it is membersRequireAttention, which counts members: pending approval or review, or with unread messages nobody has answered or unread mentions. Reading does not clear a pending member - approving (once nothing else in their support chat needs attention), rejecting, or the member leaving does - so the group stays listed until then. Mentions-only chats still count support chats, on the view that mentions-only is a statement about group chatter, and support chats (the user's own line to the admins, or members waiting on a moderator) are not chatter.
This commit is contained in:
1 parent
ef6c913f78
commit
43ad806482
8 files changed
+12
-6
No files matched your search
@@ -623,12 +623,14 @@ final class ChatModel: ObservableObject {
|
||||
// Spec: spec/state.md#updateChatInfo
|
||||
func updateChatInfo(_ cInfo: ChatInfo) {
|
||||
if let i = getChatIndex(cInfo.id) {
|
||||
let wasUnread = chats[i].hasUnread
|
||||
if case let .group(groupInfo, groupChatScope) = cInfo, groupChatScope != nil {
|
||||
chats[i].chatInfo = .group(groupInfo: groupInfo, groupChatScope: nil)
|
||||
} else {
|
||||
chats[i].chatInfo = cInfo
|
||||
}
|
||||
chats[i].created = Date.now
|
||||
if chats[i].hasUnread != wasUnread { objectWillChange.send() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1470,6 +1472,8 @@ final class Chat: ObservableObject, Identifiable, ChatLike {
|
||||
}
|
||||
}
|
||||
|
||||
var hasUnread: Bool { unreadTag || (chatInfo.chatSettings?.enableNtfs != MsgFilter.none && supportUnreadCount > 0) }
|
||||
|
||||
public static var sampleData: Chat = Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: [])
|
||||
}
|
||||
|
||||
|
||||
@@ -673,7 +673,7 @@ struct ChatListView: View {
|
||||
switch chatTagsModel.activeFilter {
|
||||
case let .presetTag(tag): presetTagMatchesChat(tag, chat.chatInfo, chat.chatStats)
|
||||
case let .userTag(tag): chat.chatInfo.chatTags?.contains(tag.chatTagId) == true
|
||||
case .unread: chat.unreadTag
|
||||
case .unread: chat.hasUnread
|
||||
case .none: true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ Managed by `ChatTagsModel` and `TagListView`:
|
||||
| Filter | PresetTag | Description |
|
||||
|---|---|---|
|
||||
| All | (none) | No filter, shows all chats |
|
||||
| Unread | `.unread` | Chats with unread messages |
|
||||
| Unread | `.unread` | Chats with unread messages, or support chats that need attention (as flagged on the row: unread messages or mentions, or, for moderators, members pending, with unread messages nobody has answered, or with unread mentions) unless muted to "mute all" |
|
||||
| Favorites | `.favorites` | User-favorited chats |
|
||||
| Groups | `.groups` | Group conversations only |
|
||||
| Contacts | `.contacts` | Direct contacts only |
|
||||
|
||||
@@ -164,7 +164,7 @@ Horizontal scrolling tab bar below the navigation bar. Tabs:
|
||||
| Tab | Filter | Shows |
|
||||
|-----|--------|-------|
|
||||
| All | `nil` | All conversations |
|
||||
| Unread | `.unread` | Conversations with unread messages |
|
||||
| Unread | `.unread` | Conversations with unread messages, or support chats that need attention (as flagged on the row: unread messages or mentions, or, for moderators, members pending, with unread messages nobody has answered, or with unread mentions) unless muted to "mute all" |
|
||||
| Favorites | `.presetTag(.favorites)` | Favorited conversations |
|
||||
| Groups | `.presetTag(.groups)` | Group conversations |
|
||||
| Contacts | `.presetTag(.contacts)` | Direct conversations |
|
||||
|
||||
@@ -1507,6 +1507,8 @@ data class Chat(
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val hasUnread: Boolean get() = unreadTag || (chatInfo.chatSettings?.enableNtfs != None && supportUnreadCount > 0)
|
||||
|
||||
fun groupFeatureEnabled(feature: GroupFeature): Boolean =
|
||||
if (chatInfo is ChatInfo.Group) {
|
||||
chatInfo.groupInfo.groupFeatureEnabled(feature)
|
||||
|
||||
+1
-1
@@ -1601,7 +1601,7 @@ private fun filtered(chat: Chat, activeFilter: ActiveFilter?): Boolean =
|
||||
when (activeFilter) {
|
||||
is ActiveFilter.PresetTag -> presetTagMatchesChat(activeFilter.tag, chat.chatInfo, chat.chatStats)
|
||||
is ActiveFilter.UserTag -> chat.chatInfo.chatTags?.contains(activeFilter.tag.chatTagId) ?: false
|
||||
is ActiveFilter.Unread -> chat.unreadTag
|
||||
is ActiveFilter.Unread -> chat.hasUnread
|
||||
else -> true
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ Managed by `chatModel.userTags`, `chatModel.presetTags`, and `chatModel.activeCh
|
||||
| Business | `BUSINESS` | Work | Business chat conversations |
|
||||
| Notes | `NOTES` | Folder | Notes to self |
|
||||
| Custom tags | `UserTag(ChatTag)` | Label/emoji | User-created tags with custom emoji and name |
|
||||
| Unread | `ActiveFilter.Unread` | Filter list icon | Chats with unread messages (toggle via filter button) |
|
||||
| Unread | `ActiveFilter.Unread` | Filter list icon | Chats with unread messages, or support chats that need attention (as flagged on the row: unread messages or mentions, or, for moderators, members pending, with unread messages nobody has answered, or with unread mentions) unless muted to "mute all" (toggle via filter button) |
|
||||
|
||||
Display logic:
|
||||
- When collapsible preset tags exceed 3 total (with user tags), they collapse into a `CollapsedTagsFilterView` dropdown menu
|
||||
|
||||
@@ -144,7 +144,7 @@ The `filteredChats` function (line ~1474) applies filters in this order:
|
||||
3. **Active filter:**
|
||||
- `PresetTag`: Matches chat type and characteristics (e.g., `CONTACTS` filters `ChatInfo.Direct`, `GROUPS` filters `ChatInfo.Group`).
|
||||
- `UserTag`: Matches chats whose `chatTags` contain the tag ID.
|
||||
- `Unread`: Matches chats with `unreadCount > 0` or `unreadChat == true`.
|
||||
- `Unread`: Matches `Chat.hasUnread` — a chat marked unread by hand, unread messages as the chat's notification setting counts them, or support chats that need attention (as flagged on the row: unread messages or mentions, or, for moderators, members pending, with unread messages nobody has answered, or with unread mentions) unless the chat is muted to "mute all".
|
||||
|
||||
### Search Bar
|
||||
|
||||
|
||||
Reference in new issue
Block a user