Use upstream scaffold (#3834)
This commit is contained in:
@@ -2,22 +2,18 @@ package eu.kanade.tachiyomi.ui.home
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.material3.Badge
|
||||
import androidx.compose.material3.BadgedBox
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationRailItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteDefaults
|
||||
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteItem
|
||||
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
|
||||
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType
|
||||
import androidx.compose.material3.adaptive.navigationsuite.rememberNavigationSuiteScaffoldState
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -29,6 +25,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
@@ -52,9 +49,6 @@ import mihon.app.di.appGraph
|
||||
import soup.compose.material.motion.animation.materialFadeThroughIn
|
||||
import soup.compose.material.motion.animation.materialFadeThroughOut
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.NavigationBar
|
||||
import tachiyomi.presentation.core.components.material.NavigationRail
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.pluralStringResource
|
||||
|
||||
object HomeScreen : Screen() {
|
||||
@@ -86,52 +80,48 @@ object HomeScreen : Screen() {
|
||||
) { tabNavigator ->
|
||||
// Provide usable navigator to content screen
|
||||
CompositionLocalProvider(LocalNavigator provides navigator) {
|
||||
Scaffold(
|
||||
startBar = {
|
||||
if (isTabletUi()) {
|
||||
NavigationRail {
|
||||
TABS.fastForEach {
|
||||
NavigationRailItem(it)
|
||||
}
|
||||
}
|
||||
val tabletUi = isTabletUi()
|
||||
val navigationSuiteType = if (tabletUi) {
|
||||
NavigationSuiteType.NavigationRail
|
||||
} else {
|
||||
NavigationSuiteType.NavigationBar
|
||||
}
|
||||
val navigationSuiteState = rememberNavigationSuiteScaffoldState()
|
||||
LaunchedEffect(navigationSuiteState, tabletUi) {
|
||||
if (tabletUi) navigationSuiteState.show()
|
||||
showBottomNavEvent.receiveAsFlow().collectLatest { show ->
|
||||
if (tabletUi || show) {
|
||||
navigationSuiteState.show()
|
||||
} else {
|
||||
navigationSuiteState.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavigationSuiteScaffold(
|
||||
navigationSuiteType = navigationSuiteType,
|
||||
state = navigationSuiteState,
|
||||
navigationSuiteColors = NavigationSuiteDefaults.colors(
|
||||
navigationRailContainerColor = MaterialTheme.colorScheme
|
||||
.surfaceColorAtElevation(3.dp),
|
||||
),
|
||||
navigationItemVerticalArrangement = Arrangement.Center,
|
||||
navigationItems = {
|
||||
TABS.fastForEach { NavigationSuiteItem(it, navigationSuiteType) }
|
||||
},
|
||||
bottomBar = {
|
||||
if (!isTabletUi()) {
|
||||
val bottomNavVisible by produceState(initialValue = true) {
|
||||
showBottomNavEvent.receiveAsFlow().collectLatest { value = it }
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = bottomNavVisible,
|
||||
enter = expandVertically(),
|
||||
exit = shrinkVertically(),
|
||||
) {
|
||||
NavigationBar {
|
||||
TABS.fastForEach {
|
||||
NavigationBarItem(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
contentWindowInsets = WindowInsets(0),
|
||||
) { contentPadding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(contentPadding)
|
||||
.consumeWindowInsets(contentPadding),
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = tabNavigator.current,
|
||||
transitionSpec = {
|
||||
materialFadeThroughIn(
|
||||
initialScale = 1f,
|
||||
durationMillis = TabFadeDuration,
|
||||
) togetherWith materialFadeThroughOut(durationMillis = TabFadeDuration)
|
||||
},
|
||||
label = "tabContent",
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = tabNavigator.current,
|
||||
transitionSpec = {
|
||||
materialFadeThroughIn(initialScale = 1f, durationMillis = TabFadeDuration) togetherWith
|
||||
materialFadeThroughOut(durationMillis = TabFadeDuration)
|
||||
},
|
||||
label = "tabContent",
|
||||
) {
|
||||
tabNavigator.saveableState(key = "currentTab", it) {
|
||||
it.Content()
|
||||
}
|
||||
tabNavigator.saveableState(key = "currentTab", it) {
|
||||
it.Content()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,12 +166,16 @@ object HomeScreen : Screen() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RowScope.NavigationBarItem(tab: eu.kanade.presentation.util.Tab) {
|
||||
private fun NavigationSuiteItem(
|
||||
tab: eu.kanade.presentation.util.Tab,
|
||||
navigationSuiteType: NavigationSuiteType,
|
||||
) {
|
||||
val tabNavigator = LocalTabNavigator.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val scope = rememberCoroutineScope()
|
||||
val selected = tabNavigator.current::class == tab::class
|
||||
NavigationBarItem(
|
||||
NavigationSuiteItem(
|
||||
navigationSuiteType = navigationSuiteType,
|
||||
selected = selected,
|
||||
onClick = {
|
||||
if (!selected) {
|
||||
@@ -190,7 +184,12 @@ object HomeScreen : Screen() {
|
||||
scope.launch { tab.onReselect(navigator) }
|
||||
}
|
||||
},
|
||||
icon = { NavigationIconItem(tab) },
|
||||
icon = {
|
||||
Icon(
|
||||
painter = tab.options.icon!!,
|
||||
contentDescription = tab.options.title,
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(
|
||||
text = tab.options.title,
|
||||
@@ -199,93 +198,59 @@ object HomeScreen : Screen() {
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
alwaysShowLabel = true,
|
||||
badge = tabBadge(tab),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NavigationRailItem(tab: eu.kanade.presentation.util.Tab) {
|
||||
val tabNavigator = LocalTabNavigator.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
val scope = rememberCoroutineScope()
|
||||
val selected = tabNavigator.current::class == tab::class
|
||||
NavigationRailItem(
|
||||
selected = selected,
|
||||
onClick = {
|
||||
if (!selected) {
|
||||
tabNavigator.current = tab
|
||||
} else {
|
||||
scope.launch { tab.onReselect(navigator) }
|
||||
}
|
||||
},
|
||||
icon = { NavigationIconItem(tab) },
|
||||
label = {
|
||||
Text(
|
||||
text = tab.options.title,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
alwaysShowLabel = true,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NavigationIconItem(tab: eu.kanade.presentation.util.Tab) {
|
||||
private fun tabBadge(tab: eu.kanade.presentation.util.Tab): (@Composable () -> Unit)? {
|
||||
val context = LocalContext.current
|
||||
BadgedBox(
|
||||
badge = {
|
||||
when {
|
||||
tab is UpdatesTab -> {
|
||||
val count by produceState(initialValue = 0) {
|
||||
val pref = context.appGraph.libraryPreferences
|
||||
combine(
|
||||
pref.newShowUpdatesCount.changes(),
|
||||
pref.newUpdatesCount.changes(),
|
||||
) { show, count -> if (show) count else 0 }
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
if (count > 0) {
|
||||
Badge {
|
||||
val desc = pluralStringResource(
|
||||
MR.plurals.notification_chapters_generic,
|
||||
count = count,
|
||||
count,
|
||||
)
|
||||
Text(
|
||||
text = count.toString(),
|
||||
modifier = Modifier.semantics { contentDescription = desc },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
BrowseTab::class.isInstance(tab) -> {
|
||||
val count by produceState(initialValue = 0) {
|
||||
context.appGraph.sourcePreferences.extensionUpdatesCount.changes()
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
if (count > 0) {
|
||||
Badge {
|
||||
val desc = pluralStringResource(
|
||||
MR.plurals.update_check_notification_ext_updates,
|
||||
count = count,
|
||||
count,
|
||||
)
|
||||
Text(
|
||||
text = count.toString(),
|
||||
modifier = Modifier.semantics { contentDescription = desc },
|
||||
)
|
||||
}
|
||||
}
|
||||
val count by produceState(initialValue = 0, tab) {
|
||||
val graph = context.appGraph
|
||||
when (tab) {
|
||||
is UpdatesTab -> {
|
||||
combine(
|
||||
graph.libraryPreferences.newShowUpdatesCount.changes(),
|
||||
graph.libraryPreferences.newUpdatesCount.changes(),
|
||||
) { show, count ->
|
||||
if (show) count else 0
|
||||
}
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
painter = tab.options.icon!!,
|
||||
contentDescription = tab.options.title,
|
||||
)
|
||||
|
||||
is BrowseTab -> {
|
||||
graph.sourcePreferences.extensionUpdatesCount.changes()
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
|
||||
else -> value = 0
|
||||
}
|
||||
}
|
||||
if (count <= 0) return null
|
||||
return {
|
||||
Badge {
|
||||
val desc = when (tab) {
|
||||
is UpdatesTab -> pluralStringResource(
|
||||
MR.plurals.notification_chapters_generic,
|
||||
count = count,
|
||||
count,
|
||||
)
|
||||
|
||||
is BrowseTab -> pluralStringResource(
|
||||
MR.plurals.update_check_notification_ext_updates,
|
||||
count = count,
|
||||
count,
|
||||
)
|
||||
|
||||
else -> null
|
||||
}
|
||||
Text(
|
||||
text = count.toString(),
|
||||
modifier = Modifier.semantics {
|
||||
if (desc != null) contentDescription = desc
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user