mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-27 17:58:47 +00:00
ui: include unread support chats in the chat list unread filter
A group where a member is waiting in a support chat has something to read - the chat list row already flags it - but the unread filter did not list it, so a moderator filtering for unread silently skipped the member waiting on them. chatStats.unreadCount is filled by a query scoped to the main conversation (group_scope_tag IS NULL), so 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. Two consequences of taking supportUnreadCount whole are deliberate. For a moderator it is membersRequireAttention, which counts members pending approval as well as unread messages, and only approving or rejecting clears those - so the group stays listed until the moderator acts. And mentions-only chats still count support unread, on the view that mentions-only is a statement about group chatter and the user's own line to the admins is not chatter.
This commit is contained in:
@@ -1412,6 +1412,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: [])
|
||||
}
|
||||
|
||||
|
||||
@@ -552,7 +552,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 unread support chats unless muted to "mute all" |
|
||||
| Favorites | `.favorites` | User-favorited chats |
|
||||
| Groups | `.groups` | Group conversations only |
|
||||
| Contacts | `.contacts` | Direct contacts only |
|
||||
|
||||
@@ -163,7 +163,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 unread support chats unless muted to "mute all" |
|
||||
| Favorites | `.presetTag(.favorites)` | Favorited conversations |
|
||||
| Groups | `.presetTag(.groups)` | Group conversations |
|
||||
| Contacts | `.presetTag(.contacts)` | Direct conversations |
|
||||
|
||||
@@ -1456,6 +1456,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
@@ -1476,7 +1476,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 unread support chats 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
|
||||
|
||||
@@ -143,7 +143,7 @@ The `filteredChats` function (line ~1188) 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 unread support chats unless the chat is muted to "mute all".
|
||||
|
||||
### Search Bar
|
||||
|
||||
|
||||
Reference in New Issue
Block a user