Merge branch 'master' into sync-part-final

This commit is contained in:
KaiserBh 2023-11-18 00:10:28 +11:00 committed by GitHub
commit 6d54953580
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 276 additions and 298 deletions

View File

@ -12,7 +12,7 @@ jobs:
lock:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v4
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: '2'

View File

@ -4,7 +4,7 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.Public
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.SnackbarDuration
@ -80,7 +80,7 @@ fun BrowseSourceContent(
persistentListOf(
EmptyScreenAction(
stringResId = R.string.local_source_help_guide,
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = onLocalSourceHelpClick,
),
)
@ -98,7 +98,7 @@ fun BrowseSourceContent(
),
EmptyScreenAction(
stringResId = R.string.label_help,
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = onHelpClick,
),
)

View File

@ -16,7 +16,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.History
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.AlertDialog
@ -92,7 +92,7 @@ fun ExtensionDetailsScreen(
add(
AppBar.Action(
title = stringResource(R.string.action_faq_and_guides),
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = onClickReadme,
),
)

View File

@ -1,7 +1,7 @@
package eu.kanade.presentation.browse.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ViewList
import androidx.compose.material.icons.automirrored.filled.ViewList
import androidx.compose.material.icons.filled.ViewModule
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior
@ -57,7 +57,7 @@ fun BrowseSourceToolbar(
AppBar.Action(
title = stringResource(R.string.action_display_mode),
icon = if (displayMode == LibraryDisplayMode.List) {
Icons.Filled.ViewList
Icons.AutoMirrored.Filled.ViewList
} else {
Icons.Filled.ViewModule
},

View File

@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowForward
import androidx.compose.material.icons.outlined.ArrowForward
import androidx.compose.material.icons.outlined.Error
import androidx.compose.material3.CircularProgressIndicator
@ -54,7 +55,7 @@ fun GlobalSearchResultItem(
Text(text = subtitle)
}
IconButton(onClick = onClick) {
Icon(imageVector = Icons.Outlined.ArrowForward, contentDescription = null)
Icon(imageVector = Icons.AutoMirrored.Outlined.ArrowForward, contentDescription = null)
}
}
content()

View File

@ -58,7 +58,7 @@ fun GlobalSearchToolbar(
)
if (progress in 1..<total) {
LinearProgressIndicator(
progress = progress / total.toFloat(),
progress = { progress / total.toFloat() },
modifier = Modifier
.align(Alignment.BottomStart)
.fillMaxWidth(),

View File

@ -19,7 +19,7 @@ fun CategoryFloatingActionButton(
) {
ExtendedFloatingActionButton(
text = { Text(text = stringResource(R.string.action_add)) },
icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = "") },
icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = null) },
onClick = onCreate,
expanded = lazyListState.isScrollingUp() || lazyListState.isScrolledToEnd(),
)

View File

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.ArrowDropDown
import androidx.compose.material.icons.outlined.ArrowDropUp
import androidx.compose.material.icons.outlined.Delete
@ -49,7 +50,7 @@ fun CategoryListItem(
),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(imageVector = Icons.Outlined.Label, contentDescription = "")
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = "")
Text(
text = category.name,
modifier = Modifier

View File

@ -8,10 +8,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.ArrowForward
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material.icons.outlined.Search
@ -20,11 +18,15 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltipBox
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTooltipState
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
@ -40,14 +42,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.tachiyomi.R
@ -189,13 +189,18 @@ fun AppBarActions(
var showMenu by remember { mutableStateOf(false) }
actions.filterIsInstance<AppBar.Action>().map {
PlainTooltipBox(
tooltip = { Text(it.title) },
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = {
PlainTooltip {
Text(it.title)
}
},
state = rememberTooltipState(),
) {
IconButton(
onClick = it.onClick,
enabled = it.enabled,
modifier = Modifier.tooltipTrigger(),
) {
Icon(
imageVector = it.icon,
@ -208,12 +213,17 @@ fun AppBarActions(
val overflowActions = actions.filterIsInstance<AppBar.OverflowAction>()
if (overflowActions.isNotEmpty()) {
PlainTooltipBox(
tooltip = { Text(stringResource(R.string.abc_action_menu_overflow_description)) },
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = {
PlainTooltip {
Text(stringResource(R.string.abc_action_menu_overflow_description))
}
},
state = rememberTooltipState(),
) {
IconButton(
onClick = { showMenu = !showMenu },
modifier = Modifier.tooltipTrigger(),
) {
Icon(
Icons.Outlined.MoreVert,
@ -327,12 +337,17 @@ fun SearchToolbar(
if (!searchEnabled) {
// Don't show search action
} else if (searchQuery == null) {
PlainTooltipBox(
tooltip = { Text(stringResource(R.string.action_search)) },
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = {
PlainTooltip {
Text(stringResource(R.string.action_search))
}
},
state = rememberTooltipState(),
) {
IconButton(
onClick = onClick,
modifier = Modifier.tooltipTrigger(),
) {
Icon(
Icons.Outlined.Search,
@ -341,15 +356,20 @@ fun SearchToolbar(
}
}
} else if (searchQuery.isNotEmpty()) {
PlainTooltipBox(
tooltip = { Text(stringResource(R.string.action_reset)) },
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = {
PlainTooltip {
Text(stringResource(R.string.action_reset))
}
},
state = rememberTooltipState(),
) {
IconButton(
onClick = {
onClick()
focusRequester.requestFocus()
},
modifier = Modifier.tooltipTrigger(),
) {
Icon(
Icons.Outlined.Close,
@ -370,11 +390,7 @@ fun SearchToolbar(
@Composable
fun UpIcon(navigationIcon: ImageVector? = null) {
val icon = navigationIcon
?: if (LocalLayoutDirection.current == LayoutDirection.Ltr) {
Icons.Outlined.ArrowBack
} else {
Icons.Outlined.ArrowForward
}
?: Icons.AutoMirrored.Outlined.ArrowBack
Icon(
imageVector = icon,
contentDescription = stringResource(R.string.abc_action_bar_up_description),

View File

@ -3,8 +3,7 @@ package eu.kanade.presentation.components
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowLeft
import androidx.compose.material.icons.outlined.ArrowRight
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
import androidx.compose.material.icons.outlined.RadioButtonChecked
import androidx.compose.material.icons.outlined.RadioButtonUnchecked
import androidx.compose.material3.DropdownMenuItem
@ -16,10 +15,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties
import eu.kanade.tachiyomi.R
@ -77,14 +74,13 @@ fun NestedMenuItem(
) {
var nestedExpanded by remember { mutableStateOf(false) }
val closeMenu = { nestedExpanded = false }
val isLtr = LocalLayoutDirection.current == LayoutDirection.Ltr
DropdownMenuItem(
text = text,
onClick = { nestedExpanded = true },
trailingIcon = {
Icon(
imageVector = if (isLtr) Icons.Outlined.ArrowRight else Icons.Outlined.ArrowLeft,
imageVector = Icons.AutoMirrored.Outlined.ArrowRight,
contentDescription = null,
)
},

View File

@ -1,6 +1,7 @@
package eu.kanade.presentation.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.Surface
@ -39,7 +40,7 @@ private fun WithActionPreview() {
),
EmptyScreenAction(
stringResId = R.string.getting_started_guide,
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = {},
),
),

View File

@ -14,8 +14,8 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -30,7 +30,6 @@ import androidx.compose.ui.util.fastForEachIndexed
import eu.kanade.tachiyomi.R
import kotlinx.coroutines.launch
import tachiyomi.presentation.core.components.HorizontalPager
import tachiyomi.presentation.core.components.material.TabIndicator
import tachiyomi.presentation.core.components.material.TabText
object TabbedDialogPaddings {
@ -55,10 +54,9 @@ fun TabbedDialog(
Column {
Row {
TabRow(
PrimaryTabRow(
modifier = Modifier.weight(1f),
selectedTabIndex = pagerState.currentPage,
indicator = { TabIndicator(it[pagerState.currentPage], pagerState.currentPageOffsetFraction) },
divider = {},
) {
tabTitles.fastForEachIndexed { index, tab ->

View File

@ -9,10 +9,10 @@ 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.material3.TabRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
@ -24,7 +24,6 @@ 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
@Composable
@ -67,9 +66,8 @@ fun TabbedScreen(
end = contentPadding.calculateEndPadding(LocalLayoutDirection.current),
),
) {
TabRow(
PrimaryTabRow(
selectedTabIndex = state.currentPage,
indicator = { TabIndicator(it[state.currentPage], state.currentPageOffsetFraction) },
) {
tabs.forEachIndexed { index, tab ->
Tab(

View File

@ -33,11 +33,13 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.presentation.manga.components.MangaCover
import eu.kanade.tachiyomi.R
import tachiyomi.presentation.core.components.BadgeGroup
import tachiyomi.presentation.core.util.selectedBackground
@ -376,7 +378,7 @@ private fun ContinueReadingButton(
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "",
contentDescription = stringResource(R.string.action_resume),
modifier = Modifier.size(16.dp),
)
}

View File

@ -4,13 +4,12 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.pager.PagerState
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.PrimaryScrollableTabRow
import androidx.compose.material3.Tab
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.category.visualName
import tachiyomi.domain.category.model.Category
import tachiyomi.presentation.core.components.material.TabIndicator
import tachiyomi.presentation.core.components.material.TabText
@Composable
@ -21,10 +20,9 @@ internal fun LibraryTabs(
onTabItemClick: (Int) -> Unit,
) {
Column {
ScrollableTabRow(
PrimaryScrollableTabRow(
selectedTabIndex = pagerState.currentPage,
edgePadding = 0.dp,
indicator = { TabIndicator(it[pagerState.currentPage], pagerState.currentPageOffsetFraction) },
// TODO: use default when width is fixed upstream
// https://issuetracker.google.com/issues/242879624
divider = {},

View File

@ -148,7 +148,7 @@ private fun DownloadingIndicator(
MaterialTheme.colorScheme.background
}
CircularProgressIndicator(
progress = animatedProgress,
progress = { animatedProgress },
modifier = IndicatorModifier,
color = strokeColor,
strokeWidth = IndicatorSize / 2,

View File

@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.ZeroCornerSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.BookmarkAdd
import androidx.compose.material.icons.outlined.BookmarkRemove
import androidx.compose.material.icons.outlined.Delete
@ -258,7 +259,7 @@ fun LibraryBottomActionMenu(
) {
Button(
title = stringResource(R.string.action_move_category),
icon = Icons.Outlined.Label,
icon = Icons.AutoMirrored.Outlined.Label,
toConfirm = confirm[0],
onLongClick = { onLongClickItem(0) },
onClick = onChangeCategoryClicked,

View File

@ -9,6 +9,8 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.outlined.CloudOff
import androidx.compose.material.icons.outlined.GetApp
import androidx.compose.material.icons.outlined.HelpOutline
@ -130,7 +132,7 @@ fun MoreScreen(
item {
TextPreferenceWidget(
title = stringResource(R.string.categories),
icon = Icons.Outlined.Label,
icon = Icons.AutoMirrored.Outlined.Label,
onPreferenceClick = onClickCategories,
)
}
@ -168,7 +170,7 @@ fun MoreScreen(
item {
TextPreferenceWidget(
title = stringResource(R.string.label_help),
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onPreferenceClick = { uriHandler.openUri(Constants.URL_HELP) },
)
}

View File

@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.OpenInNew
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material3.Icon
@ -60,7 +61,7 @@ fun NewUpdateScreen(
) {
Text(text = stringResource(R.string.update_check_open))
Spacer(modifier = Modifier.width(MaterialTheme.padding.tiny))
Icon(imageVector = Icons.Default.OpenInNew, contentDescription = null)
Icon(imageVector = Icons.AutoMirrored.Outlined.OpenInNew, contentDescription = null)
}
}
}

View File

@ -9,6 +9,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ChromeReaderMode
import androidx.compose.material.icons.outlined.ChromeReaderMode
import androidx.compose.material.icons.outlined.Code
import androidx.compose.material.icons.outlined.CollectionsBookmark
@ -186,7 +187,7 @@ object SettingsMainScreen : Screen() {
Item(
titleRes = R.string.pref_category_reader,
subtitleRes = R.string.pref_reader_summary,
icon = Icons.Outlined.ChromeReaderMode,
icon = Icons.AutoMirrored.Outlined.ChromeReaderMode,
screen = SettingsReaderScreen,
),
Item(

View File

@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material.icons.outlined.Close
@ -72,7 +73,7 @@ object SettingsTrackingScreen : SearchableSettings {
val uriHandler = LocalUriHandler.current
IconButton(onClick = { uriHandler.openUri("https://tachiyomi.org/docs/guides/tracking") }) {
Icon(
imageVector = Icons.Outlined.HelpOutline,
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
contentDescription = stringResource(R.string.tracking_guide),
)
}

View File

@ -28,6 +28,7 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Close
@ -97,7 +98,7 @@ fun TrackerSearch(
navigationIcon = {
IconButton(onClick = onDismissRequest) {
Icon(
imageVector = Icons.Default.ArrowBack,
imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)

View File

@ -11,6 +11,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.automirrored.outlined.ArrowForward
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.ArrowForward
import androidx.compose.material.icons.outlined.Close
@ -125,7 +127,7 @@ fun WebViewScreenContent(
listOf(
AppBar.Action(
title = stringResource(R.string.action_webview_back),
icon = Icons.Outlined.ArrowBack,
icon = Icons.AutoMirrored.Outlined.ArrowBack,
onClick = {
if (navigator.canGoBack) {
navigator.navigateBack()
@ -135,7 +137,7 @@ fun WebViewScreenContent(
),
AppBar.Action(
title = stringResource(R.string.action_webview_forward),
icon = Icons.Outlined.ArrowForward,
icon = Icons.AutoMirrored.Outlined.ArrowForward,
onClick = {
if (navigator.canGoForward) {
navigator.navigateForward()
@ -188,7 +190,7 @@ fun WebViewScreenContent(
.align(Alignment.BottomCenter),
)
is LoadingState.Loading -> LinearProgressIndicator(
progress = (loadingState as? LoadingState.Loading)?.progress ?: 1f,
progress = { (loadingState as? LoadingState.Loading)?.progress ?: 1f },
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter),

View File

@ -67,7 +67,7 @@ data class SourceSearchScreen(
AnimatedVisibility(visible = state.filters.isNotEmpty()) {
ExtendedFloatingActionButton(
text = { Text(text = stringResource(R.string.action_filter)) },
icon = { Icon(Icons.Outlined.FilterList, contentDescription = "") },
icon = { Icon(Icons.Outlined.FilterList, contentDescription = null) },
onClick = screenModel::openFilterSheet,
)
}

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.browse.migration.sources
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
@ -29,7 +30,7 @@ fun Screen.migrateSourceTab(): TabContent {
actions = listOf(
AppBar.Action(
title = stringResource(R.string.migration_help_guide),
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = {
uriHandler.openUri("https://tachiyomi.org/docs/guides/source-migration")
},

View File

@ -144,7 +144,7 @@ data class BrowseSourceScreen(
leadingIcon = {
Icon(
imageVector = Icons.Outlined.Favorite,
contentDescription = "",
contentDescription = null,
modifier = Modifier
.size(FilterChipDefaults.IconSize),
)
@ -163,7 +163,7 @@ data class BrowseSourceScreen(
leadingIcon = {
Icon(
imageVector = Icons.Outlined.NewReleases,
contentDescription = "",
contentDescription = null,
modifier = Modifier
.size(FilterChipDefaults.IconSize),
)
@ -180,7 +180,7 @@ data class BrowseSourceScreen(
leadingIcon = {
Icon(
imageVector = Icons.Outlined.FilterList,
contentDescription = "",
contentDescription = null,
modifier = Modifier
.size(FilterChipDefaults.IconSize),
)

View File

@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.Sort
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.outlined.Pause
import androidx.compose.material.icons.outlined.Sort
@ -185,7 +186,7 @@ object DownloadQueueScreen : Screen() {
listOf(
AppBar.Action(
title = stringResource(R.string.action_sort),
icon = Icons.Outlined.Sort,
icon = Icons.AutoMirrored.Outlined.Sort,
onClick = { sortExpanded = true },
),
AppBar.OverflowAction(

View File

@ -6,6 +6,7 @@ import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter
import androidx.compose.animation.graphics.vector.AnimatedImageVector
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
@ -158,7 +159,7 @@ object LibraryTab : Tab {
actions = persistentListOf(
EmptyScreenAction(
stringResId = R.string.getting_started_guide,
icon = Icons.Outlined.HelpOutline,
icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = { handler.openUri("https://tachiyomi.org/docs/guides/getting-started") },
),
),

View File

@ -39,7 +39,7 @@ class ReaderProgressIndicator @JvmOverloads constructor(
@Composable
override fun Content() {
TachiyomiTheme {
CombinedCircularProgressIndicator(progress = progress)
CombinedCircularProgressIndicator(progress = { progress })
}
}

View File

@ -1,5 +1,5 @@
[versions]
agp_version = "8.1.2"
agp_version = "8.1.3"
lifecycle_version = "2.6.2"
paging_version = "3.2.1"
@ -25,7 +25,7 @@ workmanager = "androidx.work:work-runtime-ktx:2.8.1"
paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" }
paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" }
benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.0"
benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.1"
test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha01"
test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha01"
test-uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0-alpha05"

View File

@ -1,10 +1,10 @@
[versions]
compiler = "1.5.4"
compose-bom = "2023.09.00-alpha02"
accompanist = "0.33.1-alpha"
compose-bom = "2023.12.00-alpha01"
accompanist = "0.33.2-alpha"
[libraries]
activity = "androidx.activity:activity-compose:1.8.0"
activity = "androidx.activity:activity-compose:1.8.1"
bom = { group = "dev.chrisbanes.compose", name = "compose-bom", version.ref = "compose-bom" }
foundation = { module = "androidx.compose.foundation:foundation" }
animation = { module = "androidx.compose.animation:animation" }

View File

@ -1,6 +1,6 @@
[versions]
kotlin_version = "1.9.20"
serialization_version = "1.6.0"
serialization_version = "1.6.1"
xml_serialization_version = "0.86.2"
[libraries]

View File

@ -37,16 +37,15 @@ import androidx.compose.ui.tooling.preview.Preview
* By always rotating we give the feedback to the user that the application isn't 'stuck'.
*/
@Composable
fun CombinedCircularProgressIndicator(progress: Float) {
val animatedProgress by animateFloatAsState(
targetValue = progress,
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "progress",
)
fun CombinedCircularProgressIndicator(
progress: () -> Float,
modifier: Modifier = Modifier,
) {
AnimatedContent(
targetState = progress == 0f,
targetState = progress() == 0f,
transitionSpec = { fadeIn() togetherWith fadeOut() },
label = "progressState",
modifier = modifier,
) { indeterminate ->
if (indeterminate) {
// Indeterminate
@ -63,8 +62,13 @@ fun CombinedCircularProgressIndicator(progress: Float) {
),
label = "rotation",
)
val animatedProgress by animateFloatAsState(
targetValue = progress(),
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
label = "progress",
)
CircularProgressIndicator(
progress = animatedProgress,
progress = { animatedProgress },
modifier = Modifier.rotate(rotation),
)
}
@ -101,7 +105,7 @@ private fun CombinedCircularProgressIndicatorPreview() {
.fillMaxSize()
.padding(it),
) {
CombinedCircularProgressIndicator(progress = progress)
CombinedCircularProgressIndicator(progress = { progress })
}
}
}

View File

@ -14,36 +14,39 @@
* limitations under the License.
*/
@file:Suppress("KDocUnresolvedReference")
package tachiyomi.presentation.core.components.material
import androidx.compose.foundation.layout.MutableWindowInsets
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.exclude
import androidx.compose.foundation.layout.onConsumedWindowInsetsChanged
import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.layout.windowInsetsEndWidth
import androidx.compose.foundation.layout.windowInsetsStartWidth
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FabPosition
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.contentColorFor
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import androidx.compose.ui.unit.offset
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastMap
import androidx.compose.ui.util.fastMaxBy
@ -70,8 +73,6 @@ import kotlin.math.max
* * Pass scroll behavior to top bar by default
* * Remove height constraint for expanded app bar
* * Also take account of fab height when providing inner padding
* * Fixes for fab and snackbar horizontal placements when [contentWindowInsets] is used
* * Handle consumed window insets
* * Add startBar slot for Navigation Rail
*
* @param modifier the [Modifier] to be applied to this scaffold
@ -99,9 +100,7 @@ import kotlin.math.max
@Composable
fun Scaffold(
modifier: Modifier = Modifier,
topBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(
rememberTopAppBarState(),
),
topBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
topBar: @Composable (TopAppBarScrollBehavior) -> Unit = {},
bottomBar: @Composable () -> Unit = {},
startBar: @Composable () -> Unit = {},
@ -113,16 +112,9 @@ fun Scaffold(
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
content: @Composable (PaddingValues) -> Unit,
) {
// Tachiyomi: Handle consumed window insets
val remainingWindowInsets = remember { MutableWindowInsets() }
androidx.compose.material3.Surface(
modifier = Modifier
.nestedScroll(topBarScrollBehavior.nestedScrollConnection)
.onConsumedWindowInsetsChanged {
remainingWindowInsets.insets = contentWindowInsets.exclude(
it,
)
}
.then(modifier),
color = containerColor,
contentColor = contentColor,
@ -134,7 +126,7 @@ fun Scaffold(
bottomBar = bottomBar,
content = content,
snackbar = snackbarHost,
contentWindowInsets = remainingWindowInsets,
contentWindowInsets = contentWindowInsets,
fab = floatingActionButton,
)
}
@ -152,7 +144,6 @@ fun Scaffold(
* @param bottomBar the content to place at the bottom of the [Scaffold], on top of the
* [content], typically a [NavigationBar].
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ScaffoldLayout(
fabPosition: FabPosition,
@ -164,7 +155,47 @@ private fun ScaffoldLayout(
contentWindowInsets: WindowInsets,
bottomBar: @Composable () -> Unit,
) {
SubcomposeLayout { constraints ->
// Create the backing values for the content padding
// These values will be updated during measurement, but before measuring and placing
// the body content
var topContentPadding by remember { mutableStateOf(0.dp) }
var startContentPadding by remember { mutableStateOf(0.dp) }
var endContentPadding by remember { mutableStateOf(0.dp) }
var bottomContentPadding by remember { mutableStateOf(0.dp) }
val contentPadding = remember {
object : PaddingValues {
override fun calculateLeftPadding(layoutDirection: LayoutDirection): Dp =
when (layoutDirection) {
LayoutDirection.Ltr -> startContentPadding
LayoutDirection.Rtl -> endContentPadding
}
override fun calculateTopPadding(): Dp = topContentPadding
override fun calculateRightPadding(layoutDirection: LayoutDirection): Dp =
when (layoutDirection) {
LayoutDirection.Ltr -> endContentPadding
LayoutDirection.Rtl -> startContentPadding
}
override fun calculateBottomPadding(): Dp = bottomContentPadding
}
}
Layout(
contents = listOf(
{ Spacer(Modifier.windowInsetsTopHeight(contentWindowInsets)) },
{ Spacer(Modifier.windowInsetsBottomHeight(contentWindowInsets)) },
{ Spacer(Modifier.windowInsetsStartWidth(contentWindowInsets)) },
{ Spacer(Modifier.windowInsetsEndWidth(contentWindowInsets)) },
startBar,
topBar,
snackbar,
fab,
bottomBar,
{ content(contentPadding) },
),
) { measurables, constraints ->
val layoutWidth = constraints.maxWidth
val layoutHeight = constraints.maxHeight
@ -175,59 +206,67 @@ private fun ScaffoldLayout(
*/
val topBarConstraints = looseConstraints.copy(maxHeight = Constraints.Infinity)
layout(layoutWidth, layoutHeight) {
val leftInset = contentWindowInsets.getLeft(this@SubcomposeLayout, layoutDirection)
val rightInset = contentWindowInsets.getRight(this@SubcomposeLayout, layoutDirection)
val bottomInset = contentWindowInsets.getBottom(this@SubcomposeLayout)
val topInsetsPlaceables = measurables[0].single()
.measure(looseConstraints)
val bottomInsetsPlaceables = measurables[1].single()
.measure(looseConstraints)
val startInsetsPlaceables = measurables[2].single()
.measure(looseConstraints)
val endInsetsPlaceables = measurables[3].single()
.measure(looseConstraints)
val startInsetsWidth = startInsetsPlaceables.width
val endInsetsWidth = endInsetsPlaceables.width
val topInsetsHeight = topInsetsPlaceables.height
val bottomInsetsHeight = bottomInsetsPlaceables.height
// Tachiyomi: Add startBar slot for Navigation Rail
val startBarPlaceables = subcompose(ScaffoldLayoutContent.StartBar, startBar).fastMap {
it.measure(looseConstraints)
}
val startBarPlaceables = measurables[4]
.fastMap { it.measure(looseConstraints) }
val startBarWidth = startBarPlaceables.fastMaxBy { it.width }?.width ?: 0
// Tachiyomi: layoutWidth after horizontal insets
val insetLayoutWidth = layoutWidth - leftInset - rightInset - startBarWidth
val topBarPlaceables = subcompose(ScaffoldLayoutContent.TopBar, topBar).fastMap {
it.measure(topBarConstraints)
}
val topBarPlaceables = measurables[5]
.fastMap { it.measure(topBarConstraints) }
val topBarHeight = topBarPlaceables.fastMaxBy { it.height }?.height ?: 0
val snackbarPlaceables = subcompose(ScaffoldLayoutContent.Snackbar, snackbar).fastMap {
it.measure(looseConstraints)
}
val bottomPlaceablesConstraints = looseConstraints.offset(
-startInsetsWidth - endInsetsWidth,
-bottomInsetsHeight,
)
val snackbarPlaceables = measurables[6]
.fastMap { it.measure(bottomPlaceablesConstraints) }
val snackbarHeight = snackbarPlaceables.fastMaxBy { it.height }?.height ?: 0
val snackbarWidth = snackbarPlaceables.fastMaxBy { it.width }?.width ?: 0
// Tachiyomi: Calculate insets for snackbar placement offset
val snackbarLeft = if (snackbarPlaceables.isNotEmpty()) {
(insetLayoutWidth - snackbarWidth) / 2 + leftInset
} else {
0
}
val fabPlaceables =
subcompose(ScaffoldLayoutContent.Fab, fab).fastMap { measurable ->
measurable.measure(looseConstraints)
}
val fabPlaceables = measurables[7]
.fastMap { it.measure(bottomPlaceablesConstraints) }
val fabWidth = fabPlaceables.fastMaxBy { it.width }?.width ?: 0
val fabHeight = fabPlaceables.fastMaxBy { it.height }?.height ?: 0
val fabPlacement = if (fabPlaceables.isNotEmpty() && fabWidth != 0 && fabHeight != 0) {
val fabPlacement = if (fabWidth > 0 && fabHeight > 0) {
// FAB distance from the left of the layout, taking into account LTR / RTL
// Tachiyomi: Calculate insets for fab placement offset
val fabLeftOffset = if (fabPosition == FabPosition.End) {
val fabLeftOffset = when (fabPosition) {
FabPosition.Start -> {
if (layoutDirection == LayoutDirection.Ltr) {
layoutWidth - FabSpacing.roundToPx() - fabWidth - rightInset
FabSpacing.roundToPx()
} else {
FabSpacing.roundToPx() + leftInset
layoutWidth - FabSpacing.roundToPx() - fabWidth
}
}
FabPosition.End, FabPosition.EndOverlay -> {
if (layoutDirection == LayoutDirection.Ltr) {
layoutWidth - FabSpacing.roundToPx() - fabWidth
} else {
leftInset + ((insetLayoutWidth - fabWidth) / 2)
FabSpacing.roundToPx()
}
}
else -> (layoutWidth - fabWidth) / 2
}
FabPlacement(
@ -239,55 +278,45 @@ private fun ScaffoldLayout(
null
}
val bottomBarPlaceables = subcompose(ScaffoldLayoutContent.BottomBar) {
CompositionLocalProvider(
LocalFabPlacement provides fabPlacement,
content = bottomBar,
)
}.fastMap { it.measure(looseConstraints) }
val bottomBarPlaceables = measurables[8]
.fastMap { it.measure(looseConstraints) }
val bottomBarHeight = bottomBarPlaceables.fastMaxBy { it.height }?.height ?: 0
val bottomBarHeight = bottomBarPlaceables
.fastMaxBy { it.height }
?.height
?.takeIf { it != 0 }
val fabOffsetFromBottom = fabPlacement?.let {
max(bottomBarHeight ?: 0, bottomInset) + it.height + FabSpacing.roundToPx()
if (fabPosition == FabPosition.EndOverlay) {
it.height + FabSpacing.roundToPx() + bottomInsetsHeight
} else {
// Total height is the bottom bar height + the FAB height + the padding
// between the FAB and bottom bar
max(bottomBarHeight, bottomInsetsHeight) + it.height + FabSpacing.roundToPx()
}
}
val snackbarOffsetFromBottom = if (snackbarHeight != 0) {
snackbarHeight + (fabOffsetFromBottom ?: max(bottomBarHeight ?: 0, bottomInset))
snackbarHeight + max(
fabOffsetFromBottom ?: 0,
max(
bottomBarHeight,
bottomInsetsHeight,
),
)
} else {
0
}
val bodyContentPlaceables = subcompose(ScaffoldLayoutContent.MainContent) {
val insets = contentWindowInsets.asPaddingValues(this@SubcomposeLayout)
val fabOffsetDp = fabOffsetFromBottom?.toDp() ?: 0.dp
val bottomBarHeightPx = bottomBarHeight ?: 0
val innerPadding = PaddingValues(
top =
if (topBarPlaceables.isEmpty()) {
insets.calculateTopPadding()
} else {
topBarHeight.toDp()
},
bottom = // Tachiyomi: Also take account of fab height when providing inner padding
if (bottomBarPlaceables.isEmpty() || bottomBarHeightPx == 0) {
max(insets.calculateBottomPadding(), fabOffsetDp)
} else {
max(bottomBarHeightPx.toDp(), fabOffsetDp)
},
start = max(
insets.calculateStartPadding((this@SubcomposeLayout).layoutDirection),
startBarWidth.toDp(),
),
end = insets.calculateEndPadding((this@SubcomposeLayout).layoutDirection),
)
content(innerPadding)
}.fastMap { it.measure(looseConstraints) }
// Update the backing value for the content padding of the body content
// We do this before measuring or placing the body content
topContentPadding = max(topBarHeight, topInsetsHeight).toDp()
bottomContentPadding = max(fabOffsetFromBottom ?: 0, max(bottomBarHeight, bottomInsetsHeight)).toDp()
startContentPadding = max(startBarWidth, startInsetsWidth).toDp()
endContentPadding = endInsetsWidth.toDp()
val bodyContentPlaceables = measurables[9]
.fastMap { it.measure(looseConstraints) }
layout(layoutWidth, layoutHeight) {
// Inset spacers are just for convenient measurement logic, no need to place them
// Placing to control drawing order to match default elevation of each placeable
bodyContentPlaceables.fastForEach {
it.place(0, 0)
}
@ -299,48 +328,25 @@ private fun ScaffoldLayout(
}
snackbarPlaceables.fastForEach {
it.place(
snackbarLeft,
(layoutWidth - snackbarWidth) / 2 + when (layoutDirection) {
LayoutDirection.Ltr -> startInsetsWidth
LayoutDirection.Rtl -> endInsetsWidth
},
layoutHeight - snackbarOffsetFromBottom,
)
}
// The bottom bar is always at the bottom of the layout
bottomBarPlaceables.fastForEach {
it.place(0, layoutHeight - (bottomBarHeight ?: 0))
it.place(0, layoutHeight - bottomBarHeight)
}
// Explicitly not using placeRelative here as `leftOffset` already accounts for RTL
fabPlacement?.let { placement ->
fabPlaceables.fastForEach {
it.place(fabPlacement?.left ?: 0, layoutHeight - (fabOffsetFromBottom ?: 0))
it.place(placement.left, layoutHeight - fabOffsetFromBottom!!)
}
}
}
}
/**
* The possible positions for a [FloatingActionButton] attached to a [Scaffold].
*/
@ExperimentalMaterial3Api
@JvmInline
value class FabPosition internal constructor(@Suppress("unused") private val value: Int) {
companion object {
/**
* Position FAB at the bottom of the screen in the center, above the [NavigationBar] (if it
* exists)
*/
val Center = FabPosition(0)
/**
* Position FAB at the bottom of the screen at the end, above the [NavigationBar] (if it
* exists)
*/
val End = FabPosition(1)
}
override fun toString(): String {
return when (this) {
Center -> "FabPosition.Center"
else -> "FabPosition.End"
}
}
}
/**
@ -358,12 +364,5 @@ internal class FabPlacement(
val height: Int,
)
/**
* CompositionLocal containing a [FabPlacement] that is used to calculate the FAB bottom offset.
*/
internal val LocalFabPlacement = staticCompositionLocalOf<FabPlacement?> { null }
// FAB spacing above the bottom bar / bottom of the Scaffold
private val FabSpacing = 16.dp
private enum class ScaffoldLayoutContent { TopBar, MainContent, Snackbar, Fab, BottomBar, StartBar }

View File

@ -1,63 +1,15 @@
package tachiyomi.presentation.core.components.material
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TabPosition
import androidx.compose.material3.TabRowDefaults.SecondaryIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import tachiyomi.presentation.core.components.Pill
private fun Modifier.tabIndicatorOffset(
currentTabPosition: TabPosition,
currentPageOffsetFraction: Float,
) = fillMaxWidth()
.wrapContentSize(Alignment.BottomStart)
.composed {
val currentTabWidth by animateDpAsState(
targetValue = currentTabPosition.width,
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "currentTabWidth",
)
val offset by animateDpAsState(
targetValue = currentTabPosition.left + (currentTabWidth * currentPageOffsetFraction),
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "offset",
)
Modifier
.offset { IntOffset(x = offset.roundToPx(), y = 0) }
.width(currentTabWidth)
}
@Composable
fun TabIndicator(currentTabPosition: TabPosition, currentPageOffsetFraction: Float) {
SecondaryIndicator(
modifier = Modifier
.tabIndicatorOffset(currentTabPosition, currentPageOffsetFraction)
.padding(horizontal = 8.dp)
.clip(RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp)),
)
}
@Composable
fun TabText(text: String, badgeCount: Int? = null) {
val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f