Procházet zdrojové kódy

fix: 双击底栏书架滚动当前分组到顶,Pager 惯性传递移至 MainScreen

HapeLee před 4 měsíci
rodič
revize
88152e0388

+ 20 - 0
app/src/main/java/io/legado/app/ui/main/MainScreen.kt

@@ -10,6 +10,7 @@ import androidx.compose.animation.SharedTransitionScope
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.combinedClickable
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -44,6 +45,7 @@ import androidx.compose.material3.rememberWideNavigationRailState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableLongStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
@@ -85,6 +87,7 @@ import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
 import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
 import io.legado.app.ui.widget.components.navigation.AppNavigationBar
 import io.legado.app.ui.widget.components.navigation.AppNavigationBarItem
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.text.AppText
 import io.legado.app.ui.widget.dialog.TextDialog
 import io.legado.app.utils.sendToClip
@@ -189,6 +192,11 @@ fun MainScreen(
         if (index != -1) index else 0
     }
     val pagerState = rememberPagerState(initialPage = initialPage) { destinations.size }
+    val pagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
+    var bookshelfScrollToTopRequest by remember { mutableLongStateOf(0L) }
     LaunchedEffect(destinations) {
         if (destinations.isNotEmpty() && pagerState.currentPage !in destinations.indices) {
             pagerState.scrollToPage(destinations.lastIndex)
@@ -366,6 +374,7 @@ fun MainScreen(
                 ) {
                     HorizontalPager(
                         state = pagerState,
+                        pageNestedScrollConnection = pagerNestedScrollConnection,
                         modifier = Modifier
                             .fillMaxSize()
                             .then(
@@ -388,6 +397,7 @@ fun MainScreen(
                             )
 
                             MainDestination.Bookshelf -> BookshelfScreen(
+                                scrollToTopRequest = bookshelfScrollToTopRequest,
                                 onBookClick = { book ->
                                     context.startActivityForBook(book)
                                 },
@@ -493,6 +503,16 @@ fun MainScreen(
                                             pagerState.animateScrollToPage(index)
                                         }
                                     },
+                                    onDoubleClick = if (destination == MainDestination.Bookshelf) {
+                                        {
+                                            bookshelfScrollToTopRequest++
+                                            coroutineScope.launch {
+                                                pagerState.animateScrollToPage(index)
+                                            }
+                                        }
+                                    } else {
+                                        null
+                                    },
                                     modifier = Modifier
                                         .defaultMinSize(minWidth = 76.dp)
                                         .semantics(mergeDescendants = true) {

+ 9 - 7
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt

@@ -27,7 +27,6 @@ import androidx.compose.animation.scaleOut
 import androidx.compose.animation.shrinkVertically
 import androidx.compose.animation.togetherWith
 import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -131,7 +130,6 @@ import io.legado.app.ui.widget.components.list.TopFloatingStickyItem
 import io.legado.app.ui.widget.components.log.AppLogSheet
 import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
 import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
-import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
 import io.legado.app.ui.widget.components.tabRow.AppTabRow
 import io.legado.app.ui.widget.components.text.AppText
@@ -157,6 +155,7 @@ import sh.calvin.reorderable.rememberReorderableLazyGridState
 @Composable
 fun BookshelfScreen(
     viewModel: BookshelfViewModel = koinViewModel(),
+    scrollToTopRequest: Long = 0L,
     onBookClick: (BookShelfItem) -> Unit,
     onBookLongClick: (book: BookShelfItem, sharedCoverKey: String?) -> Unit,
     onNavigateToSearch: (String) -> Unit,
@@ -234,10 +233,6 @@ fun BookshelfScreen(
         initialPage = uiState.selectedGroupIndex.coerceAtLeast(0),
         pageCount = { uiState.groups.size }
     )
-    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
-        state = pagerState,
-        orientation = Orientation.Horizontal,
-    )
     val latestGroups by rememberUpdatedState(uiState.groups)
     val latestSelectedGroupId by rememberUpdatedState(uiState.selectedGroupId)
 
@@ -819,6 +814,7 @@ fun BookshelfScreen(
                 } else {
                     if (isUsingStandaloneSearchGroup) {
                         BookshelfPage(
+                            scrollToTopRequest = scrollToTopRequest,
                             paddingValues = paddingValues,
                             books = uiState.items,
                             uiState = uiState,
@@ -840,7 +836,6 @@ fun BookshelfScreen(
                     } else {
                         HorizontalPager(
                             state = pagerState,
-                            pageNestedScrollConnection = childPagerNestedScrollConnection,
                             modifier = Modifier
                                 .fillMaxSize()
                                 .then(
@@ -866,6 +861,7 @@ fun BookshelfScreen(
                                             ?: uiState.bookshelfSort) == 3 &&
                                         isSelectedGroup
                                 BookshelfPage(
+                                    scrollToTopRequest = scrollToTopRequest,
                                     paddingValues = paddingValues,
                                     books = books,
                                     uiState = uiState,
@@ -1215,6 +1211,7 @@ private data class BookshelfEditStickySummary(
 
 @Composable
 fun BookshelfPage(
+    scrollToTopRequest: Long,
     paddingValues: PaddingValues,
     books: ImmutableList<BookUiItem>,
     uiState: BookshelfUiState,
@@ -1301,6 +1298,11 @@ fun BookshelfPage(
     val hapticFeedback = LocalHapticFeedback.current
     val displayBooks = draggingBooks ?: pendingSavedBooks ?: books
     val gridState = rememberLazyGridState()
+    LaunchedEffect(scrollToTopRequest, isCurrentPage) {
+        if (scrollToTopRequest > 0L && isCurrentPage) {
+            gridState.animateScrollToItem(0)
+        }
+    }
     val reorderableState = rememberReorderableLazyGridState(gridState) { from, to ->
         if (canReorderBooks) {
             onMoveBook(from.index, to.index, displayBooks)

+ 19 - 5
app/src/main/java/io/legado/app/ui/widget/components/FloatingBottomBar.kt

@@ -9,6 +9,7 @@ import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.EaseOut
 import androidx.compose.animation.core.spring
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.combinedClickable
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -77,6 +78,7 @@ val LocalFloatingBottomBarTabScale = staticCompositionLocalOf { { 1f } }
 @Composable
 fun RowScope.FloatingBottomBarItem(
     onClick: () -> Unit,
+    onDoubleClick: (() -> Unit)? = null,
     modifier: Modifier = Modifier,
     content: @Composable ColumnScope.() -> Unit
 ) {
@@ -84,11 +86,23 @@ fun RowScope.FloatingBottomBarItem(
     Column(
         modifier
             .clip(ContinuousCapsule)
-            .clickable(
-                interactionSource = null,
-                indication = null,
-                role = Role.Tab,
-                onClick = onClick
+            .then(
+                if (onDoubleClick != null) {
+                    Modifier.combinedClickable(
+                        interactionSource = null,
+                        indication = null,
+                        role = Role.Tab,
+                        onClick = onClick,
+                        onDoubleClick = onDoubleClick,
+                    )
+                } else {
+                    Modifier.clickable(
+                        interactionSource = null,
+                        indication = null,
+                        role = Role.Tab,
+                        onClick = onClick,
+                    )
+                }
             )
             .fillMaxHeight()
             .weight(1f)