Kaynağa Gözat

refactor: 拆分主壳、书架与 RSS 的路由注入边界

将 MainScreen 和 BookshelfScreen 调整为无状态渲染入口,由导航图或 RouteScreen 收集状态并分发 Intent。

同时通过功能 Gateway 向 RSS 排序和阅读页面提供所需设置,移除 Compose 层配置门面读取。
5151561 3 ay önce
ebeveyn
işleme
7a8a14f172

+ 6 - 0
app/src/main/java/io/legado/app/ui/main/MainNavGraph.kt

@@ -7,6 +7,7 @@ import androidx.compose.animation.fadeIn
 import androidx.compose.animation.fadeOut
 import androidx.compose.animation.fadeOut
 import androidx.compose.animation.togetherWith
 import androidx.compose.animation.togetherWith
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.remember
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalContext
@@ -92,7 +93,12 @@ fun MainActivity.mainEntryProvider(
     onRegisterVariableSetter: (((String, String?) -> Unit)?) -> Unit
     onRegisterVariableSetter: (((String, String?) -> Unit)?) -> Unit
 ) = entryProvider {
 ) = entryProvider {
     entry<MainRouteHome> {
     entry<MainRouteHome> {
+        val mainViewModel = koinViewModel<MainViewModel>()
+        val mainUiState by mainViewModel.uiState.collectAsStateWithLifecycle()
         MainScreen(
         MainScreen(
+            mainUiState = mainUiState,
+            onIntent = mainViewModel::onIntent,
+            effects = mainViewModel.effects,
             useRail = useRail,
             useRail = useRail,
             onOpenSettings = {
             onOpenSettings = {
                 onNavigateToRoute(MainRouteSettings)
                 onNavigateToRoute(MainRouteSettings)

+ 36 - 16
app/src/main/java/io/legado/app/ui/main/MainScreen.kt

@@ -77,7 +77,7 @@ import com.kyant.backdrop.backdrops.rememberLayerBackdrop
 import dev.chrisbanes.haze.HazeState
 import dev.chrisbanes.haze.HazeState
 import dev.chrisbanes.haze.hazeSource
 import dev.chrisbanes.haze.hazeSource
 import io.legado.app.R
 import io.legado.app.R
-import io.legado.app.ui.main.bookshelf.BookshelfScreen
+import io.legado.app.ui.main.bookshelf.BookshelfRouteScreen
 import io.legado.app.ui.main.bookshelf.BookshelfViewModel
 import io.legado.app.ui.main.bookshelf.BookshelfViewModel
 import io.legado.app.ui.main.explore.ExploreRouteScreen
 import io.legado.app.ui.main.explore.ExploreRouteScreen
 import io.legado.app.ui.main.home.HomeRouteScreen
 import io.legado.app.ui.main.home.HomeRouteScreen
@@ -120,7 +120,9 @@ import top.yukonga.miuix.kmp.basic.NavigationRailItem as MiuixNavigationRailItem
 )
 )
 @Composable
 @Composable
 fun MainScreen(
 fun MainScreen(
-    viewModel: MainViewModel = koinViewModel(),
+    mainUiState: MainUiState,
+    onIntent: (MainUiIntent) -> Unit,
+    effects: kotlinx.coroutines.flow.Flow<MainEffect>,
     useRail: Boolean,
     useRail: Boolean,
     onOpenSettings: () -> Unit,
     onOpenSettings: () -> Unit,
     onNavigateToChat: () -> Unit,
     onNavigateToChat: () -> Unit,
@@ -151,11 +153,10 @@ fun MainScreen(
 ) {
 ) {
     val context = LocalContext.current
     val context = LocalContext.current
     val coroutineScope = rememberCoroutineScope()
     val coroutineScope = rememberCoroutineScope()
-    val mainUiState by viewModel.uiState.collectAsStateWithLifecycle()
     val defaultHelpTitle = stringResource(R.string.help)
     val defaultHelpTitle = stringResource(R.string.help)
 
 
-    LaunchedEffect(viewModel, context) {
-        viewModel.effects.collectLatest { effect ->
+    LaunchedEffect(effects, context) {
+        effects.collectLatest { effect ->
             when (effect) {
             when (effect) {
                 is MainEffect.OpenUrl -> {
                 is MainEffect.OpenUrl -> {
                     context.startActivity(
                     context.startActivity(
@@ -279,7 +280,7 @@ fun MainScreen(
                     }
                     }
                 )
                 )
                 LaunchedEffect(miuixNavState.currentValue) {
                 LaunchedEffect(miuixNavState.currentValue) {
-                    viewModel.onIntent(MainUiIntent.SetNavigationRailExpanded(miuixNavState.isExpanded))
+                    onIntent(MainUiIntent.SetNavigationRailExpanded(miuixNavState.isExpanded))
                 }
                 }
                 MiuixNavigationRail(
                 MiuixNavigationRail(
                     state = miuixNavState,
                     state = miuixNavState,
@@ -333,7 +334,7 @@ fun MainScreen(
                                 label = destinationLabel,
                                 label = destinationLabel,
                             )
                             )
                             if (destination == MainDestination.Bookshelf && showGroupMenu) {
                             if (destination == MainDestination.Bookshelf && showGroupMenu) {
-                                BookshelfRailGroupMenu(
+                                BookshelfRailGroupMenuRoute(
                                     expanded = showGroupMenu,
                                     expanded = showGroupMenu,
                                     onDismissRequest = { showGroupMenu = false },
                                     onDismissRequest = { showGroupMenu = false },
                                     onBeforeSelectGroup = {
                                     onBeforeSelectGroup = {
@@ -359,7 +360,7 @@ fun MainScreen(
                                     val targetExpanded = !expanded
                                     val targetExpanded = !expanded
                                     if (targetExpanded) navState.expand()
                                     if (targetExpanded) navState.expand()
                                     else navState.collapse()
                                     else navState.collapse()
-                                    viewModel.onIntent(MainUiIntent.SetNavigationRailExpanded(targetExpanded))
+                                    onIntent(MainUiIntent.SetNavigationRailExpanded(targetExpanded))
                                 }
                                 }
                             }
                             }
                         ) {
                         ) {
@@ -423,7 +424,7 @@ fun MainScreen(
                                 )
                                 )
 
 
                                 if (destination == MainDestination.Bookshelf && showGroupMenu) {
                                 if (destination == MainDestination.Bookshelf && showGroupMenu) {
-                                    BookshelfRailGroupMenu(
+                                    BookshelfRailGroupMenuRoute(
                                         expanded = showGroupMenu,
                                         expanded = showGroupMenu,
                                         onDismissRequest = { showGroupMenu = false },
                                         onDismissRequest = { showGroupMenu = false },
                                         onBeforeSelectGroup = {
                                         onBeforeSelectGroup = {
@@ -543,7 +544,7 @@ fun MainScreen(
                                 animatedVisibilityScope = animatedVisibilityScope,
                                 animatedVisibilityScope = animatedVisibilityScope,
                             )
                             )
 
 
-                            MainDestination.Bookshelf -> BookshelfScreen(
+                            MainDestination.Bookshelf -> BookshelfRouteScreen(
                                 scrollToTopRequest = bookshelfScrollToTopRequest,
                                 scrollToTopRequest = bookshelfScrollToTopRequest,
                                 onScrollToTopRequestHandled = { handledRequest ->
                                 onScrollToTopRequestHandled = { handledRequest ->
                                     if (bookshelfScrollToTopRequest == handledRequest) {
                                     if (bookshelfScrollToTopRequest == handledRequest) {
@@ -591,7 +592,7 @@ fun MainScreen(
                                     when (event) {
                                     when (event) {
                                         PrefClickEvent.OpenBookCacheManage -> onNavigateToBookCacheManage()
                                         PrefClickEvent.OpenBookCacheManage -> onNavigateToBookCacheManage()
                                         PrefClickEvent.OpenReadRecord -> onNavigateToReadRecord()
                                         PrefClickEvent.OpenReadRecord -> onNavigateToReadRecord()
-                                        else -> viewModel.onIntent(MainUiIntent.HandlePreferenceClick(event))
+                                        else -> onIntent(MainUiIntent.HandlePreferenceClick(event))
                                     }
                                     }
                                 }
                                 }
                             )
                             )
@@ -722,31 +723,50 @@ private class MainPageLifecycleOwner : LifecycleOwner {
 }
 }
 
 
 @Composable
 @Composable
-private fun BookshelfRailGroupMenu(
+private fun BookshelfRailGroupMenuRoute(
     expanded: Boolean,
     expanded: Boolean,
     onDismissRequest: () -> Unit,
     onDismissRequest: () -> Unit,
     onBeforeSelectGroup: suspend () -> Unit,
     onBeforeSelectGroup: suspend () -> Unit,
     viewModel: BookshelfViewModel = koinViewModel()
     viewModel: BookshelfViewModel = koinViewModel()
 ) {
 ) {
     val groupState by viewModel.groupSelectorState.collectAsStateWithLifecycle()
     val groupState by viewModel.groupSelectorState.collectAsStateWithLifecycle()
+    BookshelfRailGroupMenu(
+        expanded = expanded,
+        state = groupState,
+        onDismissRequest = onDismissRequest,
+        onSelectGroup = { groupId ->
+            onBeforeSelectGroup()
+            viewModel.onIntent(
+                io.legado.app.ui.main.bookshelf.BookshelfIntent.ChangeGroup(groupId)
+            )
+        },
+    )
+}
+
+@Composable
+private fun BookshelfRailGroupMenu(
+    expanded: Boolean,
+    state: io.legado.app.ui.main.bookshelf.BookshelfGroupSelectorState,
+    onDismissRequest: () -> Unit,
+    onSelectGroup: suspend (Long) -> Unit,
+) {
     val coroutineScope = rememberCoroutineScope()
     val coroutineScope = rememberCoroutineScope()
 
 
     RoundDropdownMenu(
     RoundDropdownMenu(
         expanded = expanded,
         expanded = expanded,
         onDismissRequest = onDismissRequest
         onDismissRequest = onDismissRequest
     ) { dismiss ->
     ) { dismiss ->
-        groupState.groups.forEachIndexed { groupIndex, group ->
+        state.groups.forEachIndexed { groupIndex, group ->
             RoundDropdownMenuItem(
             RoundDropdownMenuItem(
                 text = group.groupName,
                 text = group.groupName,
                 onClick = {
                 onClick = {
                     coroutineScope.launch {
                     coroutineScope.launch {
-                        onBeforeSelectGroup()
-                        viewModel.changeGroup(group.groupId)
+                        onSelectGroup(group.groupId)
                         dismiss()
                         dismiss()
                     }
                     }
                 },
                 },
                 trailingIcon = {
                 trailingIcon = {
-                    if (groupState.selectedGroupIndex == groupIndex) {
+                    if (state.selectedGroupIndex == groupIndex) {
                         Icon(
                         Icon(
                             Icons.Default.Check,
                             Icons.Default.Check,
                             null,
                             null,

+ 115 - 74
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt

@@ -154,7 +154,7 @@ import sh.calvin.reorderable.rememberReorderableLazyGridState
     ExperimentalAnimationApi::class
     ExperimentalAnimationApi::class
 )
 )
 @Composable
 @Composable
-fun BookshelfScreen(
+fun BookshelfRouteScreen(
     viewModel: BookshelfViewModel = koinViewModel(),
     viewModel: BookshelfViewModel = koinViewModel(),
     scrollToTopRequest: Long = 0L,
     scrollToTopRequest: Long = 0L,
     onScrollToTopRequestHandled: (Long) -> Unit = {},
     onScrollToTopRequestHandled: (Long) -> Unit = {},
@@ -167,7 +167,48 @@ fun BookshelfScreen(
     sharedTransitionScope: SharedTransitionScope? = null,
     sharedTransitionScope: SharedTransitionScope? = null,
     animatedVisibilityScope: AnimatedVisibilityScope? = null,
     animatedVisibilityScope: AnimatedVisibilityScope? = null,
 ) {
 ) {
-    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
+    val state by viewModel.uiState.collectAsStateWithLifecycle()
+    val allGroups by viewModel.allGroupsFlow.collectAsStateWithLifecycle()
+    BookshelfScreen(
+        uiState = state,
+        onIntent = viewModel::onIntent,
+        effects = viewModel.effects,
+        allGroups = allGroups,
+        scrollToTopRequest = scrollToTopRequest,
+        onScrollToTopRequestHandled = onScrollToTopRequestHandled,
+        onBookClick = onBookClick,
+        onBookLongClick = onBookLongClick,
+        onNavigateToSearch = onNavigateToSearch,
+        onNavigateToRemoteImport = onNavigateToRemoteImport,
+        onNavigateToLocalImport = onNavigateToLocalImport,
+        onNavigateToCache = onNavigateToCache,
+        sharedTransitionScope = sharedTransitionScope,
+        animatedVisibilityScope = animatedVisibilityScope,
+    )
+}
+
+@OptIn(
+    ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class,
+    ExperimentalMaterial3ExpressiveApi::class, ExperimentalSharedTransitionApi::class,
+    ExperimentalAnimationApi::class
+)
+@Composable
+fun BookshelfScreen(
+    uiState: BookshelfUiState,
+    onIntent: (BookshelfIntent) -> Unit,
+    effects: kotlinx.coroutines.flow.Flow<BookshelfEffect>,
+    allGroups: List<io.legado.app.data.entities.BookGroup>,
+    scrollToTopRequest: Long = 0L,
+    onScrollToTopRequestHandled: (Long) -> Unit = {},
+    onBookClick: (BookShelfItem) -> Unit,
+    onBookLongClick: (book: BookShelfItem, sharedCoverKey: String?) -> Unit,
+    onNavigateToSearch: (String) -> Unit,
+    onNavigateToRemoteImport: () -> Unit,
+    onNavigateToLocalImport: () -> Unit,
+    onNavigateToCache: (Long) -> Unit,
+    sharedTransitionScope: SharedTransitionScope? = null,
+    animatedVisibilityScope: AnimatedVisibilityScope? = null,
+) {
     val scope = rememberCoroutineScope()
     val scope = rememberCoroutineScope()
 
 
     ReportDrawnWhen { !uiState.isInitialLoading }
     ReportDrawnWhen { !uiState.isInitialLoading }
@@ -176,7 +217,7 @@ fun BookshelfScreen(
     val snackbarHostState = remember { SnackbarHostState() }
     val snackbarHostState = remember { SnackbarHostState() }
 
 
     LaunchedEffect(Unit) {
     LaunchedEffect(Unit) {
-        viewModel.effects.collect { effect ->
+        effects.collect { effect ->
             when (effect) {
             when (effect) {
                 is BookshelfEffect.ShowSnackbar -> {
                 is BookshelfEffect.ShowSnackbar -> {
                     val result = snackbarHostState.showSnackbar(
                     val result = snackbarHostState.showSnackbar(
@@ -204,7 +245,7 @@ fun BookshelfScreen(
         onResult = { uri ->
         onResult = { uri ->
             uri?.let {
             uri?.let {
                 val groupId = uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
                 val groupId = uiState.groups.getOrNull(uiState.selectedGroupIndex)?.groupId ?: -1L
-                viewModel.onIntent(BookshelfIntent.ImportFromUri(it, groupId))
+                onIntent(BookshelfIntent.ImportFromUri(it, groupId))
             }
             }
         }
         }
     )
     )
@@ -212,7 +253,7 @@ fun BookshelfScreen(
     val exportLauncher = rememberLauncherForActivityResult(
     val exportLauncher = rememberLauncherForActivityResult(
         contract = ActivityResultContracts.CreateDocument("application/json"),
         contract = ActivityResultContracts.CreateDocument("application/json"),
         onResult = { uri ->
         onResult = { uri ->
-            uri?.let { viewModel.onIntent(BookshelfIntent.ExportToUri(it, uiState.items)) }
+            uri?.let { onIntent(BookshelfIntent.ExportToUri(it, uiState.items)) }
         }
         }
     )
     )
 
 
@@ -265,7 +306,7 @@ fun BookshelfScreen(
                 if (groups.isNotEmpty() && page in groups.indices) {
                 if (groups.isNotEmpty() && page in groups.indices) {
                     val targetGroupId = groups[page].groupId
                     val targetGroupId = groups[page].groupId
                     if (latestSelectedGroupId != targetGroupId) {
                     if (latestSelectedGroupId != targetGroupId) {
-                        viewModel.onIntent(BookshelfIntent.ChangeGroup(targetGroupId))
+                        onIntent(BookshelfIntent.ChangeGroup(targetGroupId))
                     }
                     }
                 }
                 }
             }
             }
@@ -312,16 +353,16 @@ fun BookshelfScreen(
     val currentGroupBookCount by remember { derivedStateOf { uiState.currentGroupBookCount } }
     val currentGroupBookCount by remember { derivedStateOf { uiState.currentGroupBookCount } }
 
 
     val clearSelection = {
     val clearSelection = {
-        viewModel.onIntent(BookshelfIntent.ClearSelection)
+        onIntent(BookshelfIntent.ClearSelection)
     }
     }
     val exitEditMode = {
     val exitEditMode = {
-        viewModel.onIntent(BookshelfIntent.ExitEditMode)
+        onIntent(BookshelfIntent.ExitEditMode)
     }
     }
     val toggleEditMode = {
     val toggleEditMode = {
-        viewModel.onIntent(BookshelfIntent.ToggleEditMode)
+        onIntent(BookshelfIntent.ToggleEditMode)
     }
     }
     val toggleBookSelection: (String) -> Unit = { bookUrl ->
     val toggleBookSelection: (String) -> Unit = { bookUrl ->
-        viewModel.onIntent(BookshelfIntent.ToggleBookSelection(bookUrl))
+        onIntent(BookshelfIntent.ToggleBookSelection(bookUrl))
     }
     }
 
 
     LaunchedEffect(pagerState.currentPage, isInFolderRoot) {
     LaunchedEffect(pagerState.currentPage, isInFolderRoot) {
@@ -343,7 +384,7 @@ fun BookshelfScreen(
             progress.collect { backEvent ->
             progress.collect { backEvent ->
                 transitionState.seekTo(backEvent.progress, targetState = true)
                 transitionState.seekTo(backEvent.progress, targetState = true)
             }
             }
-            viewModel.onIntent(BookshelfIntent.SetInFolderRoot(true))
+            onIntent(BookshelfIntent.SetInFolderRoot(true))
             transitionState.animateTo(true)
             transitionState.animateTo(true)
         } catch (e: CancellationException) {
         } catch (e: CancellationException) {
             transitionState.animateTo(false)
             transitionState.animateTo(false)
@@ -395,9 +436,9 @@ fun BookshelfScreen(
             onNavigateToSearch(uiState.searchKey.trim())
             onNavigateToSearch(uiState.searchKey.trim())
         } else {
         } else {
             val active = !uiState.isSearch
             val active = !uiState.isSearch
-            viewModel.onIntent(BookshelfIntent.SetSearchMode(active))
+            onIntent(BookshelfIntent.SetSearchMode(active))
             if (!active && uiState.selectedGroupId != currentTabGroupId) {
             if (!active && uiState.selectedGroupId != currentTabGroupId) {
-                viewModel.onIntent(BookshelfIntent.ChangeGroup(currentTabGroupId))
+                onIntent(BookshelfIntent.ChangeGroup(currentTabGroupId))
             }
             }
         }
         }
     }
     }
@@ -421,24 +462,24 @@ fun BookshelfScreen(
                 uiState = uiState,
                 uiState = uiState,
                 scrollBehavior = scrollBehavior,
                 scrollBehavior = scrollBehavior,
                 onSearchClick = onSearchClick,
                 onSearchClick = onSearchClick,
-                onSearchQueryChange = { viewModel.onIntent(BookshelfIntent.SetSearchKey(it)) },
+                onSearchQueryChange = { onIntent(BookshelfIntent.SetSearchKey(it)) },
                 onSearchSubmit = { rawQuery ->
                 onSearchSubmit = { rawQuery ->
                     rawQuery.trim()
                     rawQuery.trim()
                         .takeIf { it.isNotEmpty() }
                         .takeIf { it.isNotEmpty() }
                         ?.let(onNavigateToSearch)
                         ?.let(onNavigateToSearch)
                 },
                 },
-                onClearSearch = { viewModel.onIntent(BookshelfIntent.SetSearchKey("")) },
+                onClearSearch = { onIntent(BookshelfIntent.SetSearchKey("")) },
                 actions = {
                 actions = {
                     AnimatedVisibility(visible = isEditMode) {
                     AnimatedVisibility(visible = isEditMode) {
                         TopBarActionButton(
                         TopBarActionButton(
-                            onClick = { viewModel.onIntent(BookshelfIntent.SelectAllVisible) },
+                            onClick = { onIntent(BookshelfIntent.SelectAllVisible) },
                             imageVector = Icons.Default.SelectAll,
                             imageVector = Icons.Default.SelectAll,
                             contentDescription = stringResource(R.string.select_all)
                             contentDescription = stringResource(R.string.select_all)
                         )
                         )
                     }
                     }
                     AnimatedVisibility(visible = isEditMode) {
                     AnimatedVisibility(visible = isEditMode) {
                         TopBarActionButton(
                         TopBarActionButton(
-                            onClick = { viewModel.onIntent(BookshelfIntent.InvertVisibleSelection) },
+                            onClick = { onIntent(BookshelfIntent.InvertVisibleSelection) },
                             imageVector = Icons.Default.Refresh,
                             imageVector = Icons.Default.Refresh,
                             contentDescription = stringResource(R.string.revert_selection)
                             contentDescription = stringResource(R.string.revert_selection)
                         )
                         )
@@ -447,7 +488,7 @@ fun BookshelfScreen(
                         TopBarActionButton(
                         TopBarActionButton(
                             onClick = {
                             onClick = {
                                 if (selectedBookUrls.isNotEmpty()) {
                                 if (selectedBookUrls.isNotEmpty()) {
-                                    viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.BatchDownloadConfirmDialog))
+                                    onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.BatchDownloadConfirmDialog))
                                 }
                                 }
                             },
                             },
                             imageVector = Icons.Default.Download,
                             imageVector = Icons.Default.Download,
@@ -458,7 +499,7 @@ fun BookshelfScreen(
                         TopBarActionButton(
                         TopBarActionButton(
                             onClick = {
                             onClick = {
                                 if (selectedBookUrls.isNotEmpty()) {
                                 if (selectedBookUrls.isNotEmpty()) {
-                                    viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupSelectSheet))
+                                    onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupSelectSheet))
                                 }
                                 }
                             },
                             },
                             imageVector = Icons.Default.Bookmarks,
                             imageVector = Icons.Default.Bookmarks,
@@ -490,7 +531,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.update_toc),
                                     text = stringResource(R.string.update_toc),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.RefreshToc(uiState.items))
+                                        onIntent(BookshelfIntent.RefreshToc(uiState.items))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.Refresh, null) }
                                     leadingIcon = { Icon(Icons.Default.Refresh, null) }
@@ -498,7 +539,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.layout_setting),
                                     text = stringResource(R.string.layout_setting),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ConfigSheet))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ConfigSheet))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.GridView, null) }
                                     leadingIcon = { Icon(Icons.Default.GridView, null) }
@@ -506,7 +547,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.group_manage),
                                     text = stringResource(R.string.group_manage),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupManageSheet))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupManageSheet))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Outlined.ViewCarousel, null) }
                                     leadingIcon = { Icon(Icons.Outlined.ViewCarousel, null) }
@@ -514,7 +555,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.add_url),
                                     text = stringResource(R.string.add_url),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.AddUrlDialog))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.AddUrlDialog))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.Link, null) }
                                     leadingIcon = { Icon(Icons.Default.Link, null) }
@@ -541,7 +582,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.export_bookshelf),
                                     text = stringResource(R.string.export_bookshelf),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ExportSheet))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ExportSheet))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.UploadFile, null) }
                                     leadingIcon = { Icon(Icons.Default.UploadFile, null) }
@@ -549,7 +590,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.import_bookshelf),
                                     text = stringResource(R.string.import_bookshelf),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ImportSheet))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.ImportSheet))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.CloudDownload, null) }
                                     leadingIcon = { Icon(Icons.Default.CloudDownload, null) }
@@ -557,7 +598,7 @@ fun BookshelfScreen(
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
                                     text = stringResource(R.string.log),
                                     text = stringResource(R.string.log),
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.LogSheet))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.LogSheet))
                                         dismiss()
                                         dismiss()
                                     },
                                     },
                                     leadingIcon = { Icon(Icons.Default.History, null) }
                                     leadingIcon = { Icon(Icons.Default.History, null) }
@@ -596,9 +637,9 @@ fun BookshelfScreen(
                                         checked = showGroupMenu,
                                         checked = showGroupMenu,
                                         onCheckedChange = {
                                         onCheckedChange = {
                                             if (it) {
                                             if (it) {
-                                                viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupMenu))
+                                                onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupMenu))
                                             } else {
                                             } else {
-                                                viewModel.onIntent(BookshelfIntent.DismissOverlay)
+                                                onIntent(BookshelfIntent.DismissOverlay)
                                             }
                                             }
                                         },
                                         },
                                         style = ToggleStyle.Outlined,
                                         style = ToggleStyle.Outlined,
@@ -607,14 +648,14 @@ fun BookshelfScreen(
                                     )
                                     )
                                     RoundDropdownMenu(
                                     RoundDropdownMenu(
                                         expanded = showGroupMenu,
                                         expanded = showGroupMenu,
-                                        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+                                        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
                                     ) { dismiss ->
                                     ) { dismiss ->
                                         uiState.groups.forEachIndexed { index, group ->
                                         uiState.groups.forEachIndexed { index, group ->
                                             RoundDropdownMenuItem(
                                             RoundDropdownMenuItem(
                                                 text = group.groupName,
                                                 text = group.groupName,
                                                 onClick = {
                                                 onClick = {
                                                     if (uiState.isSearch) {
                                                     if (uiState.isSearch) {
-                                                        viewModel.onIntent(BookshelfIntent.ChangeGroup(group.groupId))
+                                                        onIntent(BookshelfIntent.ChangeGroup(group.groupId))
                                                     }
                                                     }
                                                     scope.launch {
                                                     scope.launch {
                                                         pagerState.animateScrollToPage(
                                                         pagerState.animateScrollToPage(
@@ -661,7 +702,7 @@ fun BookshelfScreen(
                                                     RoundDropdownMenuItem(
                                                     RoundDropdownMenuItem(
                                                         text = group.groupName,
                                                         text = group.groupName,
                                                         onClick = {
                                                         onClick = {
-                                                            viewModel.onIntent(BookshelfIntent.ChangeGroup(group.groupId))
+                                                            onIntent(BookshelfIntent.ChangeGroup(group.groupId))
                                                             dismiss()
                                                             dismiss()
                                                         },
                                                         },
                                                         trailingIcon = {
                                                         trailingIcon = {
@@ -680,7 +721,7 @@ fun BookshelfScreen(
                                                     RoundDropdownMenuItem(
                                                     RoundDropdownMenuItem(
                                                         text = group.groupName,
                                                         text = group.groupName,
                                                         onClick = {
                                                         onClick = {
-                                                            viewModel.onIntent(BookshelfIntent.ChangeGroup(group.groupId))
+                                                            onIntent(BookshelfIntent.ChangeGroup(group.groupId))
                                                             dismiss()
                                                             dismiss()
                                                         },
                                                         },
                                                         trailingIcon = {
                                                         trailingIcon = {
@@ -721,7 +762,7 @@ fun BookshelfScreen(
         Box(Modifier.fillMaxSize()) {
         Box(Modifier.fillMaxSize()) {
             AppPullToRefresh(
             AppPullToRefresh(
                 isRefreshing = uiState.isRefreshing,
                 isRefreshing = uiState.isRefreshing,
-                onRefresh = { viewModel.onIntent(BookshelfIntent.RefreshBooks(uiState.items)) },
+                onRefresh = { onIntent(BookshelfIntent.RefreshBooks(uiState.items)) },
                 enabled = pullToRefreshEnabled,
                 enabled = pullToRefreshEnabled,
                 topPadding = paddingValues.calculateTopPadding(),
                 topPadding = paddingValues.calculateTopPadding(),
                 scrollBehavior = scrollBehavior
                 scrollBehavior = scrollBehavior
@@ -816,10 +857,10 @@ fun BookshelfScreen(
                                     coverShadow = uiState.settings.bookshelfCoverShadow,
                                     coverShadow = uiState.settings.bookshelfCoverShadow,
                                     onClick = {
                                     onClick = {
                                         scope.launch { pagerState.scrollToPage(index) }
                                         scope.launch { pagerState.scrollToPage(index) }
-                                        viewModel.onIntent(BookshelfIntent.SetInFolderRoot(false))
+                                        onIntent(BookshelfIntent.SetInFolderRoot(false))
                                     },
                                     },
                                     onLongClick = {
                                     onLongClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupEditSheet(group.groupId)))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupEditSheet(group.groupId)))
                                     },
                                     },
                                     onBookClick = onBookClick
                                     onBookClick = onBookClick
                                 )
                                 )
@@ -837,10 +878,10 @@ fun BookshelfScreen(
                                     coverShadow = uiState.settings.bookshelfCoverShadow,
                                     coverShadow = uiState.settings.bookshelfCoverShadow,
                                     onClick = {
                                     onClick = {
                                         scope.launch { pagerState.scrollToPage(index) }
                                         scope.launch { pagerState.scrollToPage(index) }
-                                        viewModel.onIntent(BookshelfIntent.SetInFolderRoot(false))
+                                        onIntent(BookshelfIntent.SetInFolderRoot(false))
                                     },
                                     },
                                     onLongClick = {
                                     onLongClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupEditSheet(group.groupId)))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupEditSheet(group.groupId)))
                                     }
                                     }
                                 )
                                 )
                             }
                             }
@@ -911,15 +952,15 @@ fun BookshelfScreen(
                                         null
                                         null
                                     },
                                     },
                                     onDragStarted = {
                                     onDragStarted = {
-                                        if (isSelectedGroup) viewModel.onIntent(BookshelfIntent.StartDragging(it))
+                                        if (isSelectedGroup) onIntent(BookshelfIntent.StartDragging(it))
                                     },
                                     },
                                     onMoveBook = { from, to, currentBooks ->
                                     onMoveBook = { from, to, currentBooks ->
                                         if (isSelectedGroup) {
                                         if (isSelectedGroup) {
-                                            viewModel.onIntent(BookshelfIntent.MoveDragging(from, to, currentBooks))
+                                            onIntent(BookshelfIntent.MoveDragging(from, to, currentBooks))
                                         }
                                         }
                                     },
                                     },
                                     onDragFinished = {
                                     onDragFinished = {
-                                        if (isSelectedGroup) viewModel.onIntent(BookshelfIntent.FinishDragging)
+                                        if (isSelectedGroup) onIntent(BookshelfIntent.FinishDragging)
                                     },
                                     },
                                     onGlobalSearch = { onNavigateToSearch(uiState.searchKey.trim()) },
                                     onGlobalSearch = { onNavigateToSearch(uiState.searchKey.trim()) },
                                     onBookClick = onBookClick,
                                     onBookClick = onBookClick,
@@ -995,7 +1036,7 @@ fun BookshelfScreen(
                                         role = Role.Button
                                         role = Role.Button
                                     },
                                     },
                                     onClick = {
                                     onClick = {
-                                        viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupMenu))
+                                        onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.GroupMenu))
                                     }
                                     }
                                 )
                                 )
                             }
                             }
@@ -1006,7 +1047,7 @@ fun BookshelfScreen(
                     if (summary.showGroupName) {
                     if (summary.showGroupName) {
                         RoundDropdownMenu(
                         RoundDropdownMenu(
                             expanded = showGroupMenu,
                             expanded = showGroupMenu,
-                            onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+                            onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
                         ) { dismiss ->
                         ) { dismiss ->
                             uiState.groups.forEach { group ->
                             uiState.groups.forEach { group ->
                                 RoundDropdownMenuItem(
                                 RoundDropdownMenuItem(
@@ -1022,10 +1063,10 @@ fun BookshelfScreen(
                                             }
                                             }
                                         }
                                         }
                                         if (uiState.isSearch || uiState.selectedGroupId != group.groupId) {
                                         if (uiState.isSearch || uiState.selectedGroupId != group.groupId) {
-                                            viewModel.onIntent(BookshelfIntent.ChangeGroup(group.groupId))
+                                            onIntent(BookshelfIntent.ChangeGroup(group.groupId))
                                         }
                                         }
                                         if (bookGroupStyle == 2) {
                                         if (bookGroupStyle == 2) {
-                                            viewModel.onIntent(BookshelfIntent.SetInFolderRoot(false))
+                                            onIntent(BookshelfIntent.SetInFolderRoot(false))
                                         }
                                         }
                                         dismiss()
                                         dismiss()
                                     },
                                     },
@@ -1051,7 +1092,8 @@ fun BookshelfScreen(
     BookshelfOverlays(
     BookshelfOverlays(
         activeOverlay = activeOverlay,
         activeOverlay = activeOverlay,
         uiState = uiState,
         uiState = uiState,
-        viewModel = viewModel,
+        onIntent = onIntent,
+        allGroups = allGroups,
         selectedBookUrls = selectedBookUrls,
         selectedBookUrls = selectedBookUrls,
         importLauncher = importLauncher,
         importLauncher = importLauncher,
         exportLauncher = exportLauncher,
         exportLauncher = exportLauncher,
@@ -1121,7 +1163,8 @@ private fun BookshelfTopBar(
 private fun BookshelfOverlays(
 private fun BookshelfOverlays(
     activeOverlay: BookshelfOverlay?,
     activeOverlay: BookshelfOverlay?,
     uiState: BookshelfUiState,
     uiState: BookshelfUiState,
-    viewModel: BookshelfViewModel,
+    onIntent: (BookshelfIntent) -> Unit,
+    allGroups: List<BookGroup>,
     selectedBookUrls: Set<String>,
     selectedBookUrls: Set<String>,
     importLauncher: ManagedActivityResultLauncher<Array<String>, Uri?>,
     importLauncher: ManagedActivityResultLauncher<Array<String>, Uri?>,
     exportLauncher: ManagedActivityResultLauncher<String, Uri?>,
     exportLauncher: ManagedActivityResultLauncher<String, Uri?>,
@@ -1130,43 +1173,41 @@ private fun BookshelfOverlays(
     BookshelfConfigSheet(
     BookshelfConfigSheet(
         show = activeOverlay == BookshelfOverlay.ConfigSheet,
         show = activeOverlay == BookshelfOverlay.ConfigSheet,
         settings = uiState.settings,
         settings = uiState.settings,
-        onUpdate = { viewModel.onIntent(BookshelfIntent.UpdateSetting(it)) },
+        onUpdate = { onIntent(BookshelfIntent.UpdateSetting(it)) },
         enableCustomTagColors = uiState.enableCustomTagColors,
         enableCustomTagColors = uiState.enableCustomTagColors,
         customTagColors = uiState.customTagColors,
         customTagColors = uiState.customTagColors,
         themeColor = uiState.themeColor,
         themeColor = uiState.themeColor,
-        onThemeUpdate = { viewModel.onIntent(BookshelfIntent.UpdateThemeSetting(it)) },
+        onThemeUpdate = { onIntent(BookshelfIntent.UpdateThemeSetting(it)) },
         onCustomTagColorsChange = {
         onCustomTagColorsChange = {
-            viewModel.onIntent(BookshelfIntent.SetCustomTagColors(it))
+            onIntent(BookshelfIntent.SetCustomTagColors(it))
         },
         },
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
     )
     )
 
 
     GroupManageSheet(
     GroupManageSheet(
         show = activeOverlay == BookshelfOverlay.GroupManageSheet,
         show = activeOverlay == BookshelfOverlay.GroupManageSheet,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
     )
     )
 
 
-    val groups by viewModel.allGroupsFlow.collectAsStateWithLifecycle()
-
     if (activeOverlay is BookshelfOverlay.GroupEditSheet) {
     if (activeOverlay is BookshelfOverlay.GroupEditSheet) {
-        val editGroup = groups.firstOrNull { it.groupId == activeOverlay.groupId }
+        val editGroup = allGroups.firstOrNull { it.groupId == activeOverlay.groupId }
         if (editGroup != null) {
         if (editGroup != null) {
             GroupEditSheet(
             GroupEditSheet(
                 show = true,
                 show = true,
                 group = editGroup,
                 group = editGroup,
-                onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+                onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
             )
             )
         }
         }
     }
     }
 
 
     GroupSelectSheet(
     GroupSelectSheet(
         show = activeOverlay == BookshelfOverlay.GroupSelectSheet,
         show = activeOverlay == BookshelfOverlay.GroupSelectSheet,
-        groups = groups.filter { it.groupId > 0 },
+        groups = allGroups.filter { it.groupId > 0 },
         currentGroupId = 0L,
         currentGroupId = 0L,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) },
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) },
         onConfirm = { groupId ->
         onConfirm = { groupId ->
-            viewModel.onIntent(BookshelfIntent.MoveBooksToGroup(selectedBookUrls, groupId))
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.MoveBooksToGroup(selectedBookUrls, groupId))
+            onIntent(BookshelfIntent.DismissOverlay)
             clearSelection()
             clearSelection()
         }
         }
     )
     )
@@ -1174,58 +1215,58 @@ private fun BookshelfOverlays(
     SourceInputDialog(
     SourceInputDialog(
         show = activeOverlay == BookshelfOverlay.AddUrlDialog,
         show = activeOverlay == BookshelfOverlay.AddUrlDialog,
         title = stringResource(R.string.add_book_url),
         title = stringResource(R.string.add_book_url),
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) },
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) },
         onConfirm = { url ->
         onConfirm = { url ->
-            viewModel.onIntent(BookshelfIntent.AddBookByUrl(url))
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.AddBookByUrl(url))
+            onIntent(BookshelfIntent.DismissOverlay)
         }
         }
     )
     )
 
 
     FilePickerSheet(
     FilePickerSheet(
         show = activeOverlay == BookshelfOverlay.ImportSheet,
         show = activeOverlay == BookshelfOverlay.ImportSheet,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) },
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) },
         title = stringResource(R.string.import_bookshelf),
         title = stringResource(R.string.import_bookshelf),
         onSelectSysFile = { types ->
         onSelectSysFile = { types ->
             importLauncher.launch(types)
             importLauncher.launch(types)
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.DismissOverlay)
         },
         },
         onManualInput = {
         onManualInput = {
-            viewModel.onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.AddUrlDialog))
+            onIntent(BookshelfIntent.ShowOverlay(BookshelfOverlay.AddUrlDialog))
         },
         },
         allowExtensions = arrayOf("json", "txt")
         allowExtensions = arrayOf("json", "txt")
     )
     )
 
 
     FilePickerSheet(
     FilePickerSheet(
         show = activeOverlay == BookshelfOverlay.ExportSheet,
         show = activeOverlay == BookshelfOverlay.ExportSheet,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) },
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) },
         title = stringResource(R.string.export_bookshelf),
         title = stringResource(R.string.export_bookshelf),
         onSelectSysDir = {
         onSelectSysDir = {
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.DismissOverlay)
             exportLauncher.launch("bookshelf.json")
             exportLauncher.launch("bookshelf.json")
         },
         },
         onUpload = {
         onUpload = {
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
-            viewModel.onIntent(BookshelfIntent.UploadBookshelf(uiState.items))
+            onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.UploadBookshelf(uiState.items))
         }
         }
     )
     )
 
 
     AppLogSheet(
     AppLogSheet(
         show = activeOverlay == BookshelfOverlay.LogSheet,
         show = activeOverlay == BookshelfOverlay.LogSheet,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) }
     )
     )
 
 
     AppAlertDialog(
     AppAlertDialog(
         show = activeOverlay == BookshelfOverlay.BatchDownloadConfirmDialog,
         show = activeOverlay == BookshelfOverlay.BatchDownloadConfirmDialog,
-        onDismissRequest = { viewModel.onIntent(BookshelfIntent.DismissOverlay) },
+        onDismissRequest = { onIntent(BookshelfIntent.DismissOverlay) },
         title = stringResource(R.string.draw),
         title = stringResource(R.string.draw),
         text = stringResource(R.string.sure_cache_book),
         text = stringResource(R.string.sure_cache_book),
         confirmText = stringResource(android.R.string.ok),
         confirmText = stringResource(android.R.string.ok),
         onConfirm = {
         onConfirm = {
-            viewModel.onIntent(BookshelfIntent.DismissOverlay)
-            viewModel.onIntent(BookshelfIntent.DownloadBooks(selectedBookUrls))
+            onIntent(BookshelfIntent.DismissOverlay)
+            onIntent(BookshelfIntent.DownloadBooks(selectedBookUrls))
         },
         },
         dismissText = stringResource(android.R.string.cancel),
         dismissText = stringResource(android.R.string.cancel),
-        onDismiss = { viewModel.onIntent(BookshelfIntent.DismissOverlay) }
+        onDismiss = { onIntent(BookshelfIntent.DismissOverlay) }
     )
     )
 
 
     if (uiState.isLoading) {
     if (uiState.isLoading) {

+ 3 - 0
app/src/main/java/io/legado/app/ui/rss/article/RssSortRouteScreen.kt

@@ -24,6 +24,7 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withContext
 import org.koin.androidx.compose.koinViewModel
 import org.koin.androidx.compose.koinViewModel
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
 
 
 @Composable
 @Composable
 fun RssSortRouteScreen(
 fun RssSortRouteScreen(
@@ -52,6 +53,7 @@ fun RssSortRouteScreen(
     var showReadRecordSheet by remember { mutableStateOf(false) }
     var showReadRecordSheet by remember { mutableStateOf(false) }
     var readRecords by remember { mutableStateOf<List<RssReadRecord>>(emptyList()) }
     var readRecords by remember { mutableStateOf<List<RssReadRecord>>(emptyList()) }
     var sourceVariableSheet by remember { mutableStateOf<RssSourceVariableSheetState?>(null) }
     var sourceVariableSheet by remember { mutableStateOf<RssSourceVariableSheetState?>(null) }
+    val shouldShowExpandButton by viewModel.shouldShowExpandButton.collectAsStateWithLifecycle()
 
 
     suspend fun reloadSourceState() {
     suspend fun reloadSourceState() {
         withContext(Dispatchers.IO) {
         withContext(Dispatchers.IO) {
@@ -86,6 +88,7 @@ fun RssSortRouteScreen(
         showReadRecordSheet = showReadRecordSheet,
         showReadRecordSheet = showReadRecordSheet,
         readRecords = readRecords,
         readRecords = readRecords,
         sourceVariableSheet = sourceVariableSheet,
         sourceVariableSheet = sourceVariableSheet,
+        shouldShowExpandButton = shouldShowExpandButton,
         onBackClick = onBackClick,
         onBackClick = onBackClick,
         onSearch = onSearch,
         onSearch = onSearch,
         onLogin = {
         onLogin = {

+ 2 - 2
app/src/main/java/io/legado/app/ui/rss/article/RssSortScreen.kt

@@ -46,7 +46,6 @@ import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.dp
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.data.entities.RssReadRecord
 import io.legado.app.data.entities.RssReadRecord
-import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
 import io.legado.app.ui.rss.read.RedirectPolicy
 import io.legado.app.ui.rss.read.RedirectPolicy
 import io.legado.app.ui.rss.read.title
 import io.legado.app.ui.rss.read.title
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.theme.LegadoTheme
@@ -93,6 +92,7 @@ fun RssSortScreen(
     showReadRecordSheet: Boolean,
     showReadRecordSheet: Boolean,
     readRecords: List<RssReadRecord>,
     readRecords: List<RssReadRecord>,
     sourceVariableSheet: RssSourceVariableSheetState?,
     sourceVariableSheet: RssSourceVariableSheetState?,
+    shouldShowExpandButton: Boolean,
     onBackClick: () -> Unit,
     onBackClick: () -> Unit,
     onSearch: (String) -> Unit,
     onSearch: (String) -> Unit,
     onLogin: () -> Unit,
     onLogin: () -> Unit,
@@ -276,7 +276,7 @@ fun RssSortScreen(
                                 modifier = Modifier.weight(1f)
                                 modifier = Modifier.weight(1f)
                             )
                             )
 
 
-                            if (BookshelfConfig.shouldShowExpandButton) {
+                            if (shouldShowExpandButton) {
                                 Box {
                                 Box {
                                     SmallToggleButton(
                                     SmallToggleButton(
                                         checked = showGroupMenu,
                                         checked = showGroupMenu,

+ 12 - 1
app/src/main/java/io/legado/app/ui/rss/article/RssSortViewModel.kt

@@ -7,6 +7,7 @@ import io.legado.app.data.appDb
 import io.legado.app.data.entities.RssArticle
 import io.legado.app.data.entities.RssArticle
 import io.legado.app.data.entities.RssReadRecord
 import io.legado.app.data.entities.RssReadRecord
 import io.legado.app.data.entities.RssSource
 import io.legado.app.data.entities.RssSource
+import io.legado.app.domain.gateway.BookshelfSettingsGateway
 import io.legado.app.help.source.removeSortCache
 import io.legado.app.help.source.removeSortCache
 import io.legado.app.help.source.sortUrls
 import io.legado.app.help.source.sortUrls
 import io.legado.app.utils.GSONStrict
 import io.legado.app.utils.GSONStrict
@@ -14,8 +15,18 @@ import io.legado.app.utils.fromJsonObject
 import io.legado.app.utils.isJsonObject
 import io.legado.app.utils.isJsonObject
 import io.legado.app.utils.toastOnUi
 import io.legado.app.utils.toastOnUi
 import splitties.init.appCtx
 import splitties.init.appCtx
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
 
 
-class RssSortViewModel(application: Application) : BaseViewModel(application) {
+class RssSortViewModel(
+    application: Application,
+    bookshelfSettingsGateway: BookshelfSettingsGateway,
+) : BaseViewModel(application) {
+    val shouldShowExpandButton = bookshelfSettingsGateway.settings
+        .map { it.shouldShowExpandButton }
+        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
     var url: String? = null
     var url: String? = null
     var rssSource: RssSource? = null
     var rssSource: RssSource? = null
     val titleLiveData = MutableLiveData<String>()
     val titleLiveData = MutableLiveData<String>()

+ 24 - 1
app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt

@@ -11,6 +11,8 @@ import io.legado.app.data.appDb
 import io.legado.app.data.entities.RssArticle
 import io.legado.app.data.entities.RssArticle
 import io.legado.app.data.entities.RssSource
 import io.legado.app.data.entities.RssSource
 import io.legado.app.data.entities.RssStar
 import io.legado.app.data.entities.RssStar
+import io.legado.app.domain.gateway.AppShellSettingsGateway
+import io.legado.app.domain.gateway.DownloadCacheSettingsGateway
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.exception.NoStackTraceException
 import io.legado.app.help.TTS
 import io.legado.app.help.TTS
 import io.legado.app.help.http.newCallResponseBody
 import io.legado.app.help.http.newCallResponseBody
@@ -24,6 +26,9 @@ import kotlinx.coroutines.Dispatchers.IO
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.stateIn
 import splitties.init.appCtx
 import splitties.init.appCtx
 import kotlin.coroutines.coroutineContext
 import kotlin.coroutines.coroutineContext
 
 
@@ -35,7 +40,25 @@ data class ReadRssArgs(
     val startPage: Boolean = false
     val startPage: Boolean = false
 )
 )
 
 
-class ReadRssViewModel(application: Application) : BaseViewModel(application) {
+data class ReadRssSettings(
+    val showStatusBar: Boolean = true,
+    val userAgent: String = "",
+)
+
+class ReadRssViewModel(
+    application: Application,
+    appShellSettingsGateway: AppShellSettingsGateway,
+    downloadCacheSettingsGateway: DownloadCacheSettingsGateway,
+) : BaseViewModel(application) {
+    val settings = combine(
+        appShellSettingsGateway.settings,
+        downloadCacheSettingsGateway.settings,
+    ) { appShell, download ->
+        ReadRssSettings(
+            showStatusBar = appShell.showStatusBar,
+            userAgent = download.userAgent,
+        )
+    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), ReadRssSettings())
     var rssSource: RssSource? = null
     var rssSource: RssSource? = null
     var rssArticle: RssArticle? = null
     var rssArticle: RssArticle? = null
     var tts: TTS? = null
     var tts: TTS? = null

+ 3 - 4
app/src/main/java/io/legado/app/ui/rss/read/RssReadRouteScreen.kt

@@ -51,9 +51,7 @@ import androidx.compose.ui.zIndex
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.constant.AppConst
 import io.legado.app.constant.AppConst
-import io.legado.app.help.config.AppConfig
 import io.legado.app.help.http.CookieManager
 import io.legado.app.help.http.CookieManager
-import io.legado.app.ui.config.otherConfig.OtherConfig
 import io.legado.app.ui.login.SourceLoginActivity
 import io.legado.app.ui.login.SourceLoginActivity
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.theme.LegadoTheme
 import io.legado.app.ui.theme.LocalHazeState
 import io.legado.app.ui.theme.LocalHazeState
@@ -124,7 +122,8 @@ fun RssReadRouteScreen(
     val content by viewModel.contentState.collectAsStateWithLifecycle()
     val content by viewModel.contentState.collectAsStateWithLifecycle()
     val analyzeUrl by viewModel.urlState.collectAsStateWithLifecycle()
     val analyzeUrl by viewModel.urlState.collectAsStateWithLifecycle()
     val isSpeaking by viewModel.isSpeakingState.collectAsStateWithLifecycle()
     val isSpeaking by viewModel.isSpeakingState.collectAsStateWithLifecycle()
-    val fallbackUserAgent = OtherConfig.userAgent
+    val settings by viewModel.settings.collectAsStateWithLifecycle()
+    val fallbackUserAgent = settings.userAgent
 
 
     fun hideCustomView() {
     fun hideCustomView() {
         val currentCustomView = customView ?: return
         val currentCustomView = customView ?: return
@@ -132,7 +131,7 @@ fun RssReadRouteScreen(
         customView = null
         customView = null
         customViewCallback = null
         customViewCallback = null
         activity?.keepScreenOn(false)
         activity?.keepScreenOn(false)
-        activity?.toggleSystemBar(AppConfig.showStatusBar)
+        activity?.toggleSystemBar(settings.showStatusBar)
     }
     }
 
 
     LaunchedEffect(origin, link, openUrl, title, startPage) {
     LaunchedEffect(origin, link, openUrl, title, startPage) {