From 86bd1b467c0930972535ad0ef92e1614c59c6eef Mon Sep 17 00:00:00 2001
From: Ash <glaxyinfinite@outlook.com>
Date: Fri, 29 Apr 2022 06:00:59 +0800
Subject: [PATCH] Add initial page and initial filter settings

---
 .../reader/ui/component/BlockRadioButton.kt   |  12 +-
 .../me/ash/reader/ui/component/RadioDialog.kt |  84 +++++++++
 .../java/me/ash/reader/ui/ext/DataStoreExt.kt |  14 ++
 .../me/ash/reader/ui/page/common/HomeEntry.kt |  74 +++++---
 .../me/ash/reader/ui/page/common/RouteName.kt |   1 +
 .../ash/reader/ui/page/home/HomeViewModel.kt  |   4 +-
 .../reader/ui/page/home/feeds/FeedsPage.kt    |   4 +-
 .../ash/reader/ui/page/home/flow/FlowPage.kt  |  10 +-
 .../reader/ui/page/settings/SettingsPage.kt   |  14 +-
 .../settings/{ => color}/ColorAndStyle.kt     |  11 +-
 .../page/settings/interaction/Interaction.kt  | 168 ++++++++++++++++++
 .../settings/{ => tips}/TipsAndSupport.kt     |   2 +-
 .../page/settings/{ => tips}/UpdateDialog.kt  |   2 +-
 .../settings/{ => tips}/UpdateViewModel.kt    |   2 +-
 .../ash/reader/ui/page/startup/StartupPage.kt |   4 +-
 app/src/main/res/values-zh-rCN/strings.xml    |   5 +-
 app/src/main/res/values/strings.xml           |   5 +-
 17 files changed, 367 insertions(+), 49 deletions(-)
 create mode 100644 app/src/main/java/me/ash/reader/ui/component/RadioDialog.kt
 rename app/src/main/java/me/ash/reader/ui/page/settings/{ => color}/ColorAndStyle.kt (97%)
 create mode 100644 app/src/main/java/me/ash/reader/ui/page/settings/interaction/Interaction.kt
 rename app/src/main/java/me/ash/reader/ui/page/settings/{ => tips}/TipsAndSupport.kt (99%)
 rename app/src/main/java/me/ash/reader/ui/page/settings/{ => tips}/UpdateDialog.kt (99%)
 rename app/src/main/java/me/ash/reader/ui/page/settings/{ => tips}/UpdateViewModel.kt (98%)

diff --git a/app/src/main/java/me/ash/reader/ui/component/BlockRadioButton.kt b/app/src/main/java/me/ash/reader/ui/component/BlockRadioButton.kt
index 1f011dc8..d1633bb1 100644
--- a/app/src/main/java/me/ash/reader/ui/component/BlockRadioButton.kt
+++ b/app/src/main/java/me/ash/reader/ui/component/BlockRadioButton.kt
@@ -7,11 +7,11 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
 
 @Composable
-fun BlockButtonRadios(
+fun BlockRadioGroupButton(
     modifier: Modifier = Modifier,
     selected: Int = 0,
     onSelected: (Int) -> Unit,
-    items: List<BlockButtonRadiosItem> = listOf(),
+    itemRadioGroups: List<BlockRadioGroupButtonItem> = listOf(),
 ) {
 
     Column {
@@ -20,11 +20,11 @@ fun BlockButtonRadios(
             horizontalArrangement = Arrangement.SpaceBetween,
             verticalAlignment = Alignment.CenterVertically,
         ) {
-            items.forEachIndexed { index, item ->
+            itemRadioGroups.forEachIndexed { index, item ->
                 BlockButton(
                     modifier = Modifier
                         .weight(1f)
-                        .padding(end = if (item == items.last()) 0.dp else 8.dp),
+                        .padding(end = if (item == itemRadioGroups.last()) 0.dp else 8.dp),
                     text = item.text,
                     selected = selected == index,
                 ) {
@@ -34,11 +34,11 @@ fun BlockButtonRadios(
             }
         }
         Spacer(modifier = Modifier.height(24.dp))
-        items[selected].content()
+        itemRadioGroups[selected].content()
     }
 }
 
-data class BlockButtonRadiosItem(
+data class BlockRadioGroupButtonItem(
     val text: String,
     val onClick: () -> Unit = {},
     val content: @Composable () -> Unit,
diff --git a/app/src/main/java/me/ash/reader/ui/component/RadioDialog.kt b/app/src/main/java/me/ash/reader/ui/component/RadioDialog.kt
new file mode 100644
index 00000000..ff1608c2
--- /dev/null
+++ b/app/src/main/java/me/ash/reader/ui/component/RadioDialog.kt
@@ -0,0 +1,84 @@
+package me.ash.reader.ui.component
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RadioButton
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.text.style.BaselineShift
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import com.google.accompanist.pager.ExperimentalPagerApi
+
+@OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class)
+@Composable
+fun RadioDialog(
+    modifier: Modifier = Modifier,
+    visible: Boolean = false,
+    title: String = "",
+    options: List<RadioDialogOption> = emptyList(),
+    onDismissRequest: () -> Unit = {},
+) {
+    Dialog(
+        modifier = modifier,
+        visible = visible,
+        onDismissRequest = onDismissRequest,
+        title = {
+            Text(
+                text = title,
+                maxLines = 1,
+                overflow = TextOverflow.Ellipsis,
+                style = MaterialTheme.typography.titleLarge,
+            )
+        },
+        text = {
+            LazyColumn {
+                items(options) { option ->
+                    Row(
+                        modifier = Modifier
+                            .fillMaxWidth()
+                            .clip(CircleShape)
+                            .clickable {
+                                option.onClick()
+                                onDismissRequest()
+                            },
+                        verticalAlignment = Alignment.CenterVertically,
+                    ) {
+                        RadioButton(selected = option.selected, onClick = {
+                            option.onClick()
+                            onDismissRequest()
+                        })
+                        Text(
+                            modifier = Modifier.padding(start = 6.dp),
+                            text = option.text,
+                            style = MaterialTheme.typography.bodyLarge.copy(
+                                baselineShift = BaselineShift.None
+                            ),
+                            color = MaterialTheme.colorScheme.onSurface,
+                        )
+                    }
+                }
+            }
+        },
+        confirmButton = {},
+        dismissButton = {},
+    )
+}
+
+@Immutable
+data class RadioDialogOption(
+    val text: String = "",
+    val selected: Boolean = false,
+    val onClick: () -> Unit = {},
+)
\ No newline at end of file
diff --git a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt
index 3f9faaea..52d749c0 100644
--- a/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt
+++ b/app/src/main/java/me/ash/reader/ui/ext/DataStoreExt.kt
@@ -35,6 +35,10 @@ val Context.themeIndex: Int
     get() = this.dataStore.get(DataStoreKeys.ThemeIndex) ?: 5
 val Context.customPrimaryColor: String
     get() = this.dataStore.get(DataStoreKeys.CustomPrimaryColor) ?: ""
+val Context.initialPage: Int
+    get() = this.dataStore.get(DataStoreKeys.InitialPage) ?: 0
+val Context.initialFilter: Int
+    get() = this.dataStore.get(DataStoreKeys.InitialFilter) ?: 2
 
 suspend fun <T> DataStore<Preferences>.put(dataStoreKeys: DataStoreKeys<T>, value: T) {
     this.edit {
@@ -124,4 +128,14 @@ sealed class DataStoreKeys<T> {
         override val key: Preferences.Key<String>
             get() = stringPreferencesKey("customPrimaryColor")
     }
+
+    object InitialPage : DataStoreKeys<Int>() {
+        override val key: Preferences.Key<Int>
+            get() = intPreferencesKey("initialPage")
+    }
+
+    object InitialFilter : DataStoreKeys<Int>() {
+        override val key: Preferences.Key<Int>
+            get() = intPreferencesKey("initialFilter")
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt b/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt
index df745168..bd335132 100644
--- a/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt
@@ -13,17 +13,17 @@ import androidx.paging.compose.collectAsLazyPagingItems
 import com.google.accompanist.navigation.animation.AnimatedNavHost
 import com.google.accompanist.navigation.animation.rememberAnimatedNavController
 import com.google.accompanist.systemuicontroller.rememberSystemUiController
-import me.ash.reader.ui.ext.animatedComposable
-import me.ash.reader.ui.ext.collectAsStateValue
-import me.ash.reader.ui.ext.findActivity
-import me.ash.reader.ui.ext.isFirstLaunch
+import me.ash.reader.data.entity.Filter
+import me.ash.reader.ui.ext.*
+import me.ash.reader.ui.page.home.HomeViewAction
 import me.ash.reader.ui.page.home.HomeViewModel
 import me.ash.reader.ui.page.home.feeds.FeedsPage
 import me.ash.reader.ui.page.home.flow.FlowPage
 import me.ash.reader.ui.page.home.read.ReadPage
-import me.ash.reader.ui.page.settings.ColorAndStyle
 import me.ash.reader.ui.page.settings.SettingsPage
-import me.ash.reader.ui.page.settings.TipsAndSupport
+import me.ash.reader.ui.page.settings.color.ColorAndStyle
+import me.ash.reader.ui.page.settings.interaction.Interaction
+import me.ash.reader.ui.page.settings.tips.TipsAndSupport
 import me.ash.reader.ui.page.startup.StartupPage
 import me.ash.reader.ui.theme.AppTheme
 import me.ash.reader.ui.theme.LocalUseDarkTheme
@@ -33,30 +33,59 @@ import me.ash.reader.ui.theme.LocalUseDarkTheme
 fun HomeEntry(
     homeViewModel: HomeViewModel = hiltViewModel(),
 ) {
+    val context = LocalContext.current
     val viewState = homeViewModel.viewState.collectAsStateValue()
+    val filterState = homeViewModel.filterState.collectAsStateValue()
     val pagingItems = viewState.pagingData.collectAsLazyPagingItems()
 
-    AppTheme {
-        val context = LocalContext.current
-        val useDarkTheme = LocalUseDarkTheme.current
-        val navController = rememberAnimatedNavController()
+    val navController = rememberAnimatedNavController()
 
-        val intent by rememberSaveable { mutableStateOf(context.findActivity()?.intent) }
-        var openArticleId by rememberSaveable {
-            mutableStateOf(intent?.extras?.get(ExtraName.ARTICLE_ID)?.toString() ?: "")
-        }.also {
-            intent?.replaceExtras(null)
-        }
+    val intent by rememberSaveable { mutableStateOf(context.findActivity()?.intent) }
+    var openArticleId by rememberSaveable {
+        mutableStateOf(intent?.extras?.get(ExtraName.ARTICLE_ID)?.toString() ?: "")
+    }.also {
+        intent?.replaceExtras(null)
+    }
 
-        LaunchedEffect(openArticleId) {
-            if (openArticleId.isNotEmpty()) {
-                navController.navigate("${RouteName.READING}/${openArticleId}") {
-                    popUpTo(RouteName.FEEDS)
+    LaunchedEffect(Unit) {
+        when (context.initialPage) {
+            1 -> {
+                navController.navigate(RouteName.FLOW) {
+                    launchSingleTop = true
                 }
-                openArticleId = ""
             }
+            // Other initial pages
         }
 
+        homeViewModel.dispatch(
+            HomeViewAction.ChangeFilter(
+                filterState.copy(
+                    filter = when (context.initialFilter) {
+                        0 -> Filter.Starred
+                        1 -> Filter.Unread
+                        2 -> Filter.All
+                        else -> Filter.All
+                    }
+                )
+            )
+        )
+    }
+
+    LaunchedEffect(openArticleId) {
+        if (openArticleId.isNotEmpty()) {
+            navController.navigate(RouteName.FLOW) {
+                launchSingleTop = true
+            }
+            navController.navigate("${RouteName.READING}/${openArticleId}") {
+                launchSingleTop = true
+            }
+            openArticleId = ""
+        }
+    }
+
+    AppTheme {
+        val useDarkTheme = LocalUseDarkTheme.current
+
         rememberSystemUiController().run {
             setStatusBarColor(Color.Transparent, !useDarkTheme)
             setSystemBarsColor(Color.Transparent, !useDarkTheme)
@@ -90,6 +119,9 @@ fun HomeEntry(
             animatedComposable(route = RouteName.COLOR_AND_STYLE) {
                 ColorAndStyle(navController)
             }
+            animatedComposable(route = RouteName.INTERACTION) {
+                Interaction(navController)
+            }
             animatedComposable(route = RouteName.TIPS_AND_SUPPORT) {
                 TipsAndSupport(navController)
             }
diff --git a/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt b/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt
index 36a8c055..aa4accbe 100644
--- a/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/common/RouteName.kt
@@ -7,5 +7,6 @@ object RouteName {
     const val READING = "reading"
     const val SETTINGS = "settings"
     const val COLOR_AND_STYLE = "color_and_style"
+    const val INTERACTION = "interaction"
     const val TIPS_AND_SUPPORT = "tips_and_support"
 }
\ No newline at end of file
diff --git a/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt
index 585607be..e2ea70b8 100644
--- a/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/home/HomeViewModel.kt
@@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModel
 import androidx.paging.*
 import androidx.work.WorkManager
 import com.google.accompanist.pager.ExperimentalPagerApi
-import com.google.accompanist.pager.PagerState
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.*
@@ -25,7 +24,7 @@ class HomeViewModel @Inject constructor(
     private val stringsRepository: StringsRepository,
     @ApplicationScope
     private val applicationScope: CoroutineScope,
-    workManager: WorkManager,
+    private val workManager: WorkManager,
 ) : ViewModel() {
 
     private val _viewState = MutableStateFlow(HomeViewState())
@@ -115,7 +114,6 @@ data class FilterState(
 
 @OptIn(ExperimentalPagerApi::class)
 data class HomeViewState(
-    val pagerState: PagerState = PagerState(0),
     val pagingData: Flow<PagingData<FlowItemView>> = emptyFlow(),
     val searchContent: String = "",
 )
diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt
index e38b36f5..d13ffa3b 100644
--- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt
@@ -132,7 +132,7 @@ fun FeedsPage(
                         showBadge = latestVersion.whetherNeedUpdate(currentVersion, skipVersion),
                     ) {
                         navController.navigate(RouteName.SETTINGS) {
-                            popUpTo(RouteName.FEEDS)
+                            launchSingleTop = true
                         }
                     }
                 },
@@ -271,7 +271,7 @@ private fun filterChange(
     homeViewModel.dispatch(HomeViewAction.ChangeFilter(filterState))
     if (isNavigate) {
         navController.navigate(RouteName.FLOW) {
-            popUpTo(RouteName.FEEDS)
+            launchSingleTop = true
         }
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt
index 4dce2429..c0367176 100644
--- a/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt
@@ -113,7 +113,13 @@ fun FlowPage(
                         tint = MaterialTheme.colorScheme.onSurface
                     ) {
                         onSearch = false
-                        navController.popBackStack()
+                        if(navController.previousBackStackEntry == null) {
+                            navController.navigate(RouteName.FEEDS) {
+                                launchSingleTop = true
+                            }
+                        } else {
+                            navController.popBackStack()
+                        }
                     }
                 },
                 actions = {
@@ -241,7 +247,7 @@ fun FlowPage(
                     ) {
                         onSearch = false
                         navController.navigate("${RouteName.READING}/${it.article.id}") {
-                            popUpTo(RouteName.FLOW)
+                            launchSingleTop = true
                         }
                     }
                     item {
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/SettingsPage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/SettingsPage.kt
index 1118a636..0cb21dc7 100644
--- a/app/src/main/java/me/ash/reader/ui/page/settings/SettingsPage.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/SettingsPage.kt
@@ -27,6 +27,9 @@ import me.ash.reader.ui.ext.DataStoreKeys
 import me.ash.reader.ui.ext.dataStore
 import me.ash.reader.ui.ext.getCurrentVersion
 import me.ash.reader.ui.page.common.RouteName
+import me.ash.reader.ui.page.settings.tips.UpdateDialog
+import me.ash.reader.ui.page.settings.tips.UpdateViewAction
+import me.ash.reader.ui.page.settings.tips.UpdateViewModel
 import me.ash.reader.ui.theme.palette.onLight
 
 @SuppressLint("FlowOperatorInvokedInComposition")
@@ -120,7 +123,7 @@ fun SettingsPage(
                         icon = Icons.Outlined.Palette,
                     ) {
                         navController.navigate(RouteName.COLOR_AND_STYLE) {
-                            popUpTo(RouteName.SETTINGS)
+                            launchSingleTop = true
                         }
                     }
                 }
@@ -129,8 +132,11 @@ fun SettingsPage(
                         title = stringResource(R.string.interaction),
                         desc = stringResource(R.string.interaction_desc),
                         icon = Icons.Outlined.TouchApp,
-                        enable = false,
-                    ) {}
+                    ) {
+                        navController.navigate(RouteName.INTERACTION) {
+                            launchSingleTop = true
+                        }
+                    }
                 }
                 item {
                     SelectableSettingGroupItem(
@@ -147,7 +153,7 @@ fun SettingsPage(
                         icon = Icons.Outlined.TipsAndUpdates,
                     ) {
                         navController.navigate(RouteName.TIPS_AND_SUPPORT) {
-                            popUpTo(RouteName.SETTINGS)
+                            launchSingleTop = true
                         }
                     }
                 }
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/ColorAndStyle.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt
similarity index 97%
rename from app/src/main/java/me/ash/reader/ui/page/settings/ColorAndStyle.kt
rename to app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt
index 8b89719f..e3ba1147 100644
--- a/app/src/main/java/me/ash/reader/ui/page/settings/ColorAndStyle.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/ColorAndStyle.kt
@@ -1,4 +1,4 @@
-package me.ash.reader.ui.page.settings
+package me.ash.reader.ui.page.settings.color
 
 import android.annotation.SuppressLint
 import android.os.Build
@@ -30,6 +30,7 @@ import kotlinx.coroutines.launch
 import me.ash.reader.R
 import me.ash.reader.ui.component.*
 import me.ash.reader.ui.ext.*
+import me.ash.reader.ui.page.settings.SettingItem
 import me.ash.reader.ui.svg.PALETTE
 import me.ash.reader.ui.svg.SVGString
 import me.ash.reader.ui.theme.LocalUseDarkTheme
@@ -101,11 +102,11 @@ fun ColorAndStyle(
                     Spacer(modifier = Modifier.height(24.dp))
                 }
                 item {
-                    BlockButtonRadios(
+                    BlockRadioGroupButton(
                         selected = radioButtonSelected,
                         onSelected = { radioButtonSelected = it },
-                        items = listOf(
-                            BlockButtonRadiosItem(
+                        itemRadioGroups = listOf(
+                            BlockRadioGroupButtonItem(
                                 text = stringResource(R.string.wallpaper_colors),
                                 onClick = {},
                             ) {
@@ -120,7 +121,7 @@ fun ColorAndStyle(
                                     themeIndexPrefix = 5,
                                 )
                             },
-                            BlockButtonRadiosItem(
+                            BlockRadioGroupButtonItem(
                                 text = stringResource(R.string.basic_colors),
                                 onClick = {},
                             ) {
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/interaction/Interaction.kt b/app/src/main/java/me/ash/reader/ui/page/settings/interaction/Interaction.kt
new file mode 100644
index 00000000..40ce721c
--- /dev/null
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/interaction/Interaction.kt
@@ -0,0 +1,168 @@
+package me.ash.reader.ui.page.settings.interaction
+
+import android.annotation.SuppressLint
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.rounded.ArrowBack
+import androidx.compose.material3.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.navigation.NavHostController
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import me.ash.reader.R
+import me.ash.reader.ui.component.*
+import me.ash.reader.ui.ext.DataStoreKeys
+import me.ash.reader.ui.ext.dataStore
+import me.ash.reader.ui.ext.put
+import me.ash.reader.ui.page.settings.SettingItem
+import me.ash.reader.ui.theme.palette.onLight
+
+@SuppressLint("FlowOperatorInvokedInComposition")
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun Interaction(
+    navController: NavHostController,
+) {
+    val context = LocalContext.current
+    val view = LocalView.current
+    val scope = rememberCoroutineScope()
+    var initialPageDialogVisible by remember { mutableStateOf(false) }
+    var initialFilterDialogVisible by remember { mutableStateOf(false) }
+
+    val initialPage = context.dataStore.data
+        .map { it[DataStoreKeys.InitialPage.key] ?: 0 }
+        .collectAsState(initial = 0).value
+
+    val initialFilter = context.dataStore.data
+        .map { it[DataStoreKeys.InitialFilter.key] ?: 2 }
+        .collectAsState(initial = 2).value
+
+    Scaffold(
+        modifier = Modifier
+            .background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
+            .statusBarsPadding()
+            .navigationBarsPadding(),
+        containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
+        topBar = {
+            SmallTopAppBar(
+                colors = TopAppBarDefaults.smallTopAppBarColors(
+                    containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface
+                ),
+                title = {},
+                navigationIcon = {
+                    FeedbackIconButton(
+                        imageVector = Icons.Rounded.ArrowBack,
+                        contentDescription = stringResource(R.string.back),
+                        tint = MaterialTheme.colorScheme.onSurface
+                    ) {
+                        navController.popBackStack()
+                    }
+                },
+                actions = {}
+            )
+        },
+        content = {
+            LazyColumn {
+                item {
+                    DisplayText(text = stringResource(R.string.interaction), desc = "")
+                    Spacer(modifier = Modifier.height(16.dp))
+                }
+                item {
+                    Subtitle(
+                        modifier = Modifier.padding(horizontal = 24.dp),
+                        text = stringResource(R.string.on_start),
+                    )
+                    SettingItem(
+                        title = stringResource(R.string.initial_page),
+                        desc = when (initialPage) {
+                            0 -> stringResource(R.string.feeds_page)
+                            1 -> stringResource(R.string.flow_page)
+                            else -> ""
+                        },
+                        onClick = {
+                            initialPageDialogVisible = true
+                        },
+                    ) {}
+                    SettingItem(
+                        title = stringResource(R.string.initial_filter),
+                        desc = when (initialFilter) {
+                            0 -> stringResource(R.string.starred)
+                            1 -> stringResource(R.string.unread)
+                            2 -> stringResource(R.string.all)
+                            else -> ""
+                        },
+                        onClick = {
+                            initialFilterDialogVisible = true
+                        },
+                    ) {}
+                }
+            }
+        }
+    )
+
+    RadioDialog(
+        visible = initialPageDialogVisible,
+        title = stringResource(R.string.initial_page),
+        options = listOf(
+            RadioDialogOption(
+                text = stringResource(R.string.feeds_page),
+                selected = initialPage == 0,
+            ) {
+                scope.launch(Dispatchers.IO) {
+                    context.dataStore.put(DataStoreKeys.InitialPage, 0)
+                }
+            },
+            RadioDialogOption(
+                text = stringResource(R.string.flow_page),
+                selected = initialPage == 1,
+            ) {
+                scope.launch(Dispatchers.IO) {
+                    context.dataStore.put(DataStoreKeys.InitialPage, 1)
+                }
+            },
+        ),
+    ) {
+        initialPageDialogVisible = false
+    }
+
+    RadioDialog(
+        visible = initialFilterDialogVisible,
+        title = stringResource(R.string.initial_filter),
+        options = listOf(
+            RadioDialogOption(
+                text = stringResource(R.string.starred),
+                selected = initialFilter == 0,
+            ) {
+                scope.launch(Dispatchers.IO) {
+                    context.dataStore.put(DataStoreKeys.InitialFilter, 0)
+                }
+            },
+            RadioDialogOption(
+                text = stringResource(R.string.unread),
+                selected = initialFilter == 1,
+            ) {
+                scope.launch(Dispatchers.IO) {
+                    context.dataStore.put(DataStoreKeys.InitialFilter, 1)
+                }
+            },
+            RadioDialogOption(
+                text = stringResource(R.string.all),
+                selected = initialFilter == 2,
+            ) {
+                scope.launch(Dispatchers.IO) {
+                    context.dataStore.put(DataStoreKeys.InitialFilter, 2)
+                }
+            },
+        ),
+    ) {
+        initialFilterDialogVisible = false
+    }
+}
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/TipsAndSupport.kt b/app/src/main/java/me/ash/reader/ui/page/settings/tips/TipsAndSupport.kt
similarity index 99%
rename from app/src/main/java/me/ash/reader/ui/page/settings/TipsAndSupport.kt
rename to app/src/main/java/me/ash/reader/ui/page/settings/tips/TipsAndSupport.kt
index b4d19920..66e00de4 100644
--- a/app/src/main/java/me/ash/reader/ui/page/settings/TipsAndSupport.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/tips/TipsAndSupport.kt
@@ -1,4 +1,4 @@
-package me.ash.reader.ui.page.settings
+package me.ash.reader.ui.page.settings.tips
 
 import android.content.Intent
 import android.net.Uri
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/UpdateDialog.kt b/app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateDialog.kt
similarity index 99%
rename from app/src/main/java/me/ash/reader/ui/page/settings/UpdateDialog.kt
rename to app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateDialog.kt
index bdea512a..081058be 100644
--- a/app/src/main/java/me/ash/reader/ui/page/settings/UpdateDialog.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateDialog.kt
@@ -1,4 +1,4 @@
-package me.ash.reader.ui.page.settings
+package me.ash.reader.ui.page.settings.tips
 
 import android.Manifest
 import android.annotation.SuppressLint
diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/UpdateViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateViewModel.kt
similarity index 98%
rename from app/src/main/java/me/ash/reader/ui/page/settings/UpdateViewModel.kt
rename to app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateViewModel.kt
index 80f28925..4d7d75c9 100644
--- a/app/src/main/java/me/ash/reader/ui/page/settings/UpdateViewModel.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/settings/tips/UpdateViewModel.kt
@@ -1,4 +1,4 @@
-package me.ash.reader.ui.page.settings
+package me.ash.reader.ui.page.settings.tips
 
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
diff --git a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt
index da7c51d8..c302a91b 100644
--- a/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt
+++ b/app/src/main/java/me/ash/reader/ui/page/startup/StartupPage.kt
@@ -102,7 +102,9 @@ fun StartupPage(
         floatingActionButton = {
             ExtendedFloatingActionButton(
                 onClick = {
-                    navController.navigate(RouteName.FEEDS)
+                    navController.navigate(RouteName.FEEDS) {
+                        launchSingleTop = true
+                    }
                     scope.launch {
                         context.dataStore.put(DataStoreKeys.IsFirstLaunch, false)
                     }
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index ee1d42f2..84ffc0de 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -81,7 +81,7 @@
     <string name="color_and_style">颜色和样式</string>
     <string name="color_and_style_desc">主题、色彩系统、字体大小</string>
     <string name="interaction">交互</string>
-    <string name="interaction_desc">布局、触感反馈</string>
+    <string name="interaction_desc">启动时、触感反馈</string>
     <string name="languages">语言</string>
     <string name="languages_desc">英语、中文</string>
     <string name="tips_and_support">提示和支持</string>
@@ -121,4 +121,7 @@
     <string name="download_failure">下载失败</string>
     <string name="rate_limit">请求速率受限</string>
     <string name="help">帮助</string>
+    <string name="on_start">启动时</string>
+    <string name="initial_page">起始页面</string>
+    <string name="initial_filter">起始过滤条件</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6fc487b0..4aa92b79 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -81,7 +81,7 @@
     <string name="color_and_style">Color &amp; style</string>
     <string name="color_and_style_desc">Theme, color system, font size</string>
     <string name="interaction">Interaction</string>
-    <string name="interaction_desc">Layout, haptic feedback</string>
+    <string name="interaction_desc">On start, haptic feedback</string>
     <string name="languages">Languages</string>
     <string name="languages_desc">English, Chinese</string>
     <string name="tips_and_support">Tips &amp; support</string>
@@ -121,4 +121,7 @@
     <string name="download_failure">Download failure</string>
     <string name="rate_limit">The request rate is limited</string>
     <string name="help">Help</string>
+    <string name="on_start">On Start</string>
+    <string name="initial_page">Initial Page</string>
+    <string name="initial_filter">Initial Filter</string>
 </resources>
\ No newline at end of file