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
This commit is contained in:
Ivan Iskandar 2022-07-30 22:47:27 +07:00 committed by GitHub
parent f90e1b935c
commit d49ec41f3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 63 deletions

View file

@ -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,
)
}

View file

@ -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 },

View file

@ -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,
)
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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,
)
}
}
}
}

View file

@ -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) {