2023-02-18 22:33:03 +01:00
|
|
|
package eu.kanade.presentation.track
|
2022-11-10 04:31:56 +01:00
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
|
|
import androidx.compose.foundation.layout.Box
|
|
|
|
import androidx.compose.foundation.layout.BoxScope
|
2023-02-24 21:22:23 +01:00
|
|
|
import androidx.compose.foundation.layout.Column
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
import androidx.compose.foundation.layout.RowScope
|
|
|
|
import androidx.compose.foundation.layout.Spacer
|
2022-12-04 16:27:02 +01:00
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
import androidx.compose.foundation.layout.padding
|
2022-12-04 16:27:02 +01:00
|
|
|
import androidx.compose.foundation.layout.systemBars
|
|
|
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
|
|
import androidx.compose.foundation.selection.selectable
|
|
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
2023-02-24 21:22:23 +01:00
|
|
|
import androidx.compose.material3.DatePicker
|
2023-07-27 04:33:10 +02:00
|
|
|
import androidx.compose.material3.HorizontalDivider
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
import androidx.compose.material3.RadioButton
|
2023-05-21 17:11:33 +02:00
|
|
|
import androidx.compose.material3.SelectableDates
|
2023-11-05 16:34:19 +01:00
|
|
|
import androidx.compose.material3.Surface
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.material3.Text
|
|
|
|
import androidx.compose.material3.TextButton
|
2023-02-21 16:41:56 +01:00
|
|
|
import androidx.compose.material3.minimumInteractiveComponentSize
|
2023-02-24 21:22:23 +01:00
|
|
|
import androidx.compose.material3.rememberDatePickerState
|
2022-11-10 04:31:56 +01:00
|
|
|
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
|
2022-11-10 04:31:56 +01:00
|
|
|
import androidx.compose.ui.unit.dp
|
2023-11-18 19:54:56 +01:00
|
|
|
import dev.icerock.moko.resources.StringResource
|
2023-10-22 15:30:34 +02:00
|
|
|
import eu.kanade.presentation.theme.TachiyomiTheme
|
2023-11-12 04:43:50 +01:00
|
|
|
import kotlinx.collections.immutable.ImmutableList
|
2023-12-26 00:11:22 +01:00
|
|
|
import kotlinx.collections.immutable.persistentMapOf
|
2023-11-12 04:43:50 +01:00
|
|
|
import kotlinx.collections.immutable.toImmutableList
|
2023-11-18 19:54:56 +01:00
|
|
|
import tachiyomi.i18n.MR
|
2023-02-18 22:33:03 +01:00
|
|
|
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
2023-04-15 15:26:33 +02:00
|
|
|
import tachiyomi.presentation.core.components.WheelNumberPicker
|
2023-02-18 22:33:03 +01:00
|
|
|
import tachiyomi.presentation.core.components.WheelTextPicker
|
2023-02-18 21:52:52 +01:00
|
|
|
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
2023-02-18 22:03:01 +01:00
|
|
|
import tachiyomi.presentation.core.components.material.padding
|
2023-11-19 01:41:33 +01:00
|
|
|
import tachiyomi.presentation.core.i18n.stringResource
|
2023-02-18 22:33:03 +01:00
|
|
|
import tachiyomi.presentation.core.util.isScrolledToEnd
|
|
|
|
import tachiyomi.presentation.core.util.isScrolledToStart
|
2022-11-10 04:31:56 +01:00
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun TrackStatusSelector(
|
|
|
|
selection: Int,
|
|
|
|
onSelectionChange: (Int) -> Unit,
|
2023-11-18 19:54:56 +01:00
|
|
|
selections: Map<Int, StringResource?>,
|
2022-11-10 04:31:56 +01:00
|
|
|
onConfirm: () -> Unit,
|
|
|
|
onDismissRequest: () -> Unit,
|
|
|
|
) {
|
|
|
|
BaseSelector(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.status),
|
2022-11-10 04:31:56 +01:00
|
|
|
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(),
|
2022-11-10 04:31:56 +01:00
|
|
|
) {
|
|
|
|
RadioButton(
|
|
|
|
selected = isSelected,
|
|
|
|
onClick = null,
|
|
|
|
)
|
|
|
|
Text(
|
2023-11-19 01:41:33 +01:00
|
|
|
text = value?.let { stringResource(it) } ?: "",
|
2022-11-10 04:31:56 +01:00
|
|
|
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))
|
2022-11-10 04:31:56 +01:00
|
|
|
},
|
|
|
|
onConfirm = onConfirm,
|
|
|
|
onDismissRequest = onDismissRequest,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun TrackChapterSelector(
|
|
|
|
selection: Int,
|
|
|
|
onSelectionChange: (Int) -> Unit,
|
|
|
|
range: Iterable<Int>,
|
|
|
|
onConfirm: () -> Unit,
|
|
|
|
onDismissRequest: () -> Unit,
|
|
|
|
) {
|
|
|
|
BaseSelector(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.chapters),
|
2022-11-10 04:31:56 +01:00
|
|
|
content = {
|
2023-04-15 15:26:33 +02:00
|
|
|
WheelNumberPicker(
|
2023-11-12 04:43:50 +01:00
|
|
|
items = range.toImmutableList(),
|
2022-11-10 04:31:56 +01:00
|
|
|
modifier = Modifier.align(Alignment.Center),
|
|
|
|
startIndex = selection,
|
2023-02-13 05:10:47 +01:00
|
|
|
onSelectionChanged = { onSelectionChange(it) },
|
2022-11-10 04:31:56 +01:00
|
|
|
)
|
|
|
|
},
|
|
|
|
onConfirm = onConfirm,
|
|
|
|
onDismissRequest = onDismissRequest,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun TrackScoreSelector(
|
|
|
|
selection: String,
|
|
|
|
onSelectionChange: (String) -> Unit,
|
2023-11-12 04:43:50 +01:00
|
|
|
selections: ImmutableList<String>,
|
2022-11-10 04:31:56 +01:00
|
|
|
onConfirm: () -> Unit,
|
|
|
|
onDismissRequest: () -> Unit,
|
|
|
|
) {
|
|
|
|
BaseSelector(
|
2023-11-19 01:41:33 +01:00
|
|
|
title = stringResource(MR.strings.score),
|
2022-11-10 04:31:56 +01:00
|
|
|
content = {
|
|
|
|
WheelTextPicker(
|
2023-11-12 00:13:44 +01:00
|
|
|
items = selections,
|
2022-11-10 04:31:56 +01:00
|
|
|
modifier = Modifier.align(Alignment.Center),
|
2023-06-24 16:37:20 +02:00
|
|
|
startIndex = selections.indexOf(selection).takeIf { it > 0 } ?: (selections.size / 2),
|
2023-02-13 05:10:47 +01:00
|
|
|
onSelectionChanged = { onSelectionChange(selections[it]) },
|
2022-11-10 04:31:56 +01:00
|
|
|
)
|
|
|
|
},
|
|
|
|
onConfirm = onConfirm,
|
|
|
|
onDismissRequest = onDismissRequest,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
fun TrackDateSelector(
|
|
|
|
title: String,
|
2023-02-24 21:22:23 +01:00
|
|
|
initialSelectedDateMillis: Long,
|
2023-05-21 17:11:33 +02:00
|
|
|
selectableDates: SelectableDates,
|
2023-02-24 21:22:23 +01:00
|
|
|
onConfirm: (Long) -> Unit,
|
2022-11-10 04:31:56 +01:00
|
|
|
onRemove: (() -> Unit)?,
|
|
|
|
onDismissRequest: () -> Unit,
|
|
|
|
) {
|
2023-02-24 21:22:23 +01:00
|
|
|
val pickerState = rememberDatePickerState(
|
|
|
|
initialSelectedDateMillis = initialSelectedDateMillis,
|
2023-05-21 17:11:33 +02:00
|
|
|
selectableDates = selectableDates,
|
2023-02-24 21:22:23 +01:00
|
|
|
)
|
|
|
|
AlertDialogContent(
|
|
|
|
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
2023-03-24 03:19:43 +01:00
|
|
|
title = { Text(text = title) },
|
2022-11-10 04:31:56 +01:00
|
|
|
content = {
|
2023-02-24 21:22:23 +01:00
|
|
|
Column {
|
|
|
|
DatePicker(
|
|
|
|
state = pickerState,
|
2023-03-24 03:19:43 +01:00
|
|
|
title = null,
|
|
|
|
headline = null,
|
2023-02-24 21:22:23 +01:00
|
|
|
showModeToggle = false,
|
2022-11-10 04:31:56 +01:00
|
|
|
)
|
2023-02-24 21:22:23 +01:00
|
|
|
|
|
|
|
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) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_remove))
|
2023-02-24 21:22:23 +01:00
|
|
|
}
|
|
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
}
|
|
|
|
TextButton(onClick = onDismissRequest) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_cancel))
|
2023-02-24 21:22:23 +01:00
|
|
|
}
|
|
|
|
TextButton(onClick = { onConfirm(pickerState.selectedDateMillis!!) }) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_ok))
|
2023-02-24 21:22:23 +01:00
|
|
|
}
|
2022-11-10 04:31:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@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,
|
2022-11-10 04:31:56 +01:00
|
|
|
) {
|
|
|
|
AlertDialogContent(
|
2022-12-04 16:27:02 +01:00
|
|
|
modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars),
|
2022-11-10 04:31:56 +01:00
|
|
|
title = { Text(text = title) },
|
|
|
|
text = {
|
|
|
|
Box(
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
content = content,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
buttons = {
|
|
|
|
Row(
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
2023-01-08 21:40:43 +01:00
|
|
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small, Alignment.End),
|
2022-11-10 04:31:56 +01:00
|
|
|
) {
|
|
|
|
if (thirdButton != null) {
|
|
|
|
thirdButton()
|
|
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
}
|
|
|
|
TextButton(onClick = onDismissRequest) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_cancel))
|
2022-11-10 04:31:56 +01:00
|
|
|
}
|
|
|
|
TextButton(onClick = onConfirm) {
|
2023-11-19 01:41:33 +01:00
|
|
|
Text(text = stringResource(MR.strings.action_ok))
|
2022-11-10 04:31:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2023-10-22 15:30:34 +02:00
|
|
|
|
2023-11-05 16:34:19 +01:00
|
|
|
@PreviewLightDark
|
2023-10-22 15:30:34 +02:00
|
|
|
@Composable
|
|
|
|
private fun TrackStatusSelectorPreviews() {
|
|
|
|
TachiyomiTheme {
|
2023-11-05 16:34:19 +01:00
|
|
|
Surface {
|
|
|
|
TrackStatusSelector(
|
|
|
|
selection = 1,
|
|
|
|
onSelectionChange = {},
|
2023-12-26 00:11:22 +01:00
|
|
|
selections = persistentMapOf(
|
2023-11-05 16:34:19 +01:00
|
|
|
// Anilist values
|
2023-11-18 19:54:56 +01:00
|
|
|
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 = {},
|
|
|
|
)
|
|
|
|
}
|
2023-10-22 15:30:34 +02:00
|
|
|
}
|
|
|
|
}
|