Prechádzať zdrojové kódy

Pull out settings sheet items as reusable composables

arkon 2 rokov pred
rodič
commit
7cbe18d325

+ 128 - 0
app/src/main/java/eu/kanade/presentation/components/SettingsItems.kt

@@ -0,0 +1,128 @@
+package eu.kanade.presentation.components
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowDownward
+import androidx.compose.material.icons.filled.ArrowUpward
+import androidx.compose.material.icons.rounded.CheckBox
+import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
+import androidx.compose.material.icons.rounded.DisabledByDefault
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RadioButton
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import eu.kanade.domain.manga.model.TriStateFilter
+
+@Composable
+fun TriStateItem(
+    label: String,
+    state: TriStateFilter,
+    onClick: ((TriStateFilter) -> Unit)?,
+) {
+    Row(
+        modifier = Modifier
+            .clickable(
+                enabled = onClick != null,
+                onClick = {
+                    when (state) {
+                        TriStateFilter.DISABLED -> onClick?.invoke(TriStateFilter.ENABLED_IS)
+                        TriStateFilter.ENABLED_IS -> onClick?.invoke(TriStateFilter.ENABLED_NOT)
+                        TriStateFilter.ENABLED_NOT -> onClick?.invoke(TriStateFilter.DISABLED)
+                    }
+                },
+            )
+            .fillMaxWidth()
+            .padding(horizontal = TabbedDialogPaddings.Horizontal, vertical = 12.dp),
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement = Arrangement.spacedBy(24.dp),
+    ) {
+        Icon(
+            imageVector = when (state) {
+                TriStateFilter.DISABLED -> Icons.Rounded.CheckBoxOutlineBlank
+                TriStateFilter.ENABLED_IS -> Icons.Rounded.CheckBox
+                TriStateFilter.ENABLED_NOT -> Icons.Rounded.DisabledByDefault
+            },
+            contentDescription = null,
+            tint = if (state == TriStateFilter.DISABLED) {
+                MaterialTheme.colorScheme.onSurfaceVariant
+            } else {
+                MaterialTheme.colorScheme.primary
+            },
+        )
+        Text(
+            text = label,
+            style = MaterialTheme.typography.bodyMedium,
+        )
+    }
+}
+
+@Composable
+fun SortItem(
+    label: String,
+    sortDescending: Boolean?,
+    onClick: () -> Unit,
+) {
+    val arrowIcon = when (sortDescending) {
+        true -> Icons.Default.ArrowDownward
+        false -> Icons.Default.ArrowUpward
+        null -> null
+    }
+
+    Row(
+        modifier = Modifier
+            .clickable(onClick = onClick)
+            .fillMaxWidth()
+            .padding(horizontal = TabbedDialogPaddings.Horizontal, vertical = 12.dp),
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement = Arrangement.spacedBy(24.dp),
+    ) {
+        if (arrowIcon != null) {
+            Icon(
+                imageVector = arrowIcon,
+                contentDescription = null,
+                tint = MaterialTheme.colorScheme.primary,
+            )
+        } else {
+            Spacer(modifier = Modifier.size(24.dp))
+        }
+        Text(
+            text = label,
+            style = MaterialTheme.typography.bodyMedium,
+        )
+    }
+}
+
+@Composable
+fun RadioItem(
+    label: String,
+    selected: Boolean,
+    onClick: () -> Unit,
+) {
+    Row(
+        modifier = Modifier
+            .clickable(onClick = onClick)
+            .fillMaxWidth()
+            .padding(horizontal = TabbedDialogPaddings.Horizontal, vertical = 12.dp),
+        verticalAlignment = Alignment.CenterVertically,
+        horizontalArrangement = Arrangement.spacedBy(24.dp),
+    ) {
+        RadioButton(
+            selected = selected,
+            onClick = null,
+        )
+        Text(
+            text = label,
+            style = MaterialTheme.typography.bodyMedium,
+        )
+    }
+}

+ 6 - 3
app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt

@@ -32,6 +32,11 @@ import androidx.compose.ui.util.fastForEachIndexed
 import eu.kanade.tachiyomi.R
 import kotlinx.coroutines.launch
 
+object TabbedDialogPaddings {
+    val Horizontal = 24.dp
+    val Vertical = 8.dp
+}
+
 @Composable
 fun TabbedDialog(
     onDismissRequest: () -> Unit,
@@ -72,9 +77,7 @@ fun TabbedDialog(
                     }
                 }
 
-                tabOverflowMenuContent?.let {
-                    MoreMenu(tabOverflowMenuContent)
-                }
+                tabOverflowMenuContent?.let { MoreMenu(it) }
             }
             Divider()
 

+ 84 - 218
app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt

@@ -3,26 +3,15 @@ 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.PaddingValues
+import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowDownward
-import androidx.compose.material.icons.filled.ArrowUpward
-import androidx.compose.material.icons.rounded.CheckBox
-import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
-import androidx.compose.material.icons.rounded.DisabledByDefault
 import androidx.compose.material3.AlertDialog
 import androidx.compose.material3.Checkbox
 import androidx.compose.material3.DropdownMenuItem
-import androidx.compose.material3.Icon
-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
@@ -32,12 +21,15 @@ 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.graphics.vector.ImageVector
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.TriStateFilter
+import eu.kanade.presentation.components.RadioItem
+import eu.kanade.presentation.components.SortItem
 import eu.kanade.presentation.components.TabbedDialog
+import eu.kanade.presentation.components.TabbedDialogPaddings
+import eu.kanade.presentation.components.TriStateItem
 import eu.kanade.tachiyomi.R
 
 @Composable
@@ -76,37 +68,41 @@ fun ChapterSettingsDialog(
             )
         },
     ) { contentPadding, page ->
-        when (page) {
-            0 -> {
-                val forceDownloaded = manga?.forceDownloaded() == true
-                FilterPage(
-                    contentPadding = contentPadding,
-                    downloadFilter = if (forceDownloaded) {
-                        TriStateFilter.ENABLED_NOT
-                    } else {
-                        manga?.downloadedFilter
-                    } ?: TriStateFilter.DISABLED,
-                    onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { forceDownloaded },
-                    unreadFilter = manga?.unreadFilter ?: TriStateFilter.DISABLED,
-                    onUnreadFilterChanged = onUnreadFilterChanged,
-                    bookmarkedFilter = manga?.bookmarkedFilter ?: TriStateFilter.DISABLED,
-                    onBookmarkedFilterChanged = onBookmarkedFilterChanged,
-                )
-            }
-            1 -> {
-                SortPage(
-                    contentPadding = contentPadding,
-                    sortingMode = manga?.sorting ?: 0,
-                    sortDescending = manga?.sortDescending() ?: false,
-                    onItemSelected = onSortModeChanged,
-                )
-            }
-            2 -> {
-                DisplayPage(
-                    contentPadding = contentPadding,
-                    displayMode = manga?.displayMode ?: 0,
-                    onItemSelected = onDisplayModeChanged,
-                )
+        Column(
+            modifier = Modifier
+                .padding(contentPadding)
+                .padding(vertical = TabbedDialogPaddings.Vertical)
+                .verticalScroll(rememberScrollState()),
+        ) {
+            when (page) {
+                0 -> {
+                    val forceDownloaded = manga?.forceDownloaded() == true
+                    FilterPage(
+                        downloadFilter = if (forceDownloaded) {
+                            TriStateFilter.ENABLED_NOT
+                        } else {
+                            manga?.downloadedFilter
+                        } ?: TriStateFilter.DISABLED,
+                        onDownloadFilterChanged = onDownloadFilterChanged.takeUnless { forceDownloaded },
+                        unreadFilter = manga?.unreadFilter ?: TriStateFilter.DISABLED,
+                        onUnreadFilterChanged = onUnreadFilterChanged,
+                        bookmarkedFilter = manga?.bookmarkedFilter ?: TriStateFilter.DISABLED,
+                        onBookmarkedFilterChanged = onBookmarkedFilterChanged,
+                    )
+                }
+                1 -> {
+                    SortPage(
+                        sortingMode = manga?.sorting ?: 0,
+                        sortDescending = manga?.sortDescending() ?: false,
+                        onItemSelected = onSortModeChanged,
+                    )
+                }
+                2 -> {
+                    DisplayPage(
+                        displayMode = manga?.displayMode ?: 0,
+                        onItemSelected = onDisplayModeChanged,
+                    )
+                }
             }
         }
     }
@@ -152,6 +148,7 @@ private fun SetAsDefaultDialog(
             TextButton(
                 onClick = {
                     onConfirmed(optionalChecked)
+                    onDismissRequest()
                 },
             ) {
                 Text(text = stringResource(android.R.string.ok))
@@ -161,8 +158,7 @@ private fun SetAsDefaultDialog(
 }
 
 @Composable
-private fun FilterPage(
-    contentPadding: PaddingValues,
+private fun ColumnScope.FilterPage(
     downloadFilter: TriStateFilter,
     onDownloadFilterChanged: ((TriStateFilter) -> Unit)?,
     unreadFilter: TriStateFilter,
@@ -170,189 +166,59 @@ private fun FilterPage(
     bookmarkedFilter: TriStateFilter,
     onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
 ) {
-    Column(
-        modifier = Modifier
-            .padding(vertical = VerticalPadding)
-            .padding(contentPadding)
-            .verticalScroll(rememberScrollState()),
-    ) {
-        FilterPageItem(
-            label = stringResource(R.string.label_downloaded),
-            state = downloadFilter,
-            onClick = onDownloadFilterChanged,
-        )
-        FilterPageItem(
-            label = stringResource(R.string.action_filter_unread),
-            state = unreadFilter,
-            onClick = onUnreadFilterChanged,
-        )
-        FilterPageItem(
-            label = stringResource(R.string.action_filter_bookmarked),
-            state = bookmarkedFilter,
-            onClick = onBookmarkedFilterChanged,
-        )
-    }
-}
-
-@Composable
-private fun FilterPageItem(
-    label: String,
-    state: TriStateFilter,
-    onClick: ((TriStateFilter) -> Unit)?,
-) {
-    Row(
-        modifier = Modifier
-            .clickable(
-                enabled = onClick != null,
-                onClick = {
-                    when (state) {
-                        TriStateFilter.DISABLED -> onClick?.invoke(TriStateFilter.ENABLED_IS)
-                        TriStateFilter.ENABLED_IS -> onClick?.invoke(TriStateFilter.ENABLED_NOT)
-                        TriStateFilter.ENABLED_NOT -> onClick?.invoke(TriStateFilter.DISABLED)
-                    }
-                },
-            )
-            .fillMaxWidth()
-            .padding(horizontal = HorizontalPadding, vertical = 12.dp),
-        verticalAlignment = Alignment.CenterVertically,
-        horizontalArrangement = Arrangement.spacedBy(24.dp),
-    ) {
-        Icon(
-            imageVector = when (state) {
-                TriStateFilter.DISABLED -> Icons.Rounded.CheckBoxOutlineBlank
-                TriStateFilter.ENABLED_IS -> Icons.Rounded.CheckBox
-                TriStateFilter.ENABLED_NOT -> Icons.Rounded.DisabledByDefault
-            },
-            contentDescription = null,
-            tint = if (state == TriStateFilter.DISABLED) {
-                MaterialTheme.colorScheme.onSurfaceVariant
-            } else {
-                MaterialTheme.colorScheme.primary
-            },
-        )
-        Text(
-            text = label,
-            style = MaterialTheme.typography.bodyMedium,
-        )
-    }
+    TriStateItem(
+        label = stringResource(R.string.label_downloaded),
+        state = downloadFilter,
+        onClick = onDownloadFilterChanged,
+    )
+    TriStateItem(
+        label = stringResource(R.string.action_filter_unread),
+        state = unreadFilter,
+        onClick = onUnreadFilterChanged,
+    )
+    TriStateItem(
+        label = stringResource(R.string.action_filter_bookmarked),
+        state = bookmarkedFilter,
+        onClick = onBookmarkedFilterChanged,
+    )
 }
 
 @Composable
-private fun SortPage(
-    contentPadding: PaddingValues,
+private fun ColumnScope.SortPage(
     sortingMode: Long,
     sortDescending: Boolean,
     onItemSelected: (Long) -> Unit,
 ) {
-    Column(
-        modifier = Modifier
-            .padding(contentPadding)
-            .padding(vertical = VerticalPadding)
-            .verticalScroll(rememberScrollState()),
-    ) {
-        val arrowIcon = if (sortDescending) {
-            Icons.Default.ArrowDownward
-        } else {
-            Icons.Default.ArrowUpward
-        }
-
-        SortPageItem(
-            label = stringResource(R.string.sort_by_source),
-            statusIcon = arrowIcon.takeIf { sortingMode == Manga.CHAPTER_SORTING_SOURCE },
-            onClick = { onItemSelected(Manga.CHAPTER_SORTING_SOURCE) },
-        )
-        SortPageItem(
-            label = stringResource(R.string.sort_by_number),
-            statusIcon = arrowIcon.takeIf { sortingMode == Manga.CHAPTER_SORTING_NUMBER },
-            onClick = { onItemSelected(Manga.CHAPTER_SORTING_NUMBER) },
-        )
-        SortPageItem(
-            label = stringResource(R.string.sort_by_upload_date),
-            statusIcon = arrowIcon.takeIf { sortingMode == Manga.CHAPTER_SORTING_UPLOAD_DATE },
-            onClick = { onItemSelected(Manga.CHAPTER_SORTING_UPLOAD_DATE) },
-        )
-    }
-}
-
-@Composable
-private fun SortPageItem(
-    label: String,
-    statusIcon: ImageVector?,
-    onClick: () -> Unit,
-) {
-    Row(
-        modifier = Modifier
-            .clickable(onClick = onClick)
-            .fillMaxWidth()
-            .padding(horizontal = HorizontalPadding, vertical = 12.dp),
-        verticalAlignment = Alignment.CenterVertically,
-        horizontalArrangement = Arrangement.spacedBy(24.dp),
-    ) {
-        if (statusIcon != null) {
-            Icon(
-                imageVector = statusIcon,
-                contentDescription = null,
-                tint = MaterialTheme.colorScheme.primary,
-            )
-        } else {
-            Spacer(modifier = Modifier.size(24.dp))
-        }
-        Text(
-            text = label,
-            style = MaterialTheme.typography.bodyMedium,
-        )
-    }
+    SortItem(
+        label = stringResource(R.string.sort_by_source),
+        sortDescending = sortDescending.takeIf { sortingMode == Manga.CHAPTER_SORTING_SOURCE },
+        onClick = { onItemSelected(Manga.CHAPTER_SORTING_SOURCE) },
+    )
+    SortItem(
+        label = stringResource(R.string.sort_by_number),
+        sortDescending = sortDescending.takeIf { sortingMode == Manga.CHAPTER_SORTING_NUMBER },
+        onClick = { onItemSelected(Manga.CHAPTER_SORTING_NUMBER) },
+    )
+    SortItem(
+        label = stringResource(R.string.sort_by_upload_date),
+        sortDescending = sortDescending.takeIf { sortingMode == Manga.CHAPTER_SORTING_UPLOAD_DATE },
+        onClick = { onItemSelected(Manga.CHAPTER_SORTING_UPLOAD_DATE) },
+    )
 }
 
 @Composable
-private fun DisplayPage(
-    contentPadding: PaddingValues,
+private fun ColumnScope.DisplayPage(
     displayMode: Long,
     onItemSelected: (Long) -> Unit,
 ) {
-    Column(
-        modifier = Modifier
-            .padding(contentPadding)
-            .padding(vertical = VerticalPadding)
-            .verticalScroll(rememberScrollState()),
-    ) {
-        DisplayPageItem(
-            label = stringResource(R.string.show_title),
-            selected = displayMode == Manga.CHAPTER_DISPLAY_NAME,
-            onClick = { onItemSelected(Manga.CHAPTER_DISPLAY_NAME) },
-        )
-        DisplayPageItem(
-            label = stringResource(R.string.show_chapter_number),
-            selected = displayMode == Manga.CHAPTER_DISPLAY_NUMBER,
-            onClick = { onItemSelected(Manga.CHAPTER_DISPLAY_NUMBER) },
-        )
-    }
-}
-
-@Composable
-private fun DisplayPageItem(
-    label: String,
-    selected: Boolean,
-    onClick: () -> Unit,
-) {
-    Row(
-        modifier = Modifier
-            .clickable(onClick = onClick)
-            .fillMaxWidth()
-            .padding(horizontal = HorizontalPadding, vertical = 12.dp),
-        verticalAlignment = Alignment.CenterVertically,
-        horizontalArrangement = Arrangement.spacedBy(24.dp),
-    ) {
-        RadioButton(
-            selected = selected,
-            onClick = null,
-        )
-        Text(
-            text = label,
-            style = MaterialTheme.typography.bodyMedium,
-        )
-    }
+    RadioItem(
+        label = stringResource(R.string.show_title),
+        selected = displayMode == Manga.CHAPTER_DISPLAY_NAME,
+        onClick = { onItemSelected(Manga.CHAPTER_DISPLAY_NAME) },
+    )
+    RadioItem(
+        label = stringResource(R.string.show_chapter_number),
+        selected = displayMode == Manga.CHAPTER_DISPLAY_NUMBER,
+        onClick = { onItemSelected(Manga.CHAPTER_DISPLAY_NUMBER) },
+    )
 }
-
-private val HorizontalPadding = 24.dp
-private val VerticalPadding = 8.dp