Procházet zdrojové kódy

Abstract ChapterSettingsDialog for reuse elsewhere

arkon před 2 roky
rodič
revize
a61e2799db

+ 125 - 0
app/src/main/java/eu/kanade/presentation/components/TabbedDialog.kt

@@ -0,0 +1,125 @@
+package eu.kanade.presentation.components
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.MoreVert
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Tab
+import androidx.compose.material3.TabRow
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+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.layout.onSizeChanged
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.util.fastForEachIndexed
+import eu.kanade.tachiyomi.R
+import kotlinx.coroutines.launch
+
+@Composable
+fun TabbedDialog(
+    onDismissRequest: () -> Unit,
+    tabTitles: List<String>,
+    tabOverflowMenuContent: (@Composable ColumnScope.(() -> Unit) -> Unit)? = null,
+    content: @Composable (PaddingValues, Int) -> Unit,
+) {
+    AdaptiveSheet(
+        onDismissRequest = onDismissRequest,
+    ) { contentPadding ->
+        val scope = rememberCoroutineScope()
+        val pagerState = rememberPagerState()
+
+        Column {
+            Row {
+                TabRow(
+                    modifier = Modifier.weight(1f),
+                    selectedTabIndex = pagerState.currentPage,
+                    indicator = { TabIndicator(it[pagerState.currentPage]) },
+                    divider = {},
+                ) {
+                    tabTitles.fastForEachIndexed { i, tab ->
+                        val selected = pagerState.currentPage == i
+                        Tab(
+                            selected = selected,
+                            onClick = { scope.launch { pagerState.animateScrollToPage(i) } },
+                            text = {
+                                Text(
+                                    text = tab,
+                                    color = if (selected) {
+                                        MaterialTheme.colorScheme.primary
+                                    } else {
+                                        MaterialTheme.colorScheme.onSurfaceVariant
+                                    },
+                                )
+                            },
+                        )
+                    }
+                }
+
+                tabOverflowMenuContent?.let {
+                    MoreMenu(tabOverflowMenuContent)
+                }
+            }
+            Divider()
+
+            val density = LocalDensity.current
+            var largestHeight by rememberSaveable { mutableStateOf(0f) }
+            HorizontalPager(
+                modifier = Modifier.heightIn(min = largestHeight.dp),
+                count = tabTitles.size,
+                state = pagerState,
+                verticalAlignment = Alignment.Top,
+            ) { page ->
+                Box(
+                    modifier = Modifier.onSizeChanged {
+                        with(density) {
+                            val heightDp = it.height.toDp()
+                            if (heightDp.value > largestHeight) {
+                                largestHeight = heightDp.value
+                            }
+                        }
+                    },
+                ) {
+                    content(contentPadding, page)
+                }
+            }
+        }
+    }
+}
+
+@Composable
+private fun MoreMenu(
+    content: @Composable ColumnScope.(() -> Unit) -> Unit,
+) {
+    var expanded by remember { mutableStateOf(false) }
+    Box(modifier = Modifier.wrapContentSize(Alignment.TopStart)) {
+        IconButton(onClick = { expanded = true }) {
+            Icon(
+                imageVector = Icons.Default.MoreVert,
+                contentDescription = stringResource(R.string.label_more),
+            )
+        }
+        DropdownMenu(
+            expanded = expanded,
+            onDismissRequest = { expanded = false },
+        ) {
+            content { expanded = false }
+        }
+    }
+}

+ 48 - 178
app/src/main/java/eu/kanade/presentation/manga/MangaSettingsDialog.kt → app/src/main/java/eu/kanade/presentation/manga/ChapterSettingsDialog.kt

@@ -2,22 +2,18 @@ package eu.kanade.presentation.manga
 
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.wrapContentSize
 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.filled.MoreVert
 import androidx.compose.material.icons.rounded.CheckBox
 import androidx.compose.material.icons.rounded.CheckBoxOutlineBlank
 import androidx.compose.material.icons.rounded.DisabledByDefault
@@ -25,41 +21,24 @@ import androidx.compose.material3.AlertDialog
 import androidx.compose.material3.Checkbox
 import androidx.compose.material3.DropdownMenuItem
 import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.RadioButton
-import androidx.compose.material3.Surface
-import androidx.compose.material3.Tab
-import androidx.compose.material3.TabRow
 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.rememberCoroutineScope
 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.layout.onSizeChanged
-import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastForEachIndexed
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.manga.model.TriStateFilter
-import eu.kanade.presentation.components.AdaptiveSheet
-import eu.kanade.presentation.components.Divider
-import eu.kanade.presentation.components.DropdownMenu
-import eu.kanade.presentation.components.HorizontalPager
-import eu.kanade.presentation.components.TabIndicator
-import eu.kanade.presentation.components.rememberPagerState
-import eu.kanade.presentation.theme.TachiyomiTheme
-import eu.kanade.presentation.util.ThemePreviews
+import eu.kanade.presentation.components.TabbedDialog
 import eu.kanade.tachiyomi.R
-import kotlinx.coroutines.launch
 
 @Composable
 fun ChapterSettingsDialog(
@@ -72,41 +51,6 @@ fun ChapterSettingsDialog(
     onDisplayModeChanged: (Long) -> Unit,
     onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
 ) {
-    AdaptiveSheet(
-        onDismissRequest = onDismissRequest,
-    ) { contentPadding ->
-        ChapterSettingsDialogImpl(
-            manga = manga,
-            contentPadding = contentPadding,
-            onDownloadFilterChanged = onDownloadFilterChanged,
-            onUnreadFilterChanged = onUnreadFilterChanged,
-            onBookmarkedFilterChanged = onBookmarkedFilterChanged,
-            onSortModeChanged = onSortModeChanged,
-            onDisplayModeChanged = onDisplayModeChanged,
-            onSetAsDefault = onSetAsDefault,
-        )
-    }
-}
-
-@Composable
-private fun ChapterSettingsDialogImpl(
-    manga: Manga? = null,
-    contentPadding: PaddingValues = PaddingValues(),
-    onDownloadFilterChanged: (TriStateFilter) -> Unit,
-    onUnreadFilterChanged: (TriStateFilter) -> Unit,
-    onBookmarkedFilterChanged: (TriStateFilter) -> Unit,
-    onSortModeChanged: (Long) -> Unit,
-    onDisplayModeChanged: (Long) -> Unit,
-    onSetAsDefault: (applyToExistingManga: Boolean) -> Unit,
-) {
-    val scope = rememberCoroutineScope()
-    val tabTitles = listOf(
-        stringResource(R.string.action_filter),
-        stringResource(R.string.action_sort),
-        stringResource(R.string.action_display),
-    )
-    val pagerState = rememberPagerState()
-
     var showSetAsDefaultDialog by rememberSaveable { mutableStateOf(false) }
     if (showSetAsDefaultDialog) {
         SetAsDefaultDialog(
@@ -115,85 +59,54 @@ private fun ChapterSettingsDialogImpl(
         )
     }
 
-    Column {
-        Row {
-            TabRow(
-                modifier = Modifier.weight(1f),
-                selectedTabIndex = pagerState.currentPage,
-                indicator = { TabIndicator(it[pagerState.currentPage]) },
-                divider = {},
-            ) {
-                tabTitles.fastForEachIndexed { i, s ->
-                    val selected = pagerState.currentPage == i
-                    Tab(
-                        selected = selected,
-                        onClick = { scope.launch { pagerState.animateScrollToPage(i) } },
-                        text = {
-                            Text(
-                                text = s,
-                                color = if (selected) {
-                                    MaterialTheme.colorScheme.primary
-                                } else {
-                                    MaterialTheme.colorScheme.onSurfaceVariant
-                                },
-                            )
-                        },
-                    )
-                }
-            }
-
-            MoreMenu(onSetAsDefault = { showSetAsDefaultDialog = true })
-        }
-
-        Divider()
-
-        val density = LocalDensity.current
-        var largestHeight by rememberSaveable { mutableStateOf(0f) }
-        HorizontalPager(
-            modifier = Modifier.heightIn(min = largestHeight.dp),
-            count = tabTitles.size,
-            state = pagerState,
-            verticalAlignment = Alignment.Top,
-        ) { page ->
-            Box(
-                modifier = Modifier.onSizeChanged {
-                    with(density) {
-                        val heightDp = it.height.toDp()
-                        if (heightDp.value > largestHeight) {
-                            largestHeight = heightDp.value
-                        }
-                    }
+    TabbedDialog(
+        onDismissRequest = onDismissRequest,
+        tabTitles = listOf(
+            stringResource(R.string.action_filter),
+            stringResource(R.string.action_sort),
+            stringResource(R.string.action_display),
+        ),
+        tabOverflowMenuContent = { closeMenu ->
+            DropdownMenuItem(
+                text = { Text(stringResource(R.string.set_chapter_settings_as_default)) },
+                onClick = {
+                    showSetAsDefaultDialog = true
+                    closeMenu()
                 },
-            ) {
-                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,
-                    )
-                }
+            )
+        },
+    ) { 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,
+                )
             }
         }
     }
@@ -247,33 +160,6 @@ private fun SetAsDefaultDialog(
     )
 }
 
-@Composable
-private fun MoreMenu(
-    onSetAsDefault: () -> Unit,
-) {
-    var expanded by remember { mutableStateOf(false) }
-    Box(modifier = Modifier.wrapContentSize(Alignment.TopStart)) {
-        IconButton(onClick = { expanded = true }) {
-            Icon(
-                imageVector = Icons.Default.MoreVert,
-                contentDescription = stringResource(R.string.label_more),
-            )
-        }
-        DropdownMenu(
-            expanded = expanded,
-            onDismissRequest = { expanded = false },
-        ) {
-            DropdownMenuItem(
-                text = { Text(stringResource(R.string.set_chapter_settings_as_default)) },
-                onClick = {
-                    onSetAsDefault()
-                    expanded = false
-                },
-            )
-        }
-    }
-}
-
 @Composable
 private fun FilterPage(
     contentPadding: PaddingValues,
@@ -470,19 +356,3 @@ private fun DisplayPageItem(
 
 private val HorizontalPadding = 24.dp
 private val VerticalPadding = 8.dp
-
-@ThemePreviews
-@Composable
-private fun ChapterSettingsDialogPreview() {
-    TachiyomiTheme {
-        Surface {
-            ChapterSettingsDialogImpl(
-                onDownloadFilterChanged = {},
-                onUnreadFilterChanged = {},
-                onBookmarkedFilterChanged = {},
-                onSortModeChanged = {},
-                onDisplayModeChanged = {},
-            ) {}
-        }
-    }
-}