From c53172265b4dfba380a096c8d9107358515bf0e1 Mon Sep 17 00:00:00 2001 From: arkon Date: Sat, 21 Oct 2023 09:42:12 -0400 Subject: [PATCH] Consistent labeled checkbox composable --- .../history/components/HistoryDialogs.kt | 39 +++----- .../library/DeleteLibraryMangaDialog.kt | 40 +++----- .../manga/ChapterSettingsDialog.kt | 26 ++--- .../settings/screen/SettingsBackupScreen.kt | 53 +++-------- .../widget/MultiSelectListPreferenceWidget.kt | 50 +++------- .../browse/migration/search/MigrateDialog.kt | 21 ++--- .../ui/manga/track/TrackInfoDialog.kt | 94 +++++++++---------- .../core/components/LabeledCheckbox.kt | 44 +++++++++ 8 files changed, 151 insertions(+), 216 deletions(-) create mode 100644 presentation-core/src/main/java/tachiyomi/presentation/core/components/LabeledCheckbox.kt diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt index 40d3ecfa75..0ceab8f610 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryDialogs.kt @@ -1,12 +1,8 @@ package eu.kanade.presentation.history.components -import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.selection.toggleable import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -14,12 +10,11 @@ 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.res.stringResource import androidx.compose.ui.unit.dp import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.tachiyomi.R +import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.util.ThemePreviews @Composable @@ -34,28 +29,16 @@ fun HistoryDeleteDialog( Text(text = stringResource(R.string.action_remove)) }, text = { - Column { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { Text(text = stringResource(R.string.dialog_with_checkbox_remove_description)) - Row( - modifier = Modifier - .padding(top = 16.dp) - .toggleable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - value = removeEverything, - onValueChange = { removeEverything = it }, - ), - verticalAlignment = Alignment.CenterVertically, - ) { - Checkbox( - checked = removeEverything, - onCheckedChange = null, - ) - Text( - modifier = Modifier.padding(start = 4.dp), - text = stringResource(R.string.dialog_with_checkbox_reset), - ) - } + + LabeledCheckbox( + label = stringResource(R.string.dialog_with_checkbox_reset), + checked = removeEverything, + onCheckedChange = { removeEverything = it }, + ) } }, onDismissRequest = onDismissRequest, diff --git a/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt b/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt index 1f6317a972..49a9a8360b 100644 --- a/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/DeleteLibraryMangaDialog.kt @@ -1,11 +1,7 @@ package eu.kanade.presentation.library -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -13,11 +9,10 @@ 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.res.stringResource import eu.kanade.tachiyomi.R import tachiyomi.core.preference.CheckboxState +import tachiyomi.presentation.core.components.LabeledCheckbox @Composable fun DeleteLibraryMangaDialog( @@ -62,27 +57,18 @@ fun DeleteLibraryMangaDialog( text = { Column { list.forEach { state -> - val onCheck = { - val index = list.indexOf(state) - if (index != -1) { - val mutableList = list.toMutableList() - mutableList[index] = state.next() as CheckboxState.State - list = mutableList.toList() - } - } - - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { onCheck() }, - verticalAlignment = Alignment.CenterVertically, - ) { - Checkbox( - checked = state.isChecked, - onCheckedChange = { onCheck() }, - ) - Text(text = stringResource(state.value)) - } + LabeledCheckbox( + label = stringResource(state.value), + checked = state.isChecked, + onCheckedChange = { + val index = list.indexOf(state) + if (index != -1) { + val mutableList = list.toMutableList() + mutableList[index] = state.next() as CheckboxState.State + list = mutableList.toList() + } + }, + ) } } }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt index 7cfcbf0530..9f842fead5 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt @@ -1,16 +1,12 @@ package eu.kanade.presentation.manga -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -19,7 +15,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -30,6 +25,7 @@ import eu.kanade.presentation.components.TabbedDialogPaddings import eu.kanade.tachiyomi.R import tachiyomi.core.preference.TriState import tachiyomi.domain.manga.model.Manga +import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.RadioItem import tachiyomi.presentation.core.components.SortItem import tachiyomi.presentation.core.components.TriStateItem @@ -172,6 +168,7 @@ private fun SetAsDefaultDialog( onConfirmed: (optionalChecked: Boolean) -> Unit, ) { var optionalChecked by rememberSaveable { mutableStateOf(false) } + AlertDialog( onDismissRequest = onDismissRequest, title = { Text(text = stringResource(R.string.chapter_settings)) }, @@ -181,20 +178,11 @@ private fun SetAsDefaultDialog( ) { Text(text = stringResource(R.string.confirm_set_chapter_settings)) - Row( - modifier = Modifier - .clickable { optionalChecked = !optionalChecked } - .padding(vertical = 8.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(12.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Checkbox( - checked = optionalChecked, - onCheckedChange = null, - ) - Text(text = stringResource(R.string.also_set_chapter_settings_for_library)) - } + LabeledCheckbox( + label = stringResource(R.string.also_set_chapter_settings_for_library), + checked = optionalChecked, + onCheckedChange = { optionalChecked = it }, + ) } }, dismissButton = { diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt index 3bd36f9b4b..e35acffe07 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBackupScreen.kt @@ -8,20 +8,13 @@ import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.StringRes -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -38,7 +31,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import androidx.core.net.toUri import com.hippo.unifile.UniFile import eu.kanade.presentation.extensions.RequestStoragePermission @@ -55,6 +47,7 @@ import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.launch import tachiyomi.domain.backup.service.BackupPreferences +import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.util.collectAsState import tachiyomi.presentation.core.util.isScrolledToEnd @@ -160,22 +153,23 @@ object SettingsBackupScreen : SearchableSettings { val state = rememberLazyListState() ScrollbarLazyColumn(state = state) { item { - CreateBackupDialogItem( - isSelected = true, - title = stringResource(R.string.manga), + LabeledCheckbox( + label = stringResource(R.string.manga), + checked = true, + onCheckedChange = {}, ) } choices.forEach { (k, v) -> item { val isSelected = flags.contains(k) - CreateBackupDialogItem( - isSelected = isSelected, - title = stringResource(v), - modifier = Modifier.clickable { - if (isSelected) { - flags.remove(k) - } else { + LabeledCheckbox( + label = stringResource(v), + checked = isSelected, + onCheckedChange = { + if (it) { flags.add(k) + } else { + flags.remove(k) } }, ) @@ -204,29 +198,6 @@ object SettingsBackupScreen : SearchableSettings { ) } - @Composable - private fun CreateBackupDialogItem( - modifier: Modifier = Modifier, - isSelected: Boolean, - title: String, - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = modifier.fillMaxWidth(), - ) { - Checkbox( - modifier = Modifier.heightIn(min = 48.dp), - checked = isSelected, - onCheckedChange = null, - ) - Text( - text = title, - style = MaterialTheme.typography.bodyMedium.merge(), - modifier = Modifier.padding(start = 24.dp), - ) - } - } - @Composable private fun getRestoreBackupPref(): Preference.PreferenceItem.TextPreference { val context = LocalContext.current diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt b/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt index 74ed60e012..3059be939e 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/widget/MultiSelectListPreferenceWidget.kt @@ -1,30 +1,20 @@ package eu.kanade.presentation.more.settings.widget -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.selection.selectable import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.minimumInteractiveComponentSize 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.runtime.toMutableStateList -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.unit.dp import androidx.compose.ui.window.DialogProperties import eu.kanade.presentation.more.settings.Preference import eu.kanade.tachiyomi.R +import tachiyomi.presentation.core.components.LabeledCheckbox @Composable fun MultiSelectListPreferenceWidget( @@ -55,33 +45,17 @@ fun MultiSelectListPreferenceWidget( preference.entries.forEach { current -> item { val isSelected = selected.contains(current.key) - val onSelectionChanged = { - when (!isSelected) { - true -> selected.add(current.key) - false -> selected.remove(current.key) - } - } - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .clip(MaterialTheme.shapes.small) - .selectable( - selected = isSelected, - onClick = { onSelectionChanged() }, - ) - .minimumInteractiveComponentSize() - .fillMaxWidth(), - ) { - Checkbox( - checked = isSelected, - onCheckedChange = null, - ) - Text( - text = current.value, - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(start = 24.dp), - ) - } + LabeledCheckbox( + label = current.value, + checked = isSelected, + onCheckedChange = { + if (it) { + selected.add(current.key) + } else { + selected.remove(current.key) + } + }, + ) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt index ac8964412a..386e8dd803 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt @@ -1,17 +1,13 @@ package eu.kanade.tachiyomi.ui.browse.migration.search import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Checkbox import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -22,7 +18,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.toMutableStateList -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -55,6 +50,7 @@ import tachiyomi.domain.manga.model.MangaUpdate import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.InsertTrack +import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.screens.LoadingScreen import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -92,16 +88,11 @@ internal fun MigrateDialog( modifier = Modifier.verticalScroll(rememberScrollState()), ) { flags.forEachIndexed { index, flag -> - val onChange = { selectedFlags[index] = !selectedFlags[index] } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onChange), - verticalAlignment = Alignment.CenterVertically, - ) { - Checkbox(checked = selectedFlags[index], onCheckedChange = { onChange() }) - Text(text = context.getString(flag.titleId)) - } + LabeledCheckbox( + label = stringResource(flag.titleId), + checked = selectedFlags[index], + onCheckedChange = { selectedFlags[index] = it }, + ) } } }, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt index 1eb97b760a..94e6bbe845 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackInfoDialog.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.manga.track import android.app.Application import android.content.Context -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -13,7 +12,6 @@ import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Delete import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.Checkbox import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -33,6 +31,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope @@ -75,6 +74,7 @@ import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.track.interactor.DeleteTrack import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.model.Track +import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.material.AlertDialogContent import tachiyomi.presentation.core.components.material.padding import uy.kohesive.injekt.Injekt @@ -94,10 +94,10 @@ data class TrackInfoDialogHomeScreen( override fun Content() { val navigator = LocalNavigator.currentOrThrow val context = LocalContext.current - val sm = rememberScreenModel { Model(mangaId, sourceId) } + val screenModel = rememberScreenModel { Model(mangaId, sourceId) } val dateFormat = remember { UiPreferences.dateFormat(Injekt.get().dateFormat().get()) } - val state by sm.state.collectAsState() + val state by screenModel.state.collectAsState() TrackInfoDialogHome( trackItems = state.trackItems, @@ -146,7 +146,7 @@ data class TrackInfoDialogHomeScreen( }, onNewSearch = { if (it.tracker is EnhancedTracker) { - sm.registerEnhancedTracking(it) + screenModel.registerEnhancedTracking(it) } else { navigator.push( TrackerSearchScreen( @@ -261,19 +261,19 @@ private data class TrackStatusSelectorScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( track = track, tracker = Injekt.get().get(serviceId)!!, ) } - val state by sm.state.collectAsState() + val state by screenModel.state.collectAsState() TrackStatusSelector( selection = state.selection, - onSelectionChange = sm::setSelection, - selections = remember { sm.getSelections() }, + onSelectionChange = screenModel::setSelection, + selections = remember { screenModel.getSelections() }, onConfirm = { - sm.setStatus() + screenModel.setStatus() navigator.pop() }, onDismissRequest = navigator::pop, @@ -314,20 +314,20 @@ private data class TrackChapterSelectorScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( track = track, tracker = Injekt.get().get(serviceId)!!, ) } - val state by sm.state.collectAsState() + val state by screenModel.state.collectAsState() TrackChapterSelector( selection = state.selection, - onSelectionChange = sm::setSelection, - range = remember { sm.getRange() }, + onSelectionChange = screenModel::setSelection, + range = remember { screenModel.getRange() }, onConfirm = { - sm.setChapter() + screenModel.setChapter() navigator.pop() }, onDismissRequest = navigator::pop, @@ -373,20 +373,20 @@ private data class TrackScoreSelectorScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( track = track, tracker = Injekt.get().get(serviceId)!!, ) } - val state by sm.state.collectAsState() + val state by screenModel.state.collectAsState() TrackScoreSelector( selection = state.selection, - onSelectionChange = sm::setSelection, - selections = remember { sm.getSelections() }, + onSelectionChange = screenModel::setSelection, + selections = remember { screenModel.getSelections() }, onConfirm = { - sm.setScore() + screenModel.setScore() navigator.pop() }, onDismissRequest = navigator::pop, @@ -484,7 +484,7 @@ private data class TrackDateSelectorScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( track = track, tracker = Injekt.get().get(serviceId)!!, @@ -503,13 +503,13 @@ private data class TrackDateSelectorScreen( } else { stringResource(R.string.track_finished_reading_date) }, - initialSelectedDateMillis = sm.initialSelection, + initialSelectedDateMillis = screenModel.initialSelection, selectableDates = selectableDates, onConfirm = { - sm.setDate(it) + screenModel.setDate(it) navigator.pop() }, - onRemove = { sm.confirmRemoveDate(navigator) }.takeIf { canRemove }, + onRemove = { screenModel.confirmRemoveDate(navigator) }.takeIf { canRemove }, onDismissRequest = navigator::pop, ) } @@ -557,7 +557,7 @@ private data class TrackDateRemoverScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( track = track, tracker = Injekt.get().get(serviceId)!!, @@ -579,7 +579,7 @@ private data class TrackDateRemoverScreen( ) }, text = { - val serviceName = sm.getServiceName() + val serviceName = screenModel.getServiceName() Text( text = if (start) { stringResource(R.string.track_remove_start_date_conf_text, serviceName) @@ -598,7 +598,7 @@ private data class TrackDateRemoverScreen( } FilledTonalButton( onClick = { - sm.removeDate() + screenModel.removeDate() navigator.popUntil { it is TrackInfoDialogHomeScreen } }, colors = ButtonDefaults.filledTonalButtonColors( @@ -643,7 +643,7 @@ data class TrackerSearchScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( mangaId = mangaId, currentUrl = currentUrl, @@ -652,18 +652,18 @@ data class TrackerSearchScreen( ) } - val state by sm.state.collectAsState() + val state by screenModel.state.collectAsState() var textFieldValue by remember { mutableStateOf(TextFieldValue(initialQuery)) } TrackerSearch( query = textFieldValue, onQueryChange = { textFieldValue = it }, - onDispatchQuery = { sm.trackingSearch(textFieldValue.text) }, + onDispatchQuery = { screenModel.trackingSearch(textFieldValue.text) }, queryResult = state.queryResult, selected = state.selected, - onSelectedChange = sm::updateSelection, + onSelectedChange = screenModel::updateSelection, onConfirmSelection = { - sm.registerTracking(state.selected!!) + screenModel.registerTracking(state.selected!!) navigator.pop() }, onDismissRequest = navigator::pop, @@ -731,14 +731,14 @@ private data class TrackerRemoveScreen( @Composable override fun Content() { val navigator = LocalNavigator.currentOrThrow - val sm = rememberScreenModel { + val screenModel = rememberScreenModel { Model( mangaId = mangaId, track = track, tracker = Injekt.get().get(serviceId)!!, ) } - val serviceName = sm.getName() + val serviceName = screenModel.getName() var removeRemoteTrack by remember { mutableStateOf(false) } AlertDialogContent( modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars), @@ -755,21 +755,19 @@ private data class TrackerRemoveScreen( ) }, text = { - Column { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { Text( text = stringResource(R.string.track_delete_text, serviceName), ) - if (sm.isDeletable()) { - val onChange = { removeRemoteTrack = !removeRemoteTrack } - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onChange), - verticalAlignment = Alignment.CenterVertically, - ) { - Checkbox(checked = removeRemoteTrack, onCheckedChange = { onChange() }) - Text(text = stringResource(R.string.track_delete_remote_text, serviceName)) - } + + if (screenModel.isDeletable()) { + LabeledCheckbox( + label = stringResource(R.string.track_delete_remote_text, serviceName), + checked = removeRemoteTrack, + onCheckedChange = { removeRemoteTrack = it }, + ) } } }, @@ -786,8 +784,8 @@ private data class TrackerRemoveScreen( } FilledTonalButton( onClick = { - sm.unregisterTracking(serviceId) - if (removeRemoteTrack) sm.deleteMangaFromService() + screenModel.unregisterTracking(serviceId) + if (removeRemoteTrack) screenModel.deleteMangaFromService() navigator.pop() }, colors = ButtonDefaults.filledTonalButtonColors( diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/LabeledCheckbox.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/LabeledCheckbox.kt new file mode 100644 index 0000000000..0a72e4b0bd --- /dev/null +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/LabeledCheckbox.kt @@ -0,0 +1,44 @@ +package tachiyomi.presentation.core.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.material3.Checkbox +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp + +@Composable +fun LabeledCheckbox( + modifier: Modifier = Modifier, + label: String, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, +) { + Row( + modifier = modifier + .clip(MaterialTheme.shapes.small) + .fillMaxWidth() + .heightIn(min = 48.dp) + .clickable( + role = Role.Checkbox, + onClick = { onCheckedChange(!checked) }, + ), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Checkbox( + checked = checked, + onCheckedChange = null, + ) + + Text(text = label) + } +}