From 2784f274ec4320758b99030a8f5c0db0b7595d37 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 12 May 2026 13:24:58 +0000 Subject: [PATCH 1/2] fix(home): clear the Home tab dot when the only enabled tab is read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Home bottom-bar new-items dot was hardcoded to compare HomeFollows lastRead against the homeNewThreads feed. Each home tab writes to its own routeForLastRead (HomeFollows, HomeFollowsReplies, HomeFollowsEverything), so a user who only enabled the Everything tab could never clear the dot — reading items only advanced HomeFollowsEverything while the dot stayed lit on the untouched HomeFollows route. Recompute homeHasNewItems across all three (route, feed) pairs and gate each arm by its uiSettingsFlow toggle, so the dot reflects the state of whichever tabs the user has enabled. --- .../ui/screen/loggedIn/AccountViewModel.kt | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index af02c9f5d5..7d16847a78 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -159,6 +159,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -397,10 +398,13 @@ class AccountViewModel( .stateIn(viewModelScope, SharingStarted.WhileSubscribed(30000), false) @OptIn(ExperimentalCoroutinesApi::class) - val homeHasNewItems = + private fun tabHasNewItems( + route: String, + feedContent: StateFlow, + ): Flow = combineTransform( - account.loadLastReadFlow("HomeFollows"), - feedStates.homeNewThreads.feedContent + account.loadLastReadFlow(route), + feedContent .flatMapLatest { if (it is FeedState.Loaded) { it.feed @@ -412,15 +416,31 @@ class AccountViewModel( }, ) { lastRead, newestItemCreatedAt -> emit(newestItemCreatedAt != null && newestItemCreatedAt > lastRead) - }.onStart { - val lastRead = account.loadLastReadFlow("HomeFollows").value - val feed = feedStates.homeNewThreads.feedContent.value - if (feed is FeedState.Loaded) { - val newestItemCreatedAt = - feed.feed.value.list - .firstOrNull { it.event != null && it.event !is GenericRepostEvent && it.event !is RepostEvent } - ?.createdAt() - emit(newestItemCreatedAt != null && newestItemCreatedAt > lastRead) + } + + val homeHasNewItems: Flow = + combine( + settings.uiSettingsFlow.showHomeNewThreadsTab, + settings.uiSettingsFlow.showHomeConversationsTab, + settings.uiSettingsFlow.showHomeEverythingTab, + tabHasNewItems("HomeFollows", feedStates.homeNewThreads.feedContent), + tabHasNewItems("HomeFollowsReplies", feedStates.homeReplies.feedContent), + tabHasNewItems("HomeFollowsEverything", feedStates.homeEverything.feedContent), + ) { values -> + val showThreads = values[0] + val showReplies = values[1] + val showEverything = values[2] + val threadsHas = values[3] + val repliesHas = values[4] + val everythingHas = values[5] + val anyEnabled = showThreads || showReplies || showEverything + if (!anyEnabled) { + // HomeScreen falls back to the New Threads tab when the user disables every tab. + threadsHas + } else { + (showThreads && threadsHas) || + (showReplies && repliesHas) || + (showEverything && everythingHas) } } From c7eba6a620b6216cab653064febd4ff63efd952c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 11:01:08 +0000 Subject: [PATCH 2/2] fix(home): clear Home dot when any one home tab is read to the top MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous attempt lit the dot whenever *any* enabled home tab had unread items, so a user with all three tabs enabled who only scrolled through the Everything tab still saw the dot — HomeFollows / HomeFollowsReplies stayed at their old lastRead even though the same content had been read via Everything. Switch to "every enabled tab still has unread" — equivalently, reaching the top of any single enabled tab clears the dot. This matches the pre-bug behavior (where only the New Threads tab gated the dot) while still respecting users who only enable the Everything tab. --- .../amethyst/ui/screen/loggedIn/AccountViewModel.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 7d16847a78..984f8de5e8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -438,9 +438,11 @@ class AccountViewModel( // HomeScreen falls back to the New Threads tab when the user disables every tab. threadsHas } else { - (showThreads && threadsHas) || - (showReplies && repliesHas) || - (showEverything && everythingHas) + // Dot stays lit only when every enabled tab still has unread items. + // Reaching the top of any single tab marks its newest item read and clears the dot. + (!showThreads || threadsHas) && + (!showReplies || repliesHas) && + (!showEverything || everythingHas) } }