123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- package eu.kanade.presentation.components
- import androidx.annotation.StringRes
- import androidx.compose.foundation.layout.Column
- import androidx.compose.foundation.layout.PaddingValues
- import androidx.compose.foundation.layout.calculateEndPadding
- import androidx.compose.foundation.layout.calculateStartPadding
- import androidx.compose.foundation.layout.fillMaxSize
- import androidx.compose.foundation.layout.padding
- import androidx.compose.material3.MaterialTheme
- import androidx.compose.material3.SnackbarHost
- import androidx.compose.material3.SnackbarHostState
- import androidx.compose.material3.Tab
- import androidx.compose.material3.TabRow
- import androidx.compose.runtime.Composable
- import androidx.compose.runtime.LaunchedEffect
- import androidx.compose.runtime.remember
- import androidx.compose.runtime.rememberCoroutineScope
- import androidx.compose.ui.Alignment
- import androidx.compose.ui.Modifier
- import androidx.compose.ui.platform.LocalLayoutDirection
- import androidx.compose.ui.res.stringResource
- import kotlinx.coroutines.launch
- import tachiyomi.presentation.core.components.HorizontalPager
- import tachiyomi.presentation.core.components.material.Scaffold
- import tachiyomi.presentation.core.components.material.TabIndicator
- import tachiyomi.presentation.core.components.material.TabText
- import tachiyomi.presentation.core.components.rememberPagerState
- @Composable
- fun TabbedScreen(
- @StringRes titleRes: Int,
- tabs: List<TabContent>,
- startIndex: Int? = null,
- searchQuery: String? = null,
- onChangeSearchQuery: (String?) -> Unit = {},
- ) {
- val scope = rememberCoroutineScope()
- val state = rememberPagerState()
- val snackbarHostState = remember { SnackbarHostState() }
- LaunchedEffect(startIndex) {
- if (startIndex != null) {
- state.scrollToPage(startIndex)
- }
- }
- Scaffold(
- topBar = {
- val tab = tabs[state.currentPage]
- val searchEnabled = tab.searchEnabled
- SearchToolbar(
- titleContent = { AppBarTitle(stringResource(titleRes)) },
- searchEnabled = searchEnabled,
- searchQuery = if (searchEnabled) searchQuery else null,
- onChangeSearchQuery = onChangeSearchQuery,
- actions = { AppBarActions(tab.actions) },
- )
- },
- snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
- ) { contentPadding ->
- Column(
- modifier = Modifier.padding(
- top = contentPadding.calculateTopPadding(),
- start = contentPadding.calculateStartPadding(LocalLayoutDirection.current),
- end = contentPadding.calculateEndPadding(LocalLayoutDirection.current),
- ),
- ) {
- TabRow(
- selectedTabIndex = state.currentPage,
- indicator = { TabIndicator(it[state.currentPage]) },
- ) {
- tabs.forEachIndexed { index, tab ->
- Tab(
- selected = state.currentPage == index,
- onClick = { scope.launch { state.animateScrollToPage(index) } },
- text = { TabText(text = stringResource(tab.titleRes), badgeCount = tab.badgeNumber) },
- unselectedContentColor = MaterialTheme.colorScheme.onSurface,
- )
- }
- }
- HorizontalPager(
- count = tabs.size,
- modifier = Modifier.fillMaxSize(),
- state = state,
- verticalAlignment = Alignment.Top,
- ) { page ->
- tabs[page].content(
- PaddingValues(bottom = contentPadding.calculateBottomPadding()),
- snackbarHostState,
- )
- }
- }
- }
- }
- data class TabContent(
- @StringRes val titleRes: Int,
- val badgeNumber: Int? = null,
- val searchEnabled: Boolean = false,
- val actions: List<AppBar.Action> = emptyList(),
- val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit,
- )
|