From 87670e7cb09282be952370f93a248dd35d8b71b4 Mon Sep 17 00:00:00 2001 From: tapframe <85391825+tapframe@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:40:55 +0530 Subject: [PATCH] ref: remove startup observer causing stale catalog setting push --- .../commonMain/kotlin/com/nuvio/app/App.kt | 4 - .../home/HomeCatalogSettingsRepository.kt | 15 +++- .../home/HomeCatalogSettingsSyncService.kt | 74 +------------------ 3 files changed, 16 insertions(+), 77 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt index 4f040a0be..3abbb4eb2 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt @@ -182,7 +182,6 @@ import com.nuvio.app.features.collection.CollectionManagementScreen import com.nuvio.app.features.collection.CollectionEditorScreen import com.nuvio.app.features.collection.CollectionEditorRepository import com.nuvio.app.features.collection.CollectionSyncService -import com.nuvio.app.features.home.HomeCatalogSettingsSyncService import com.nuvio.app.features.collection.FolderDetailScreen import com.nuvio.app.features.collection.FolderDetailRepository import com.nuvio.app.features.streams.StreamAutoPlayPolicy @@ -687,9 +686,6 @@ private fun MainAppContent( remember { CollectionSyncService.startObserving() } - remember { - HomeCatalogSettingsSyncService.startObserving() - } remember { ProfileSettingsSync.startObserving() } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt index c5bd40ad7..067502d36 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsRepository.kt @@ -180,6 +180,7 @@ object HomeCatalogSettingsRepository { publish() persist() HomeRepository.applyCurrentSettings() + HomeCatalogSettingsSyncService.triggerPush() } fun setHideCatalogUnderline(enabled: Boolean) { @@ -188,10 +189,11 @@ object HomeCatalogSettingsRepository { hideCatalogUnderline = enabled publish() persist() + HomeCatalogSettingsSyncService.triggerPush() } fun setHeroSourceEnabled(key: String, enabled: Boolean) { - updatePreference(key) { preference -> + updatePreference(key, pushRemote = false) { preference -> if (!enabled) { preference.copy(heroSourceEnabled = false) } else if (selectedHeroSourceCount(excludingKey = key) >= HERO_SOURCE_SELECTION_LIMIT) { @@ -224,6 +226,7 @@ object HomeCatalogSettingsRepository { publish() persist() HomeRepository.applyCurrentSettings() + HomeCatalogSettingsSyncService.triggerPush() } fun moveUp(key: String) { @@ -249,6 +252,7 @@ object HomeCatalogSettingsRepository { publish() persist() HomeRepository.applyCurrentSettings() + HomeCatalogSettingsSyncService.triggerPush() } private fun ensureLoaded() { @@ -385,14 +389,20 @@ object HomeCatalogSettingsRepository { private fun updatePreference( key: String, + pushRemote: Boolean = true, transform: (StoredHomeCatalogPreference) -> StoredHomeCatalogPreference, ) { ensureLoaded() val current = preferences[key] ?: return - preferences[key] = transform(current) + val updated = transform(current) + if (updated == current) return + preferences[key] = updated publish() persist() HomeRepository.applyCurrentSettings() + if (pushRemote) { + HomeCatalogSettingsSyncService.triggerPush() + } } private fun selectedHeroSourceCount(excludingKey: String? = null): Int { @@ -427,6 +437,7 @@ object HomeCatalogSettingsRepository { publish() persist() HomeRepository.applyCurrentSettings() + HomeCatalogSettingsSyncService.triggerPush() } fun exportToSyncPayload(): SyncHomeCatalogPayload { diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt index 5a4851042..15f5ffc7c 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogSettingsSyncService.kt @@ -3,23 +3,18 @@ package com.nuvio.app.features.home import co.touchlab.kermit.Logger import com.nuvio.app.core.auth.AuthRepository import com.nuvio.app.core.auth.AuthState +import com.nuvio.app.core.network.SupabaseProvider import com.nuvio.app.core.sync.HOME_CATALOG_LEGACY_SYNC_PLATFORMS import com.nuvio.app.core.sync.HOME_CATALOG_SHARED_SYNC_PLATFORM -import com.nuvio.app.core.network.SupabaseProvider import com.nuvio.app.features.profiles.ProfileRepository import io.github.jan.supabase.postgrest.postgrest import io.github.jan.supabase.postgrest.rpc import kotlin.concurrent.Volatile import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.debounce -import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.drop -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -68,17 +63,6 @@ private data class PullToken( val profileId: Int, ) -private data class ObservedHomeCatalogChange( - val signature: String, - val token: PullToken?, - val initialPullCompleteAtEmission: Boolean, -) - -private data class HomeCatalogChangeSignature( - val signature: String, - val token: PullToken, -) - object HomeCatalogSettingsSyncService { private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) private val log = Logger.withTag("HomeCatalogSettingsSyncService") @@ -87,7 +71,6 @@ object HomeCatalogSettingsSyncService { encodeDefaults = true } - private const val PUSH_DEBOUNCE_MS = 1500L private const val HIDE_UNRELEASED_CONTENT_KEY = "hide_unreleased_content" private const val HIDE_CATALOG_UNDERLINE_KEY = "hide_catalog_underline" @@ -95,19 +78,10 @@ object HomeCatalogSettingsSyncService { var isSyncingFromRemote: Boolean = false private var pushJob: Job? = null - private var observeJob: Job? = null @Volatile private var completedInitialPull: PullToken? = null - @Volatile - private var remoteAppliedSignature: HomeCatalogChangeSignature? = null - - fun startObserving() { - if (observeJob?.isActive == true) return - observeLocalChangesAndPush() - } - suspend fun pullFromServer(profileId: Int) { runCatching { val pullToken = currentPullToken(profileId) ?: return @@ -124,12 +98,12 @@ object HomeCatalogSettingsSyncService { if (remotePayload.items.isEmpty()) { log.i { "pullFromServer — remote has empty items, preserving local catalog order" } - applyRemotePayload(remotePayload, pullToken) + applyRemotePayload(remotePayload) markInitialPullComplete(pullToken) return } - applyRemotePayload(remotePayload, pullToken) + applyRemotePayload(remotePayload) log.i { "pullFromServer — applied ${remotePayload.items.size} items from remote" } markInitialPullComplete(pullToken) }.onFailure { e -> @@ -170,43 +144,6 @@ object HomeCatalogSettingsSyncService { } } - @OptIn(FlowPreview::class) - private fun observeLocalChangesAndPush() { - observeJob = scope.launch { - HomeCatalogSettingsRepository.uiState - .map { state -> - val token = currentPullToken() - ObservedHomeCatalogChange( - signature = state.signature, - token = token, - initialPullCompleteAtEmission = token?.let(::hasCompletedInitialPull) == true, - ) - } - .drop(1) - .distinctUntilChanged() - .debounce(PUSH_DEBOUNCE_MS) - .collect { change -> - val token = change.token ?: return@collect - val changeSignature = HomeCatalogChangeSignature(change.signature, token) - if (!change.initialPullCompleteAtEmission) { - if (changeSignature == remoteAppliedSignature) { - remoteAppliedSignature = null - } - log.d { "observeLocalChangesAndPush — skipped before initial home catalog pull completed" } - return@collect - } - if (changeSignature == remoteAppliedSignature) { - remoteAppliedSignature = null - log.d { "observeLocalChangesAndPush — skipped remote-applied catalog change" } - return@collect - } - if (isSyncingFromRemote) return@collect - if (currentPullToken() != token) return@collect - pushToRemote(token.profileId) - } - } - } - private fun currentPullToken(profileId: Int = ProfileRepository.activeProfileId): PullToken? { val authState = AuthRepository.state.value if (authState !is AuthState.Authenticated || authState.isAnonymous) return null @@ -225,15 +162,10 @@ object HomeCatalogSettingsSyncService { private fun applyRemotePayload( payload: SyncHomeCatalogPayload, - token: PullToken, ) { isSyncingFromRemote = true try { HomeCatalogSettingsRepository.applyFromRemote(payload) - remoteAppliedSignature = HomeCatalogChangeSignature( - signature = HomeCatalogSettingsRepository.uiState.value.signature, - token = token, - ) } finally { isSyncingFromRemote = false }