tachiyomi/app/src/main/java/eu/kanade/presentation/track/TrackInfoDialogSelector.kt

252 lines
9.1 KiB
Kotlin
Raw Normal View History

package eu.kanade.presentation.track
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
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.DatePicker
2023-07-27 04:33:10 +02:00
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.SelectableDates
2023-11-05 16:34:19 +01:00
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
2023-02-21 16:41:56 +01:00
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
2023-11-05 16:34:19 +01:00
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import dev.icerock.moko.resources.StringResource
import eu.kanade.presentation.theme.TachiyomiTheme
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
2023-04-15 15:26:33 +02:00
import tachiyomi.presentation.core.components.WheelNumberPicker
import tachiyomi.presentation.core.components.WheelTextPicker
import tachiyomi.presentation.core.components.material.AlertDialogContent
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.isScrolledToEnd
import tachiyomi.presentation.core.util.isScrolledToStart
@Composable
fun TrackStatusSelector(
selection: Int,
onSelectionChange: (Int) -> Unit,
selections: Map<Int, StringResource?>,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
BaseSelector(
title = stringResource(MR.strings.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()
2023-02-21 16:41:56 +01:00
.minimumInteractiveComponentSize(),
) {
RadioButton(
selected = isSelected,
onClick = null,
)
Text(
text = value?.let { stringResource(it) } ?: "",
style = MaterialTheme.typography.bodyLarge.merge(),
modifier = Modifier.padding(start = 24.dp),
)
}
}
}
}
2023-07-27 04:33:10 +02:00
if (!state.isScrolledToStart()) HorizontalDivider(modifier = Modifier.align(Alignment.TopCenter))
if (!state.isScrolledToEnd()) HorizontalDivider(modifier = Modifier.align(Alignment.BottomCenter))
},
onConfirm = onConfirm,
onDismissRequest = onDismissRequest,
)
}
@Composable
fun TrackChapterSelector(
selection: Int,
onSelectionChange: (Int) -> Unit,
range: Iterable<Int>,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
BaseSelector(
title = stringResource(MR.strings.chapters),
content = {
2023-04-15 15:26:33 +02:00
WheelNumberPicker(
items = range.toImmutableList(),
modifier = Modifier.align(Alignment.Center),
startIndex = selection,
onSelectionChanged = { onSelectionChange(it) },
)
},
onConfirm = onConfirm,
onDismissRequest = onDismissRequest,
)
}
@Composable
fun TrackScoreSelector(
selection: String,
onSelectionChange: (String) -> Unit,
selections: ImmutableList<String>,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
) {
BaseSelector(
title = stringResource(MR.strings.score),
content = {
WheelTextPicker(
items = selections,
modifier = Modifier.align(Alignment.Center),
startIndex = selections.indexOf(selection).takeIf { it > 0 } ?: (selections.size / 2),
onSelectionChanged = { onSelectionChange(selections[it]) },
)
},
onConfirm = onConfirm,
onDismissRequest = onDismissRequest,
)
}
@Composable
fun TrackDateSelector(
title: String,
initialSelectedDateMillis: Long,
selectableDates: SelectableDates,
onConfirm: (Long) -> Unit,
onRemove: (() -> Unit)?,
onDismissRequest: () -> Unit,
) {
val pickerState = rememberDatePickerState(
initialSelectedDateMillis = initialSelectedDateMillis,
selectableDates = selectableDates,
)
AlertDialogContent(
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
2023-03-24 03:19:43 +01:00
title = { Text(text = title) },
content = {
Column {
DatePicker(
state = pickerState,
2023-03-24 03:19:43 +01:00
title = null,
headline = null,
showModeToggle = false,
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 12.dp, top = 8.dp, end = 12.dp, bottom = 24.dp),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small, Alignment.End),
) {
if (onRemove != null) {
TextButton(onClick = onRemove) {
Text(text = stringResource(MR.strings.action_remove))
}
Spacer(modifier = Modifier.weight(1f))
}
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(MR.strings.action_cancel))
}
TextButton(onClick = { onConfirm(pickerState.selectedDateMillis!!) }) {
Text(text = stringResource(MR.strings.action_ok))
}
}
}
},
)
}
@Composable
private fun BaseSelector(
title: String,
content: @Composable BoxScope.() -> Unit,
onConfirm: () -> Unit,
onDismissRequest: () -> Unit,
2023-11-17 15:46:13 +01:00
thirdButton: @Composable (RowScope.() -> Unit)? = null,
) {
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(MR.strings.action_cancel))
}
TextButton(onClick = onConfirm) {
Text(text = stringResource(MR.strings.action_ok))
}
}
},
)
}
2023-11-05 16:34:19 +01:00
@PreviewLightDark
@Composable
private fun TrackStatusSelectorPreviews() {
TachiyomiTheme {
2023-11-05 16:34:19 +01:00
Surface {
TrackStatusSelector(
selection = 1,
onSelectionChange = {},
selections = persistentMapOf(
2023-11-05 16:34:19 +01:00
// Anilist values
1 to MR.strings.reading,
2 to MR.strings.plan_to_read,
3 to MR.strings.completed,
4 to MR.strings.on_hold,
5 to MR.strings.dropped,
6 to MR.strings.repeating,
2023-11-05 16:34:19 +01:00
),
onConfirm = {},
onDismissRequest = {},
)
}
}
}