@@ -255,26 +255,44 @@ class ConversationsListViewModel @Inject constructor(
255255 selectedTagIsFavoritesFlow.value = tagId != null && isFavorites
256256 }
257257
258+ private val searchDisplayModeFlow = combine(_isSearchActiveFlow , _currentSearchQueryFlow ) { active, query ->
259+ when {
260+ ! active -> SearchDisplayMode .OFF
261+ query.isEmpty() -> SearchDisplayMode .ALL_CONVERSATIONS
262+ else -> SearchDisplayMode .RESULTS
263+ }
264+ }
265+
258266 /* *
259267 * Single source of truth for the [ConversationList] LazyColumn.
260268 * Auto-reacts to rooms, filter, tag filter, search-active and search-result changes.
261269 */
262270 val conversationListEntriesFlow: StateFlow <List <ConversationListEntry >> = combine(
263271 getRoomsStateFlow,
264272 _filterStateFlow ,
265- combine(_isSearchActiveFlow , _currentSearchQueryFlow ) { active, query ->
266- when {
267- ! active -> SearchDisplayMode .OFF
268- query.isEmpty() -> SearchDisplayMode .ALL_CONVERSATIONS
269- else -> SearchDisplayMode .RESULTS
270- }
271- },
273+ searchDisplayModeFlow,
272274 combine(_selectedTagFilterFlow , selectedTagIsFavoritesFlow, ::TagFilterSelection ),
273275 combine(searchResultEntries, hideRoomToken, ::Pair )
274276 ) { rooms, filterState, searchMode, tagFilter, (searchResults, hideToken) ->
275277 buildConversationListEntries(rooms, filterState, searchMode, tagFilter, searchResults, hideToken)
276278 }.stateIn(viewModelScope, SharingStarted .Eagerly , emptyList())
277279
280+ /* *
281+ * Rooms that would actually be shown in the list under the current filter chips
282+ * (mention/unread/archive) and hidden-room/lobby rules, but *before* narrowing to a
283+ * specific tag. Used to decide which tag filter chips currently have a matching,
284+ * visible conversation - e.g. a tag whose only conversation is archived should not
285+ * show up as a chip unless the "Archived" filter is active.
286+ */
287+ val visibleRoomsFlow: StateFlow <List <ConversationModel >> = combine(
288+ getRoomsStateFlow,
289+ _filterStateFlow ,
290+ searchDisplayModeFlow,
291+ hideRoomToken
292+ ) { rooms, filterState, searchMode, hideToken ->
293+ baseFilterRooms(rooms, filterState, searchMode, hideToken)
294+ }.stateIn(viewModelScope, SharingStarted .Eagerly , emptyList())
295+
278296 /* * Clears the tag filter when the filtered-by tag no longer exists (e.g. it was deleted). */
279297 fun clearTagFilterIfMatches (tagId : String ) {
280298 if (_selectedTagFilterFlow .value == tagId) {
@@ -640,6 +658,34 @@ class ConversationsListViewModel @Inject constructor(
640658 ): List <ConversationListEntry > {
641659 if (searchMode == SearchDisplayMode .RESULTS ) return searchResults
642660
661+ var filtered = baseFilterRooms(rooms, filterState, searchMode, hideToken)
662+
663+ if (searchMode != SearchDisplayMode .ALL_CONVERSATIONS ) {
664+ filtered = when {
665+ tagFilter.isFavorites -> filtered.filter { it.favorite }
666+ tagFilter.tagId != null -> filtered.filter { it.tagIds.contains(tagFilter.tagId) }
667+ else -> filtered
668+ }
669+ }
670+
671+ val sorted = filtered.sortedWith(
672+ compareByDescending<ConversationModel > { it.favorite }
673+ .thenByDescending { it.lastActivity }
674+ )
675+ return sorted.map { ConversationListEntry .ConversationEntry (it) }
676+ }
677+
678+ /* *
679+ * Applies the hidden-room/lobby rules and the current filter chips (mention/unread/archive),
680+ * but not the tag filter. Shared by [buildConversationListEntries] and [visibleRoomsFlow] so
681+ * that both the list content and the tag-chip visibility agree on what "visible" means.
682+ */
683+ private fun baseFilterRooms (
684+ rooms : List <ConversationModel >,
685+ filterState : Map <String , Boolean >,
686+ searchMode : SearchDisplayMode ,
687+ hideToken : String?
688+ ): List <ConversationModel > {
643689 val hasFilterEnabled = filterState[MENTION ] == true ||
644690 filterState[UNREAD ] == true ||
645691 filterState[ARCHIVE ] == true
@@ -655,25 +701,12 @@ class ConversationsListViewModel @Inject constructor(
655701
656702 filtered = when {
657703 // While search is open with an empty query, all conversations are listed,
658- // ignoring active filters, the tag filter and the default hiding of archived/future-event rooms
704+ // ignoring active filters and the default hiding of archived/future-event rooms
659705 searchMode == SearchDisplayMode .ALL_CONVERSATIONS -> filtered
660706 hasFilterEnabled -> filtered.filter { filterConversationModel(it, filterState) }
661707 else -> filtered.filter { ! isFutureEvent(it) && ! it.hasArchived }
662708 }
663-
664- if (searchMode != SearchDisplayMode .ALL_CONVERSATIONS ) {
665- filtered = when {
666- tagFilter.isFavorites -> filtered.filter { it.favorite }
667- tagFilter.tagId != null -> filtered.filter { it.tagIds.contains(tagFilter.tagId) }
668- else -> filtered
669- }
670- }
671-
672- val sorted = filtered.sortedWith(
673- compareByDescending<ConversationModel > { it.favorite }
674- .thenByDescending { it.lastActivity }
675- )
676- return sorted.map { ConversationListEntry .ConversationEntry (it) }
709+ return filtered
677710 }
678711
679712 @Suppress(" CyclomaticComplexMethod" , " NestedBlockDepth" )
0 commit comments