package eu.kanade.presentation.components 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.foundation.pager.rememberPagerState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.PrimaryTabRow import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Tab 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.zIndex import dev.icerock.moko.resources.StringResource import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.launch import tachiyomi.presentation.core.components.HorizontalPager import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.TabText import tachiyomi.presentation.core.i18n.stringResource @Composable fun TabbedScreen( titleRes: StringResource, tabs: ImmutableList, startIndex: Int? = null, searchQuery: String? = null, onChangeSearchQuery: (String?) -> Unit = {}, ) { val scope = rememberCoroutineScope() val state = rememberPagerState { tabs.size } 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), ), ) { PrimaryTabRow( selectedTabIndex = state.currentPage, modifier = Modifier.zIndex(1f), ) { 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( modifier = Modifier.fillMaxSize(), state = state, verticalAlignment = Alignment.Top, ) { page -> tabs[page].content( PaddingValues(bottom = contentPadding.calculateBottomPadding()), snackbarHostState, ) } } } } data class TabContent( val titleRes: StringResource, val badgeNumber: Int? = null, val searchEnabled: Boolean = false, val actions: ImmutableList = persistentListOf(), val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit, )