diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogDefinitions.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogDefinitions.kt index 853b42a46..ae239c202 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogDefinitions.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeCatalogDefinitions.kt @@ -1,6 +1,8 @@ package com.nuvio.app.features.home import com.nuvio.app.core.i18n.localizedMediaTypeLabel +import com.nuvio.app.features.addons.AddonCatalog +import com.nuvio.app.features.addons.AddonManifest import com.nuvio.app.features.addons.ManagedAddon import com.nuvio.app.features.addons.enabledAddons import com.nuvio.app.features.catalog.supportsPagination @@ -17,7 +19,21 @@ data class HomeCatalogDefinition( val type: String, val catalogId: String, val supportsPagination: Boolean, -) + val descriptorSignature: String, +) { + val cacheKey: String + get() = "$key|$descriptorSignature" +} + +fun buildHomeCatalogRefreshSignature(addons: List): List = + addons.enabledAddons().mapNotNull { addon -> + val manifest = addon.manifest ?: return@mapNotNull null + addon to manifest + }.flatMap { (addon, manifest) -> + manifest.catalogs.map { catalog -> + buildHomeCatalogDescriptorSignature(addon, manifest, catalog) + } + }.sorted() fun buildHomeCatalogDefinitions(addons: List): List = addons.enabledAddons().mapNotNull { addon -> @@ -41,8 +57,68 @@ fun buildHomeCatalogDefinitions(addons: List): List + listOf( + resource.name, + resource.types.joinToString("/"), + resource.idPrefixes.joinToString("/"), + ).joinToString(":") + }) + append('|') + append( + listOf( + manifest.behaviorHints.configurable, + manifest.behaviorHints.configurationRequired, + manifest.behaviorHints.adult, + manifest.behaviorHints.p2p, + ).joinToString(":"), + ) + append('|') + append(catalog.type) + append('|') + append(catalog.id) + append('|') + append(catalog.name) + append('|') + append(catalog.supportsPagination()) + append('|') + append(catalog.extra.joinToString(",") { extra -> + listOf( + extra.name, + extra.isRequired.toString(), + extra.options.joinToString("/"), + extra.optionsLimit?.toString().orEmpty(), + ).joinToString(":") + }) + } + internal fun String.displayLabel(): String = localizedMediaTypeLabel(this) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeRepository.kt index e0711eb12..46dcc2333 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeRepository.kt @@ -47,15 +47,15 @@ object HomeRepository { val activeAddons = addons.enabledAddons() val requests = buildHomeCatalogDefinitions(activeAddons) currentDefinitions = requests - val requestKeys = requests.mapTo(mutableSetOf(), HomeCatalogDefinition::key) - cachedSections = cachedSections.filterKeys(requestKeys::contains) + val requestCacheKeys = requests.mapTo(mutableSetOf(), HomeCatalogDefinition::cacheKey) + cachedSections = cachedSections.filterKeys(requestCacheKeys::contains) val requestKey = requests.joinToString(separator = "|") { request -> - "${request.manifestUrl}:${request.type}:${request.catalogId}" + request.cacheKey } if (!force && activeRequestKey == requestKey && _uiState.value.isLoading) return - if (!force && requestKey == lastRequestKey && requestKeys.all(cachedSections::containsKey)) { + if (!force && requestKey == lastRequestKey && requestCacheKeys.all(cachedSections::containsKey)) { if (_uiState.value.sections.isEmpty() || _uiState.value.heroItems.isEmpty()) { applyCurrentSettings() } @@ -90,7 +90,7 @@ object HomeRepository { snapshot = HomeCatalogSettingsRepository.snapshot(), ) val pendingRequests = prioritizedRequests.filter { definition -> - force || cachedSections[definition.key] == null + force || cachedSections[definition.cacheKey] == null } if (pendingRequests.isEmpty()) { publishCurrentState( @@ -108,16 +108,20 @@ object HomeRepository { pendingRequests.chunked(HOME_CATALOG_FETCH_BATCH_SIZE).forEach { batch -> if (activeRequestKey != requestKey) return@launch val results = batch.map { request -> - async { runCatching { request.toSection() } } + async { request to runCatching { request.toSection() } } }.awaitAll() if (activeRequestKey != requestKey) return@launch - results.mapNotNull { it.getOrNull() }.forEach { section -> - loadedSections[section.key] = section + results.mapNotNull { (request, result) -> + result.getOrNull()?.let { section -> request.cacheKey to section } + }.forEach { (cacheKey, section) -> + loadedSections[cacheKey] = section } if (firstErrorMessage == null) { - firstErrorMessage = results.firstNotNullOfOrNull { it.exceptionOrNull()?.message } + firstErrorMessage = results.firstNotNullOfOrNull { (_, result) -> + result.exceptionOrNull()?.message + } } cachedSections = loadedSections.toMap() lastErrorMessage = firstErrorMessage @@ -190,7 +194,7 @@ object HomeRepository { val preference = preferences[definition.key] if (preference?.enabled == false) return@mapNotNull null - val section = cachedSections[definition.key]?.withReleaseFilter() ?: return@mapNotNull null + val section = cachedSections[definition.cacheKey]?.withReleaseFilter() ?: return@mapNotNull null if (section.items.isEmpty()) return@mapNotNull null val customTitle = preference?.customTitle.orEmpty() section.copy( @@ -202,7 +206,7 @@ object HomeRepository { val heroRandom = Random((requestKey?.hashCode() ?: 0).absoluteValue + 1) currentDefinitions .filter { definition -> preferences[definition.key]?.heroSourceEnabled != false } - .mapNotNull { definition -> cachedSections[definition.key] } + .mapNotNull { definition -> cachedSections[definition.cacheKey] } .map { section -> section.withReleaseFilter() } .flatMap { section -> section.items } .distinctBy { item -> "${item.type}:${item.id}" } diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt index 917700ab2..325288874 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt @@ -433,18 +433,8 @@ fun HomeScreen( .sorted() } - val catalogRefreshKey = remember(availableManifests) { - availableManifests - .map { manifest -> - buildString { - append(manifest.transportUrl) - append(':') - append(manifest.catalogs.joinToString(separator = ",") { catalog -> - "${catalog.type}:${catalog.id}:${catalog.extra.count { it.isRequired }}" - }) - } - } - .sorted() + val catalogRefreshKey = remember(enabledAddons) { + buildHomeCatalogRefreshSignature(enabledAddons) } LaunchedEffect(catalogRefreshKey) {