Reduce recomposition of MangaHeader (#9985)
* Reduce recomposition of MangaHeader * Reuse `Modifier` for `Tags` Reference: https://developer.android.com/jetpack/compose/modifiers#reusing-modifiers * Don't recalculate Read State on recomposition * Fix Linting issue * Optimize chapter state calculations (cherry picked from commit 78aa50bb350b0142a3e0407b3d2f6084b9c1a835) # Conflicts: # app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt # app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt
This commit is contained in:
parent
c2488c41a2
commit
1aa2ad1e9c
@ -335,8 +335,14 @@ private fun MangaScreenSmallImpl(
|
||||
val metadataDescription = metadataDescription(state.source)
|
||||
// SY <--
|
||||
|
||||
val isAnySelected by remember {
|
||||
derivedStateOf {
|
||||
chapters.fastAny { it.selected }
|
||||
}
|
||||
}
|
||||
|
||||
val internalOnBackPressed = {
|
||||
if (chapters.fastAny { it.selected }) {
|
||||
if (isAnySelected) {
|
||||
onAllChapterSelected(false)
|
||||
} else {
|
||||
onBackClicked()
|
||||
@ -346,17 +352,22 @@ private fun MangaScreenSmallImpl(
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
val firstVisibleItemIndex by remember {
|
||||
derivedStateOf { chapterListState.firstVisibleItemIndex }
|
||||
val selectedChapterCount: Int = remember(chapters) {
|
||||
chapters.count { it.selected }
|
||||
}
|
||||
val firstVisibleItemScrollOffset by remember {
|
||||
derivedStateOf { chapterListState.firstVisibleItemScrollOffset }
|
||||
val isFirstItemVisible by remember {
|
||||
derivedStateOf { chapterListState.firstVisibleItemIndex == 0 }
|
||||
}
|
||||
val isFirstItemScrolled by remember {
|
||||
derivedStateOf { chapterListState.firstVisibleItemScrollOffset > 0 }
|
||||
}
|
||||
val animatedTitleAlpha by animateFloatAsState(
|
||||
if (firstVisibleItemIndex > 0) 1f else 0f,
|
||||
if (!isFirstItemVisible) 1f else 0f,
|
||||
label = "Top Bar Title",
|
||||
)
|
||||
val animatedBgAlpha by animateFloatAsState(
|
||||
if (firstVisibleItemIndex > 0 || firstVisibleItemScrollOffset > 0) 1f else 0f,
|
||||
if (!isFirstItemVisible || isFirstItemScrolled) 1f else 0f,
|
||||
label = "Top Bar Background",
|
||||
)
|
||||
MangaToolbar(
|
||||
title = state.manga.title,
|
||||
@ -376,14 +387,17 @@ private fun MangaScreenSmallImpl(
|
||||
onClickMergedSettings = onMergedSettingsClicked.takeIf { state.manga.source == MERGED_SOURCE_ID },
|
||||
onClickMerge = onMergeClicked.takeIf { state.showMergeInOverflow },
|
||||
// SY <--
|
||||
actionModeCounter = chapters.count { it.selected },
|
||||
actionModeCounter = selectedChapterCount,
|
||||
onSelectAll = { onAllChapterSelected(true) },
|
||||
onInvertSelection = { onInvertSelection() },
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
val selectedChapters = remember(chapters) {
|
||||
chapters.filter { it.selected }
|
||||
}
|
||||
SharedMangaBottomActionMenu(
|
||||
selected = chapters.filter { it.selected },
|
||||
selected = selectedChapters,
|
||||
onMultiBookmarkClicked = onMultiBookmarkClicked,
|
||||
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
|
||||
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
|
||||
@ -394,19 +408,20 @@ private fun MangaScreenSmallImpl(
|
||||
},
|
||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||
floatingActionButton = {
|
||||
val isFABVisible = remember(chapters) {
|
||||
chapters.fastAny { !it.chapter.read } && !isAnySelected
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = chapters.fastAny { !it.chapter.read } && chapters.fastAll { !it.selected },
|
||||
visible = isFABVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
ExtendedFloatingActionButton(
|
||||
text = {
|
||||
val id = if (state.chapters.fastAny { it.chapter.read }) {
|
||||
R.string.action_resume
|
||||
} else {
|
||||
R.string.action_start
|
||||
val isReading = remember(state.chapters) {
|
||||
state.chapters.fastAny { it.chapter.read }
|
||||
}
|
||||
Text(text = stringResource(id))
|
||||
Text(text = stringResource(if (isReading) R.string.action_resume else R.string.action_start))
|
||||
},
|
||||
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
|
||||
onClick = onContinueReading,
|
||||
@ -420,7 +435,7 @@ private fun MangaScreenSmallImpl(
|
||||
PullRefresh(
|
||||
refreshing = state.isRefreshingData,
|
||||
onRefresh = onRefresh,
|
||||
enabled = chapters.fastAll { !it.selected },
|
||||
enabled = !isAnySelected,
|
||||
indicatorPadding = WindowInsets.systemBars.only(WindowInsetsSides.Top).asPaddingValues(),
|
||||
) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
@ -546,10 +561,13 @@ private fun MangaScreenSmallImpl(
|
||||
key = MangaScreenItem.CHAPTER_HEADER,
|
||||
contentType = MangaScreenItem.CHAPTER_HEADER,
|
||||
) {
|
||||
val missingChapterCount = remember(chapters) {
|
||||
chapters.map { it.chapter.chapterNumber }.missingChaptersCount()
|
||||
}
|
||||
ChapterHeader(
|
||||
enabled = chapters.fastAll { !it.selected },
|
||||
enabled = !isAnySelected,
|
||||
chapterCount = chapters.size,
|
||||
missingChapterCount = chapters.map { it.chapter.chapterNumber }.missingChaptersCount(),
|
||||
missingChapterCount = missingChapterCount,
|
||||
onClick = onFilterClicked,
|
||||
)
|
||||
}
|
||||
@ -640,6 +658,12 @@ fun MangaScreenLargeImpl(
|
||||
|
||||
val chapters = remember(state) { state.processedChapters }
|
||||
|
||||
val isAnySelected by remember {
|
||||
derivedStateOf {
|
||||
chapters.fastAny { it.selected }
|
||||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
val metadataDescription = metadataDescription(state.source)
|
||||
// SY <--
|
||||
@ -649,7 +673,7 @@ fun MangaScreenLargeImpl(
|
||||
PullRefresh(
|
||||
refreshing = state.isRefreshingData,
|
||||
onRefresh = onRefresh,
|
||||
enabled = chapters.fastAll { !it.selected },
|
||||
enabled = !isAnySelected,
|
||||
indicatorPadding = PaddingValues(
|
||||
start = insetPadding.calculateStartPadding(layoutDirection),
|
||||
top = with(density) { topBarHeight.toDp() },
|
||||
@ -659,7 +683,7 @@ fun MangaScreenLargeImpl(
|
||||
val chapterListState = rememberLazyListState()
|
||||
|
||||
val internalOnBackPressed = {
|
||||
if (chapters.fastAny { it.selected }) {
|
||||
if (isAnySelected) {
|
||||
onAllChapterSelected(false)
|
||||
} else {
|
||||
onBackClicked()
|
||||
@ -669,10 +693,13 @@ fun MangaScreenLargeImpl(
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
val selectedChapterCount = remember(chapters) {
|
||||
chapters.count { it.selected }
|
||||
}
|
||||
MangaToolbar(
|
||||
modifier = Modifier.onSizeChanged { topBarHeight = it.height },
|
||||
title = state.manga.title,
|
||||
titleAlphaProvider = { if (chapters.fastAny { it.selected }) 1f else 0f },
|
||||
titleAlphaProvider = { if (isAnySelected) 1f else 0f },
|
||||
backgroundAlphaProvider = { 1f },
|
||||
hasFilters = state.manga.chaptersFiltered(),
|
||||
onBackClicked = internalOnBackPressed,
|
||||
@ -688,7 +715,7 @@ fun MangaScreenLargeImpl(
|
||||
onClickMergedSettings = onMergedSettingsClicked.takeIf { state.manga.source == MERGED_SOURCE_ID },
|
||||
onClickMerge = onMergeClicked.takeIf { state.showMergeInOverflow },
|
||||
// SY <--
|
||||
actionModeCounter = chapters.count { it.selected },
|
||||
actionModeCounter = selectedChapterCount,
|
||||
onSelectAll = { onAllChapterSelected(true) },
|
||||
onInvertSelection = { onInvertSelection() },
|
||||
)
|
||||
@ -698,8 +725,11 @@ fun MangaScreenLargeImpl(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.BottomEnd,
|
||||
) {
|
||||
val selectedChapters = remember(chapters) {
|
||||
chapters.filter { it.selected }
|
||||
}
|
||||
SharedMangaBottomActionMenu(
|
||||
selected = chapters.filter { it.selected },
|
||||
selected = selectedChapters,
|
||||
onMultiBookmarkClicked = onMultiBookmarkClicked,
|
||||
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
|
||||
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
|
||||
@ -711,19 +741,20 @@ fun MangaScreenLargeImpl(
|
||||
},
|
||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
|
||||
floatingActionButton = {
|
||||
val isFABVisible = remember(chapters) {
|
||||
chapters.fastAny { !it.chapter.read } && !isAnySelected
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = chapters.fastAny { !it.chapter.read } && chapters.fastAll { !it.selected },
|
||||
visible = isFABVisible,
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
ExtendedFloatingActionButton(
|
||||
text = {
|
||||
val id = if (state.chapters.fastAny { it.chapter.read }) {
|
||||
R.string.action_resume
|
||||
} else {
|
||||
R.string.action_start
|
||||
val isReading = remember(state.chapters) {
|
||||
state.chapters.fastAny { it.chapter.read }
|
||||
}
|
||||
Text(text = stringResource(id))
|
||||
Text(text = stringResource(if (isReading) R.string.action_resume else R.string.action_start))
|
||||
},
|
||||
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
|
||||
onClick = onContinueReading,
|
||||
@ -828,10 +859,13 @@ fun MangaScreenLargeImpl(
|
||||
key = MangaScreenItem.CHAPTER_HEADER,
|
||||
contentType = MangaScreenItem.CHAPTER_HEADER,
|
||||
) {
|
||||
val missingChapterCount = remember(chapters) {
|
||||
chapters.map { it.chapter.chapterNumber }.missingChaptersCount()
|
||||
}
|
||||
ChapterHeader(
|
||||
enabled = chapters.fastAll { !it.selected },
|
||||
enabled = !isAnySelected,
|
||||
chapterCount = chapters.size,
|
||||
missingChapterCount = chapters.map { it.chapter.chapterNumber }.missingChaptersCount(),
|
||||
missingChapterCount = missingChapterCount,
|
||||
onClick = onFilterButtonClicked,
|
||||
)
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ fun ExpandableMangaDescription(
|
||||
) {
|
||||
tags.forEach {
|
||||
TagsChip(
|
||||
modifier = Modifier.padding(vertical = 4.dp),
|
||||
modifier = DefaultTagChipModifier,
|
||||
text = it,
|
||||
onClick = {
|
||||
tagSelected = it
|
||||
@ -339,7 +339,7 @@ fun ExpandableMangaDescription(
|
||||
) {
|
||||
items(items = tags) {
|
||||
TagsChip(
|
||||
modifier = Modifier.padding(vertical = 4.dp),
|
||||
modifier = DefaultTagChipModifier,
|
||||
text = it,
|
||||
onClick = {
|
||||
tagSelected = it
|
||||
@ -691,6 +691,8 @@ private fun MangaSummary(
|
||||
}
|
||||
}
|
||||
|
||||
private val DefaultTagChipModifier = Modifier.padding(vertical = 4.dp)
|
||||
|
||||
@Composable
|
||||
private fun RowScope.MangaActionButton(
|
||||
title: String,
|
||||
|
Loading…
x
Reference in New Issue
Block a user