Bladeren bron

Library category page performance fixes (#7650)

* Don't compose category page unnecessarily

* Remove unnecessary library pager recompose

Defer and remember the "currentPage" state read since it's only needed when the
pager is composed for the first time.

* Badge opts

* Sync text style with previous impl

Also avoid reallocating by using copy
Ivan Iskandar 2 jaren geleden
bovenliggende
commit
d49ec41f3a

+ 9 - 14
app/src/main/java/eu/kanade/presentation/components/Badges.kt

@@ -1,12 +1,10 @@
 package eu.kanade.presentation.components
 
 import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.LocalTextStyle
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
@@ -36,18 +34,15 @@ fun Badge(
     textColor: Color = MaterialTheme.colorScheme.onSecondary,
     shape: Shape = RectangleShape,
 ) {
-    Box(
+    Text(
+        text = text,
         modifier = Modifier
             .clip(shape)
-            .background(color),
-    ) {
-        Text(
-            text = text,
-            modifier = Modifier.padding(horizontal = 4.dp, vertical = 2.dp),
-            style = LocalTextStyle.current.copy(
-                color = textColor,
-                fontWeight = FontWeight.Medium,
-            ),
-        )
-    }
+            .background(color)
+            .padding(horizontal = 3.dp, vertical = 1.dp),
+        color = textColor,
+        fontWeight = FontWeight.Medium,
+        maxLines = 1,
+        style = MaterialTheme.typography.bodySmall,
+    )
 }

+ 2 - 2
app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt

@@ -61,8 +61,8 @@ fun LibraryScreen(
                 LibraryContent(
                     state = presenter,
                     contentPadding = paddingValues,
-                    currentPage = presenter.activeCategory,
-                    isLibraryEmpty = presenter.loadedManga.isEmpty(),
+                    currentPage = { presenter.activeCategory },
+                    isLibraryEmpty = { presenter.loadedManga.isEmpty() },
                     showPageTabs = presenter.tabVisibility,
                     showMangaCount = presenter.mangaCountVisibility,
                     onChangeCurrentPage = { presenter.activeCategory = it },

+ 4 - 3
app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt

@@ -4,12 +4,12 @@ import androidx.compose.foundation.combinedClickable
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.grid.items
-import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import eu.kanade.domain.manga.model.MangaCover
 import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.ui.library.LibraryItem
@@ -81,8 +81,9 @@ fun LibraryComfortableGridItem(
             Text(
                 modifier = Modifier.padding(4.dp),
                 text = manga.title,
+                fontSize = 12.sp,
                 maxLines = 2,
-                style = LocalTextStyle.current.copy(fontWeight = FontWeight.SemiBold),
+                style = MaterialTheme.typography.titleSmall,
             )
         }
     }

+ 5 - 5
app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt

@@ -8,7 +8,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.grid.items
 import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
@@ -17,8 +17,8 @@ import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shadow
-import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.ui.library.LibraryItem
 
@@ -102,10 +102,10 @@ fun LibraryCompactGridItem(
             modifier = Modifier
                 .padding(8.dp)
                 .align(Alignment.BottomStart),
+            color = Color.White,
+            fontSize = 12.sp,
             maxLines = 2,
-            style = LocalTextStyle.current.copy(
-                color = Color.White,
-                fontWeight = FontWeight.SemiBold,
+            style = MaterialTheme.typography.titleSmall.copy(
                 shadow = Shadow(
                     color = Color.Black,
                     blurRadius = 4f,

+ 9 - 7
app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt

@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.State
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalUriHandler
 import com.google.accompanist.pager.rememberPagerState
@@ -26,8 +27,8 @@ import eu.kanade.tachiyomi.widget.EmptyView
 fun LibraryContent(
     state: LibraryState,
     contentPadding: PaddingValues,
-    currentPage: Int,
-    isLibraryEmpty: Boolean,
+    currentPage: () -> Int,
+    isLibraryEmpty: () -> Boolean,
     isDownloadOnly: Boolean,
     isIncognitoMode: Boolean,
     showPageTabs: Boolean,
@@ -42,12 +43,13 @@ fun LibraryContent(
     getColumnsForOrientation: (Boolean) -> PreferenceMutableState<Int>,
     getLibraryForPage: @Composable (Int) -> State<List<LibraryItem>>,
 ) {
-    val categories = state.categories
-    val pagerState = rememberPagerState(currentPage.coerceAtMost(categories.lastIndex))
-
     Column(
         modifier = Modifier.padding(contentPadding),
     ) {
+        val categories = state.categories
+        val coercedCurrentPage = remember { currentPage().coerceAtMost(categories.lastIndex) }
+        val pagerState = rememberPagerState(coercedCurrentPage)
+
         if (showPageTabs && categories.size > 1) {
             LibraryTabs(
                 state = pagerState,
@@ -72,7 +74,7 @@ fun LibraryContent(
 
         SwipeRefresh(
             state = rememberSwipeRefreshState(isRefreshing = false),
-            onRefresh = { onRefresh(categories[currentPage]) },
+            onRefresh = { onRefresh(categories[currentPage()]) },
             indicator = { s, trigger ->
                 SwipeRefreshIndicator(
                     state = s,
@@ -80,7 +82,7 @@ fun LibraryContent(
                 )
             },
         ) {
-            if (state.searchQuery.isNullOrEmpty() && isLibraryEmpty) {
+            if (state.searchQuery.isNullOrEmpty() && isLibraryEmpty()) {
                 val handler = LocalUriHandler.current
                 EmptyScreen(
                     R.string.information_empty_library,

+ 35 - 32
app/src/main/java/eu/kanade/presentation/library/components/LibraryGridCover.kt

@@ -36,40 +36,43 @@ fun LibraryGridCover(
             data = mangaCover,
         )
         content()
-        BadgeGroup(
-            modifier = Modifier
-                .padding(4.dp)
-                .align(Alignment.TopStart),
-        ) {
-            if (downloadCount > 0) {
-                Badge(
-                    text = "$downloadCount",
-                    color = MaterialTheme.colorScheme.tertiary,
-                    textColor = MaterialTheme.colorScheme.onTertiary,
-                )
-            }
-            if (unreadCount > 0) {
-                Badge(text = "$unreadCount")
+        if (downloadCount > 0 || unreadCount > 0) {
+            BadgeGroup(
+                modifier = Modifier
+                    .padding(4.dp)
+                    .align(Alignment.TopStart),
+            ) {
+                if (downloadCount > 0) {
+                    Badge(
+                        text = "$downloadCount",
+                        color = MaterialTheme.colorScheme.tertiary,
+                        textColor = MaterialTheme.colorScheme.onTertiary,
+                    )
+                }
+                if (unreadCount > 0) {
+                    Badge(text = "$unreadCount")
+                }
             }
         }
-        BadgeGroup(
-            modifier = Modifier
-                .padding(4.dp)
-                .align(Alignment.TopEnd),
-        ) {
-            if (isLocal) {
-                Badge(
-                    text = stringResource(R.string.local_source_badge),
-                    color = MaterialTheme.colorScheme.tertiary,
-                    textColor = MaterialTheme.colorScheme.onTertiary,
-                )
-            }
-            if (isLocal.not() && language.isNotEmpty()) {
-                Badge(
-                    text = language,
-                    color = MaterialTheme.colorScheme.tertiary,
-                    textColor = MaterialTheme.colorScheme.onTertiary,
-                )
+        if (isLocal || language.isNotEmpty()) {
+            BadgeGroup(
+                modifier = Modifier
+                    .padding(4.dp)
+                    .align(Alignment.TopEnd),
+            ) {
+                if (isLocal) {
+                    Badge(
+                        text = stringResource(R.string.local_source_badge),
+                        color = MaterialTheme.colorScheme.tertiary,
+                        textColor = MaterialTheme.colorScheme.onTertiary,
+                    )
+                } else if (language.isNotEmpty()) {
+                    Badge(
+                        text = language,
+                        color = MaterialTheme.colorScheme.tertiary,
+                        textColor = MaterialTheme.colorScheme.onTertiary,
+                    )
+                }
             }
         }
     }

+ 4 - 0
app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt

@@ -36,6 +36,10 @@ fun LibraryPager(
         state = state,
         verticalAlignment = Alignment.Top,
     ) { page ->
+        if (page !in ((state.currentPage - 1)..(state.currentPage + 1))) {
+            // To make sure only one offscreen page is being composed
+            return@HorizontalPager
+        }
         val library by getLibraryForPage(page)
         val displayMode by getDisplayModeForPage(page)
         val columns by if (displayMode != DisplayModeSetting.LIST) {