Added suffix when there is addons with the same names

This commit is contained in:
CrissZollo 2026-02-15 14:50:49 +01:00
parent d593ec0f29
commit 2109ebaf3f
No known key found for this signature in database
12 changed files with 41 additions and 18 deletions

View file

@ -92,7 +92,7 @@ class AddonRepositoryImpl @Inject constructor(
// Emit cached addons immediately (now includes disk-persisted cache)
val cached = urls.mapNotNull { manifestCache[it.trimEnd('/')] }
if (cached.isNotEmpty()) {
emit(cached)
emit(applyDisplayNames(cached))
}
val fresh = coroutineScope {
@ -107,7 +107,7 @@ class AddonRepositoryImpl @Inject constructor(
}
if (fresh != cached) {
emit(fresh)
emit(applyDisplayNames(fresh))
}
}.flowOn(Dispatchers.IO)
}
@ -145,4 +145,26 @@ class AddonRepositoryImpl @Inject constructor(
preferences.setAddonOrder(urls)
triggerRemoteSync()
}
private fun applyDisplayNames(addons: List<Addon>): List<Addon> {
val nameCounts = mutableMapOf<String, Int>()
for (addon in addons) {
nameCounts[addon.name] = (nameCounts[addon.name] ?: 0) + 1
}
val nameCounters = mutableMapOf<String, Int>()
return addons.map { addon ->
if ((nameCounts[addon.name] ?: 0) <= 1) {
addon.copy(displayName = addon.name)
} else {
val occurrence = (nameCounters[addon.name] ?: 0) + 1
nameCounters[addon.name] = occurrence
if (occurrence == 1) {
addon.copy(displayName = addon.name)
} else {
addon.copy(displayName = "${addon.name} ($occurrence)")
}
}
}
}
}

View file

@ -74,7 +74,7 @@ class StreamRepositoryImpl @Inject constructor(
if (streamsResult.data.isNotEmpty()) {
resultChannel.send(
AddonStreams(
addonName = addon.name,
addonName = addon.displayName,
addonLogo = addon.logo,
streams = streamsResult.data
)
@ -253,7 +253,7 @@ class StreamRepositoryImpl @Inject constructor(
// First, get addon info for name and logo
val addonResult = addonRepository.fetchAddon(baseUrl)
val addonName = when (addonResult) {
is NetworkResult.Success -> addonResult.data.name
is NetworkResult.Success -> addonResult.data.displayName
else -> "Unknown"
}
val addonLogo = when (addonResult) {

View file

@ -123,7 +123,7 @@ class SubtitleRepositoryImpl @Inject constructor(
id = dto.id ?: "${dto.lang}-${dto.url.hashCode()}",
url = dto.url,
lang = dto.lang,
addonName = addon.name,
addonName = addon.displayName,
addonLogo = addon.logo
)
} ?: emptyList()

View file

@ -6,6 +6,7 @@ import androidx.compose.runtime.Immutable
data class Addon(
val id: String,
val name: String,
val displayName: String = name,
val version: String,
val description: String?,
val logo: String?,

View file

@ -876,7 +876,7 @@ private fun AddonCard(
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = addon.name,
text = addon.displayName,
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold),
color = NuvioColors.TextPrimary
)

View file

@ -169,7 +169,7 @@ class AddonManagerViewModel @Inject constructor(
addons = addons.map { addon ->
AddonConfigServer.AddonInfo(
url = addon.baseUrl,
name = addon.name.ifBlank { addon.baseUrl },
name = addon.displayName.ifBlank { addon.baseUrl },
description = addon.description
)
},
@ -304,7 +304,7 @@ class AddonManagerViewModel @Inject constructor(
val catalogsReordered = resolvedProposedCatalogOrderKeys != currentCatalogEntries.map { it.key }
val removedNameMap = _uiState.value.installedAddons
.associateBy({ normalizeUrlForComparison(it.baseUrl) }, { it.name })
.associateBy({ normalizeUrlForComparison(it.baseUrl) }, { it.displayName })
val removedNames = removed.associateWith { url ->
removedNameMap[normalizeUrlForComparison(url)] ?: url
}
@ -508,7 +508,7 @@ class AddonManagerViewModel @Inject constructor(
catalogName = catalog.name
),
catalogName = catalog.name,
addonName = addon.name,
addonName = addon.displayName,
typeLabel = catalog.apiType
)
)

View file

@ -147,7 +147,7 @@ class CatalogOrderViewModel @Inject constructor(
catalogName = catalog.name
),
catalogName = catalog.name,
addonName = addon.name,
addonName = addon.displayName,
typeLabel = catalog.apiType
)
)

View file

@ -496,7 +496,7 @@ class HomeViewModel @Inject constructor(
catalogRepository.getCatalog(
addonBaseUrl = addon.baseUrl,
addonId = addon.id,
addonName = addon.name,
addonName = addon.displayName,
catalogId = catalog.id,
catalogName = catalog.name,
type = catalog.apiType,
@ -552,7 +552,7 @@ class HomeViewModel @Inject constructor(
catalogRepository.getCatalog(
addonBaseUrl = addon.baseUrl,
addonId = addon.id,
addonName = addon.name,
addonName = addon.displayName,
catalogId = catalogId,
catalogName = currentRow.catalogName,
type = currentRow.apiType,

View file

@ -220,7 +220,7 @@ class SearchViewModel @Inject constructor(
catalogRepository.getCatalog(
addonBaseUrl = addon.baseUrl,
addonId = addon.id,
addonName = addon.name,
addonName = addon.displayName,
catalogId = catalog.id,
catalogName = catalog.name,
type = catalog.apiType,
@ -275,7 +275,7 @@ class SearchViewModel @Inject constructor(
catalogRepository.getCatalog(
addonBaseUrl = addon.baseUrl,
addonId = addon.id,
addonName = addon.name,
addonName = addon.displayName,
catalogId = catalogId,
catalogName = currentRow.catalogName,
type = currentRow.apiType,
@ -331,7 +331,7 @@ class SearchViewModel @Inject constructor(
DiscoverCatalog(
key = "${addon.id}_${catalog.apiType}_${catalog.id}",
addonId = addon.id,
addonName = addon.name,
addonName = addon.displayName,
addonBaseUrl = addon.baseUrl,
catalogId = catalog.id,
catalogName = catalog.name,

View file

@ -304,7 +304,7 @@ class LayoutSettingsViewModel @Inject constructor(
CatalogInfo(
key = "${addon.id}_${catalog.apiType}_${catalog.id}",
name = catalog.name,
addonName = addon.name
addonName = addon.displayName
)
}
}

View file

@ -34,7 +34,7 @@ class PlaybackSettingsViewModel @Inject constructor(
resource.name.equals("stream", ignoreCase = true)
}
}
.map { it.name }
.map { it.displayName }
.distinct()
.sorted()
}

View file

@ -138,7 +138,7 @@ class StreamScreenViewModel @Inject constructor(
_uiState.update { it.copy(isLoading = true, error = null) }
val installedAddons = addonRepository.getInstalledAddons().first()
val installedAddonOrder = installedAddons.map { it.name }
val installedAddonOrder = installedAddons.map { it.displayName }
streamRepository.getStreamsFromAllAddons(
type = contentType,