2022-04-24 10:22:22 -04:00
|
|
|
package eu.kanade.presentation.components
|
|
|
|
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.animation.AnimatedVisibility
|
2022-09-27 19:05:10 -03:00
|
|
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.foundation.layout.Column
|
2022-07-16 17:58:43 -04:00
|
|
|
import androidx.compose.foundation.layout.RowScope
|
2022-08-26 20:19:47 +07:00
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
2022-08-26 20:19:47 +07:00
|
|
|
import androidx.compose.foundation.layout.statusBars
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.foundation.text.BasicTextField
|
2022-08-31 22:47:07 +02:00
|
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.material.icons.Icons
|
2022-07-16 17:58:43 -04:00
|
|
|
import androidx.compose.material.icons.filled.ArrowBack
|
2022-07-18 18:32:25 -04:00
|
|
|
import androidx.compose.material.icons.filled.Close
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.material.icons.filled.MoreVert
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.material.icons.outlined.ArrowBack
|
|
|
|
import androidx.compose.material.icons.outlined.Close
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.material3.DropdownMenuItem
|
|
|
|
import androidx.compose.material3.Icon
|
|
|
|
import androidx.compose.material3.IconButton
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
import androidx.compose.material3.Text
|
2022-09-27 19:05:10 -03:00
|
|
|
import androidx.compose.material3.TextFieldDefaults
|
2022-09-21 22:30:06 -04:00
|
|
|
import androidx.compose.material3.TopAppBar
|
2022-07-18 18:32:25 -04:00
|
|
|
import androidx.compose.material3.TopAppBarDefaults
|
2022-08-01 09:24:19 +07:00
|
|
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
2022-08-26 20:19:47 +07:00
|
|
|
import androidx.compose.material3.surfaceColorAtElevation
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.runtime.Composable
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.runtime.LaunchedEffect
|
2022-07-18 18:32:25 -04:00
|
|
|
import androidx.compose.runtime.derivedStateOf
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.runtime.getValue
|
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
import androidx.compose.runtime.remember
|
|
|
|
import androidx.compose.runtime.setValue
|
2022-07-18 18:32:25 -04:00
|
|
|
import androidx.compose.ui.Modifier
|
2022-08-29 16:39:35 -04:00
|
|
|
import androidx.compose.ui.focus.FocusRequester
|
|
|
|
import androidx.compose.ui.focus.focusRequester
|
|
|
|
import androidx.compose.ui.graphics.SolidColor
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.ui.graphics.vector.ImageVector
|
|
|
|
import androidx.compose.ui.res.stringResource
|
2022-06-15 18:02:08 -04:00
|
|
|
import androidx.compose.ui.text.font.FontWeight
|
2022-09-27 19:05:10 -03:00
|
|
|
import androidx.compose.ui.text.input.VisualTransformation
|
2022-04-24 10:22:22 -04:00
|
|
|
import androidx.compose.ui.text.style.TextOverflow
|
2022-08-26 20:19:47 +07:00
|
|
|
import androidx.compose.ui.unit.dp
|
2022-09-27 19:05:10 -03:00
|
|
|
import androidx.compose.ui.unit.sp
|
2022-04-24 10:22:22 -04:00
|
|
|
import eu.kanade.tachiyomi.R
|
|
|
|
|
2022-07-16 17:58:43 -04:00
|
|
|
@Composable
|
2022-07-16 18:11:26 -04:00
|
|
|
fun AppBar(
|
2022-07-18 18:32:25 -04:00
|
|
|
modifier: Modifier = Modifier,
|
|
|
|
// Text
|
2022-07-16 17:58:43 -04:00
|
|
|
title: String?,
|
|
|
|
subtitle: String? = null,
|
2022-07-18 18:32:25 -04:00
|
|
|
// Up button
|
2022-07-16 18:11:26 -04:00
|
|
|
navigateUp: (() -> Unit)? = null,
|
2022-07-16 17:58:43 -04:00
|
|
|
navigationIcon: ImageVector = Icons.Default.ArrowBack,
|
2022-07-18 18:32:25 -04:00
|
|
|
// Menu
|
2022-07-16 17:58:43 -04:00
|
|
|
actions: @Composable RowScope.() -> Unit = {},
|
2022-07-18 18:32:25 -04:00
|
|
|
// Action mode
|
|
|
|
actionModeCounter: Int = 0,
|
|
|
|
onCancelActionMode: () -> Unit = {},
|
|
|
|
actionModeActions: @Composable RowScope.() -> Unit = {},
|
|
|
|
// Banners
|
|
|
|
downloadedOnlyMode: Boolean = false,
|
|
|
|
incognitoMode: Boolean = false,
|
2022-08-01 09:24:19 +07:00
|
|
|
|
|
|
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
2022-07-16 17:58:43 -04:00
|
|
|
) {
|
2022-09-27 19:05:10 -03:00
|
|
|
val isActionMode by remember(actionModeCounter) {
|
|
|
|
derivedStateOf { actionModeCounter > 0 }
|
|
|
|
}
|
|
|
|
|
2022-08-01 09:24:19 +07:00
|
|
|
AppBar(
|
|
|
|
modifier = modifier,
|
|
|
|
titleContent = {
|
|
|
|
if (isActionMode) {
|
|
|
|
AppBarTitle(actionModeCounter.toString())
|
|
|
|
} else {
|
|
|
|
AppBarTitle(title, subtitle)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
navigateUp = navigateUp,
|
|
|
|
navigationIcon = navigationIcon,
|
|
|
|
actions = {
|
|
|
|
if (isActionMode) {
|
|
|
|
actionModeActions()
|
|
|
|
} else {
|
|
|
|
actions()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
isActionMode = isActionMode,
|
|
|
|
onCancelActionMode = onCancelActionMode,
|
|
|
|
downloadedOnlyMode = downloadedOnlyMode,
|
|
|
|
incognitoMode = incognitoMode,
|
|
|
|
scrollBehavior = scrollBehavior,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun AppBar(
|
|
|
|
modifier: Modifier = Modifier,
|
|
|
|
// Title
|
|
|
|
titleContent: @Composable () -> Unit,
|
|
|
|
// Up button
|
|
|
|
navigateUp: (() -> Unit)? = null,
|
|
|
|
navigationIcon: ImageVector = Icons.Default.ArrowBack,
|
|
|
|
// Menu
|
|
|
|
actions: @Composable RowScope.() -> Unit = {},
|
|
|
|
// Action mode
|
2022-08-04 04:41:15 +07:00
|
|
|
isActionMode: Boolean = false,
|
2022-08-01 09:24:19 +07:00
|
|
|
onCancelActionMode: () -> Unit = {},
|
|
|
|
// Banners
|
|
|
|
downloadedOnlyMode: Boolean = false,
|
|
|
|
incognitoMode: Boolean = false,
|
|
|
|
|
|
|
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
|
|
|
) {
|
2022-07-18 18:32:25 -04:00
|
|
|
Column(
|
2022-08-26 20:19:47 +07:00
|
|
|
modifier = modifier,
|
2022-07-18 18:32:25 -04:00
|
|
|
) {
|
2022-09-21 22:30:06 -04:00
|
|
|
TopAppBar(
|
2022-07-18 18:32:25 -04:00
|
|
|
navigationIcon = {
|
|
|
|
if (isActionMode) {
|
|
|
|
IconButton(onClick = onCancelActionMode) {
|
|
|
|
Icon(
|
|
|
|
imageVector = Icons.Default.Close,
|
2022-08-26 09:16:26 -04:00
|
|
|
contentDescription = stringResource(R.string.action_cancel),
|
2022-07-18 18:32:25 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
navigateUp?.let {
|
|
|
|
IconButton(onClick = it) {
|
|
|
|
Icon(
|
|
|
|
imageVector = navigationIcon,
|
|
|
|
contentDescription = stringResource(R.string.abc_action_bar_up_description),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2022-08-01 09:24:19 +07:00
|
|
|
title = titleContent,
|
|
|
|
actions = actions,
|
2022-08-26 20:19:47 +07:00
|
|
|
windowInsets = WindowInsets.statusBars,
|
2022-07-18 18:32:25 -04:00
|
|
|
colors = TopAppBarDefaults.smallTopAppBarColors(
|
2022-08-26 20:19:47 +07:00
|
|
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
|
|
|
|
elevation = if (isActionMode) 3.dp else 0.dp,
|
|
|
|
),
|
2022-07-18 18:32:25 -04:00
|
|
|
),
|
2022-08-01 09:24:19 +07:00
|
|
|
scrollBehavior = scrollBehavior,
|
2022-07-18 18:32:25 -04:00
|
|
|
)
|
|
|
|
|
2022-09-18 16:08:50 -04:00
|
|
|
AppStateBanners(downloadedOnlyMode, incognitoMode)
|
2022-07-18 18:32:25 -04:00
|
|
|
}
|
2022-07-16 17:58:43 -04:00
|
|
|
}
|
|
|
|
|
2022-04-24 10:22:22 -04:00
|
|
|
@Composable
|
|
|
|
fun AppBarTitle(
|
|
|
|
title: String?,
|
|
|
|
subtitle: String? = null,
|
|
|
|
) {
|
|
|
|
Column {
|
|
|
|
title?.let {
|
|
|
|
Text(
|
|
|
|
text = it,
|
|
|
|
maxLines = 1,
|
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
subtitle?.let {
|
|
|
|
Text(
|
|
|
|
text = it,
|
2022-04-24 14:39:51 -04:00
|
|
|
style = MaterialTheme.typography.bodyMedium,
|
2022-04-24 10:22:22 -04:00
|
|
|
maxLines = 1,
|
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun AppBarActions(
|
|
|
|
actions: List<AppBar.AppBarAction>,
|
|
|
|
) {
|
|
|
|
var showMenu by remember { mutableStateOf(false) }
|
|
|
|
|
|
|
|
actions.filterIsInstance<AppBar.Action>().map {
|
|
|
|
IconButton(
|
|
|
|
onClick = it.onClick,
|
2022-04-24 14:39:51 -04:00
|
|
|
enabled = it.enabled,
|
2022-04-24 10:22:22 -04:00
|
|
|
) {
|
|
|
|
Icon(
|
|
|
|
imageVector = it.icon,
|
|
|
|
contentDescription = it.title,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
val overflowActions = actions.filterIsInstance<AppBar.OverflowAction>()
|
|
|
|
if (overflowActions.isNotEmpty()) {
|
|
|
|
IconButton(onClick = { showMenu = !showMenu }) {
|
|
|
|
Icon(Icons.Default.MoreVert, contentDescription = stringResource(R.string.label_more))
|
|
|
|
}
|
|
|
|
|
|
|
|
DropdownMenu(
|
|
|
|
expanded = showMenu,
|
2022-04-24 14:39:51 -04:00
|
|
|
onDismissRequest = { showMenu = false },
|
2022-04-24 10:22:22 -04:00
|
|
|
) {
|
|
|
|
overflowActions.map {
|
|
|
|
DropdownMenuItem(
|
|
|
|
onClick = {
|
|
|
|
it.onClick()
|
|
|
|
showMenu = false
|
|
|
|
},
|
2022-06-15 18:02:08 -04:00
|
|
|
text = { Text(it.title, fontWeight = FontWeight.Normal) },
|
2022-04-24 10:22:22 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-29 16:39:35 -04:00
|
|
|
@Composable
|
|
|
|
fun SearchToolbar(
|
|
|
|
searchQuery: String,
|
|
|
|
onChangeSearchQuery: (String) -> Unit,
|
2022-09-27 19:05:10 -03:00
|
|
|
placeholderText: String? = null,
|
2022-08-31 22:47:07 +02:00
|
|
|
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
|
|
|
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
2022-08-29 16:39:35 -04:00
|
|
|
onClickCloseSearch: () -> Unit,
|
|
|
|
onClickResetSearch: () -> Unit,
|
|
|
|
incognitoMode: Boolean = false,
|
|
|
|
downloadedOnlyMode: Boolean = false,
|
|
|
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
2022-09-27 19:05:10 -03:00
|
|
|
visualTransformation: VisualTransformation = VisualTransformation.None,
|
|
|
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
2022-08-29 16:39:35 -04:00
|
|
|
) {
|
2022-09-28 04:44:06 +07:00
|
|
|
val focusRequester = remember { FocusRequester() }
|
2022-09-27 19:05:10 -03:00
|
|
|
|
2022-08-29 16:39:35 -04:00
|
|
|
AppBar(
|
|
|
|
titleContent = {
|
|
|
|
BasicTextField(
|
|
|
|
value = searchQuery,
|
|
|
|
onValueChange = onChangeSearchQuery,
|
|
|
|
modifier = Modifier
|
|
|
|
.fillMaxWidth()
|
|
|
|
.focusRequester(focusRequester),
|
2022-09-27 19:05:10 -03:00
|
|
|
textStyle = MaterialTheme.typography.titleMedium.copy(
|
|
|
|
color = MaterialTheme.colorScheme.onBackground,
|
|
|
|
fontWeight = FontWeight.Normal,
|
|
|
|
fontSize = 18.sp,
|
|
|
|
),
|
2022-08-31 22:47:07 +02:00
|
|
|
keyboardOptions = keyboardOptions,
|
|
|
|
keyboardActions = keyboardActions,
|
2022-08-29 16:39:35 -04:00
|
|
|
singleLine = true,
|
|
|
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
|
2022-09-27 19:05:10 -03:00
|
|
|
visualTransformation = visualTransformation,
|
|
|
|
interactionSource = interactionSource,
|
|
|
|
decorationBox = { innerTextField ->
|
|
|
|
TextFieldDefaults.TextFieldDecorationBox(
|
|
|
|
value = searchQuery,
|
|
|
|
innerTextField = innerTextField,
|
|
|
|
enabled = true,
|
|
|
|
singleLine = true,
|
|
|
|
visualTransformation = visualTransformation,
|
|
|
|
interactionSource = interactionSource,
|
|
|
|
placeholder = {
|
|
|
|
if (!placeholderText.isNullOrEmpty()) {
|
|
|
|
Text(
|
|
|
|
text = placeholderText,
|
|
|
|
maxLines = 1,
|
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
|
style = MaterialTheme.typography.titleMedium.copy(
|
|
|
|
fontSize = 18.sp,
|
|
|
|
fontWeight = FontWeight.Normal,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
},
|
2022-08-29 16:39:35 -04:00
|
|
|
)
|
|
|
|
},
|
|
|
|
navigationIcon = Icons.Outlined.ArrowBack,
|
|
|
|
navigateUp = onClickCloseSearch,
|
|
|
|
actions = {
|
|
|
|
AnimatedVisibility(visible = searchQuery.isNotEmpty()) {
|
|
|
|
IconButton(onClick = onClickResetSearch) {
|
|
|
|
Icon(Icons.Outlined.Close, contentDescription = stringResource(R.string.action_reset))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
isActionMode = false,
|
|
|
|
downloadedOnlyMode = downloadedOnlyMode,
|
|
|
|
incognitoMode = incognitoMode,
|
|
|
|
scrollBehavior = scrollBehavior,
|
|
|
|
)
|
|
|
|
LaunchedEffect(focusRequester) {
|
|
|
|
focusRequester.requestFocus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-15 18:02:08 -04:00
|
|
|
sealed interface AppBar {
|
|
|
|
sealed interface AppBarAction
|
2022-04-24 10:22:22 -04:00
|
|
|
|
|
|
|
data class Action(
|
|
|
|
val title: String,
|
|
|
|
val icon: ImageVector,
|
|
|
|
val onClick: () -> Unit,
|
2022-04-24 14:39:51 -04:00
|
|
|
val enabled: Boolean = true,
|
2022-04-24 10:22:22 -04:00
|
|
|
) : AppBarAction
|
|
|
|
|
|
|
|
data class OverflowAction(
|
|
|
|
val title: String,
|
|
|
|
val onClick: () -> Unit,
|
|
|
|
) : AppBarAction
|
|
|
|
}
|