diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.android.kt index 37d2d7891..798ba4822 100644 --- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.android.kt +++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.android.kt @@ -5,7 +5,7 @@ import android.content.SharedPreferences actual object WatchedStorage { private const val preferencesName = "nuvio_watched" - private const val payloadKey = "watched_payload" + private fun payloadKey(profileId: Int) = "watched_payload_$profileId" private var preferences: SharedPreferences? = null @@ -13,13 +13,13 @@ actual object WatchedStorage { preferences = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE) } - actual fun loadPayload(): String? = - preferences?.getString(payloadKey, null) + actual fun loadPayload(profileId: Int): String? = + preferences?.getString(payloadKey(profileId), null) - actual fun savePayload(payload: String) { + actual fun savePayload(profileId: Int, payload: String) { preferences ?.edit() - ?.putString(payloadKey, payload) + ?.putString(payloadKey(profileId), payload) ?.apply() } } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileRepository.kt index 6e9e00491..364d319f5 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileRepository.kt @@ -4,6 +4,7 @@ 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.features.watched.WatchedRepository import io.github.jan.supabase.postgrest.postgrest import io.github.jan.supabase.postgrest.rpc import kotlinx.coroutines.CoroutineScope @@ -106,6 +107,7 @@ object ProfileRepository { activeProfile = _state.value.profiles.find { it.profileIndex == profileIndex }, ) persist() + WatchedRepository.onProfileChanged(profileIndex) } suspend fun pushProfiles(profiles: List) { diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt index 0559dd9ae..afe52e985 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedRepository.kt @@ -44,6 +44,8 @@ private data class WatchedDeleteKey( ) object WatchedRepository { + private const val watchedItemsPageSize = 900 + private val syncScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) private val log = Logger.withTag("WatchedRepository") private val json = Json { @@ -55,13 +57,25 @@ object WatchedRepository { val uiState: StateFlow = _uiState.asStateFlow() private var hasLoaded = false + private var currentProfileId: Int = 1 private var itemsByKey: MutableMap = mutableMapOf() fun ensureLoaded() { if (hasLoaded) return - hasLoaded = true + loadFromDisk(ProfileRepository.activeProfileId) + } - val payload = WatchedStorage.loadPayload().orEmpty().trim() + fun onProfileChanged(profileId: Int) { + if (profileId == currentProfileId && hasLoaded) return + loadFromDisk(profileId) + } + + private fun loadFromDisk(profileId: Int) { + currentProfileId = profileId + hasLoaded = true + itemsByKey.clear() + + val payload = WatchedStorage.loadPayload(profileId).orEmpty().trim() if (payload.isNotEmpty()) { val items = runCatching { json.decodeFromString(payload).items @@ -73,10 +87,25 @@ object WatchedRepository { } suspend fun pullFromServer(profileId: Int) { + currentProfileId = profileId runCatching { - val params = buildJsonObject { put("p_profile_id", profileId) } - val result = SupabaseProvider.client.postgrest.rpc("sync_pull_watched_items", params) - val serverItems = result.decodeList() + val serverItems = mutableListOf() + var page = 1 + + while (true) { + val params = buildJsonObject { + put("p_profile_id", profileId) + put("p_page", page) + put("p_page_size", watchedItemsPageSize) + } + val result = SupabaseProvider.client.postgrest.rpc("sync_pull_watched_items", params) + val pageItems = result.decodeList() + serverItems += pageItems + + if (pageItems.size < watchedItemsPageSize) break + page += 1 + } + itemsByKey = serverItems.map { syncItem -> WatchedItem( id = syncItem.contentId, @@ -176,6 +205,7 @@ object WatchedRepository { private fun persist() { WatchedStorage.savePayload( + currentProfileId, json.encodeToString( StoredWatchedPayload( items = itemsByKey.values.sortedByDescending { it.markedAtEpochMs }, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.kt index 0eb37da7b..96ad90f23 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.kt @@ -1,7 +1,7 @@ package com.nuvio.app.features.watched expect object WatchedStorage { - fun loadPayload(): String? - fun savePayload(payload: String) + fun loadPayload(profileId: Int): String? + fun savePayload(profileId: Int, payload: String) } diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.ios.kt index 71c6d965c..919aad5a2 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.ios.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/watched/WatchedStorage.ios.kt @@ -3,13 +3,13 @@ package com.nuvio.app.features.watched import platform.Foundation.NSUserDefaults actual object WatchedStorage { - private const val payloadKey = "watched_payload" + private fun payloadKey(profileId: Int) = "watched_payload_$profileId" - actual fun loadPayload(): String? = - NSUserDefaults.standardUserDefaults.stringForKey(payloadKey) + actual fun loadPayload(profileId: Int): String? = + NSUserDefaults.standardUserDefaults.stringForKey(payloadKey(profileId)) - actual fun savePayload(payload: String) { - NSUserDefaults.standardUserDefaults.setObject(payload, forKey = payloadKey) + actual fun savePayload(profileId: Int, payload: String) { + NSUserDefaults.standardUserDefaults.setObject(payload, forKey = payloadKey(profileId)) } }