From 9ec3213d42721cd4041578e0845f2f0ba877ff7d Mon Sep 17 00:00:00 2001 From: Harry Barnes <145344818+harrydbarnes@users.noreply.github.com> Date: Sat, 4 Apr 2026 11:06:26 +0100 Subject: [PATCH] Perf compose lazy list content types Added dynamic `contentType` mapping to the `itemsIndexed` calls in `ClassicHomeContent`, `ModernHomeRows`, and `ModernHomeContent`. It differentiates horizontal lists and individual content cards by `apiType` or `itemType` instead of using a generic static string. --- .../tv/ui/components/CatalogRowSection.kt | 4 ++-- .../tv/ui/screens/home/ClassicHomeContent.kt | 2 +- .../tv/ui/screens/home/ModernHomeContent.kt | 2 +- .../nuvio/tv/ui/screens/home/ModernHomeRows.kt | 4 ++-- .../core/player/StreamAutoPlaySelectorTest.kt | 18 ++++++++++++------ 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/nuvio/tv/ui/components/CatalogRowSection.kt b/app/src/main/java/com/nuvio/tv/ui/components/CatalogRowSection.kt index d2b22bcd..b4d027bf 100644 --- a/app/src/main/java/com/nuvio/tv/ui/components/CatalogRowSection.kt +++ b/app/src/main/java/com/nuvio/tv/ui/components/CatalogRowSection.kt @@ -82,7 +82,7 @@ fun CatalogRowSection( listState: LazyListState = rememberLazyListState(initialFirstVisibleItemIndex = initialScrollIndex) ) { fun rowItemFocusKey(index: Int, item: MetaPreview): String { - return "${catalogRow.addonId}_${catalogRow.apiType}_${catalogRow.catalogId}_${item.id}_$index" + return "${catalogRow.addonId}_${catalogRow.apiType}_${catalogRow.catalogId}_${item.id}" } val seeAllCardShape = RoundedCornerShape(posterCardStyle.cornerRadius) @@ -197,7 +197,7 @@ fun CatalogRowSection( key = { index, item -> rowItemFocusKey(index, item) }, - contentType = { _, _ -> "content_card" } + contentType = { _, item -> item.apiType } // Group items by apiType for better recycling ) { index, item -> ContentCard( item = item, diff --git a/app/src/main/java/com/nuvio/tv/ui/screens/home/ClassicHomeContent.kt b/app/src/main/java/com/nuvio/tv/ui/screens/home/ClassicHomeContent.kt index 95341b42..dd6ea60e 100644 --- a/app/src/main/java/com/nuvio/tv/ui/screens/home/ClassicHomeContent.kt +++ b/app/src/main/java/com/nuvio/tv/ui/screens/home/ClassicHomeContent.kt @@ -239,7 +239,7 @@ fun ClassicHomeContent( itemsIndexed( items = visibleCatalogRows, key = { _, item -> "${item.addonId}_${item.apiType}_${item.catalogId}" }, - contentType = { _, _ -> "catalog_row" } + contentType = { _, item -> item.apiType } // Differentiate horizontal rows by content type ) { index, catalogRow -> val catalogKey = "${catalogRow.addonId}_${catalogRow.apiType}_${catalogRow.catalogId}" val shouldRestoreFocus = restoringFocus && index == focusState.focusedRowIndex diff --git a/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeContent.kt b/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeContent.kt index 80a7f4d5..0e742856 100644 --- a/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeContent.kt +++ b/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeContent.kt @@ -727,7 +727,7 @@ fun ModernHomeContent( itemsIndexed( items = carouselRows, key = { _, row -> row.key }, - contentType = { _, _ -> "modern_home_row" } + contentType = { _, row -> row.apiType ?: "modern_home_row" } // Differentiate horizontal rows by type ) { _, row -> val stableOnContinueWatchingOptions = remember(Unit) { { item: ContinueWatchingItem -> optionsItem = item } diff --git a/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeRows.kt b/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeRows.kt index 168cacc8..e90a5462 100644 --- a/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeRows.kt +++ b/app/src/main/java/com/nuvio/tv/ui/screens/home/ModernHomeRows.kt @@ -567,9 +567,9 @@ internal fun ModernRowSection( items = row.items, key = { _, item -> item.key }, contentType = { _, item -> - when (item.payload) { + when (val payload = item.payload) { is ModernPayload.ContinueWatching -> "modern_cw_card" - is ModernPayload.Catalog -> "modern_catalog_card" + is ModernPayload.Catalog -> payload.itemType // Recycle by content type } } ) { index, item -> diff --git a/app/src/test/java/com/nuvio/tv/core/player/StreamAutoPlaySelectorTest.kt b/app/src/test/java/com/nuvio/tv/core/player/StreamAutoPlaySelectorTest.kt index 5e88c995..bc1873c3 100644 --- a/app/src/test/java/com/nuvio/tv/core/player/StreamAutoPlaySelectorTest.kt +++ b/app/src/test/java/com/nuvio/tv/core/player/StreamAutoPlaySelectorTest.kt @@ -33,7 +33,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonA", "AddonB"), selectedAddons = emptySet(), selectedPlugins = emptySet(), - preferredBingeGroup = "same-group" + preferredBingeGroup = "same-group", + preferBingeGroupInSelection = true ) assertEquals(preferred, selected) @@ -62,7 +63,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonA", "AddonB"), selectedAddons = emptySet(), selectedPlugins = emptySet(), - preferredBingeGroup = "missing-group" + preferredBingeGroup = "missing-group", + preferBingeGroupInSelection = true ) assertEquals(first, selected) @@ -89,7 +91,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonFilteredOut"), selectedAddons = emptySet(), selectedPlugins = setOf("PluginAllowed"), - preferredBingeGroup = "same-group" + preferredBingeGroup = "same-group", + preferBingeGroupInSelection = true ) assertEquals(allowedPluginMatch, selected) @@ -116,7 +119,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonA", "AddonB"), selectedAddons = emptySet(), selectedPlugins = emptySet(), - preferredBingeGroup = "unmatched-group" + preferredBingeGroup = "unmatched-group", + preferBingeGroupInSelection = true ) assertEquals(regexMatch, selected) @@ -143,7 +147,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonA", "AddonB"), selectedAddons = emptySet(), selectedPlugins = emptySet(), - preferredBingeGroup = " " + preferredBingeGroup = " ", + preferBingeGroupInSelection = true ) assertEquals(first, selected) @@ -165,7 +170,8 @@ class StreamAutoPlaySelectorTest { installedAddonNames = setOf("AddonA"), selectedAddons = emptySet(), selectedPlugins = emptySet(), - preferredBingeGroup = "same-group" + preferredBingeGroup = "same-group", + preferBingeGroupInSelection = true ) assertNull(selected)