package eu.kanade.presentation.manga import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import eu.kanade.presentation.components.ScrollbarLazyColumn import eu.kanade.presentation.components.WheelDatePicker import eu.kanade.presentation.components.WheelTextPicker import eu.kanade.presentation.util.isScrolledToEnd import eu.kanade.presentation.util.isScrolledToStart import eu.kanade.presentation.util.minimumTouchTargetSize import eu.kanade.presentation.util.padding import eu.kanade.tachiyomi.R import tachiyomi.presentation.core.components.material.AlertDialogContent import tachiyomi.presentation.core.components.material.Divider import java.time.LocalDate import java.time.format.TextStyle @Composable fun TrackStatusSelector( selection: Int, onSelectionChange: (Int) -> Unit, selections: Map, onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { BaseSelector( title = stringResource(R.string.status), content = { val state = rememberLazyListState() ScrollbarLazyColumn(state = state) { selections.forEach { (key, value) -> val isSelected = selection == key item { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier .clip(RoundedCornerShape(8.dp)) .selectable( selected = isSelected, onClick = { onSelectionChange(key) }, ) .fillMaxWidth() .minimumTouchTargetSize(), ) { RadioButton( selected = isSelected, onClick = null, ) Text( text = value, style = MaterialTheme.typography.bodyLarge.merge(), modifier = Modifier.padding(start = 24.dp), ) } } } } if (!state.isScrolledToStart()) Divider(modifier = Modifier.align(Alignment.TopCenter)) if (!state.isScrolledToEnd()) Divider(modifier = Modifier.align(Alignment.BottomCenter)) }, onConfirm = onConfirm, onDismissRequest = onDismissRequest, ) } @Composable fun TrackChapterSelector( selection: Int, onSelectionChange: (Int) -> Unit, range: Iterable, onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { BaseSelector( title = stringResource(R.string.chapters), content = { WheelTextPicker( modifier = Modifier.align(Alignment.Center), startIndex = selection, texts = range.map { "$it" }, onSelectionChanged = { onSelectionChange(it) }, ) }, onConfirm = onConfirm, onDismissRequest = onDismissRequest, ) } @Composable fun TrackScoreSelector( selection: String, onSelectionChange: (String) -> Unit, selections: List, onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { BaseSelector( title = stringResource(R.string.score), content = { WheelTextPicker( modifier = Modifier.align(Alignment.Center), startIndex = selections.indexOf(selection).coerceAtLeast(0), texts = selections, onSelectionChanged = { onSelectionChange(selections[it]) }, ) }, onConfirm = onConfirm, onDismissRequest = onDismissRequest, ) } @Composable fun TrackDateSelector( title: String, minDate: LocalDate?, maxDate: LocalDate?, selection: LocalDate, onSelectionChange: (LocalDate) -> Unit, onConfirm: () -> Unit, onRemove: (() -> Unit)?, onDismissRequest: () -> Unit, ) { BaseSelector( title = title, content = { Row( modifier = Modifier.align(Alignment.Center), verticalAlignment = Alignment.CenterVertically, ) { var internalSelection by remember { mutableStateOf(selection) } Text( modifier = Modifier .weight(1f) .padding(end = 16.dp), text = internalSelection.dayOfWeek .getDisplayName(TextStyle.SHORT, java.util.Locale.getDefault()), textAlign = TextAlign.Center, style = MaterialTheme.typography.titleMedium, ) WheelDatePicker( startDate = selection, minDate = minDate, maxDate = maxDate, onSelectionChanged = { internalSelection = it onSelectionChange(it) }, ) } }, thirdButton = if (onRemove != null) { { TextButton(onClick = onRemove) { Text(text = stringResource(R.string.action_remove)) } } } else { null }, onConfirm = onConfirm, onDismissRequest = onDismissRequest, ) } @Composable private fun BaseSelector( title: String, content: @Composable BoxScope.() -> Unit, thirdButton: @Composable (RowScope.() -> Unit)? = null, onConfirm: () -> Unit, onDismissRequest: () -> Unit, ) { AlertDialogContent( modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars), title = { Text(text = title) }, text = { Box( modifier = Modifier.fillMaxWidth(), content = content, ) }, buttons = { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small, Alignment.End), ) { if (thirdButton != null) { thirdButton() Spacer(modifier = Modifier.weight(1f)) } TextButton(onClick = onDismissRequest) { Text(text = stringResource(android.R.string.cancel)) } TextButton(onClick = onConfirm) { Text(text = stringResource(android.R.string.ok)) } } }, ) }