Extract Scaffold component

This commit is contained in:
Ash 2022-05-18 05:41:21 +08:00
parent 27e8780d82
commit dcbb41f3ab
22 changed files with 487 additions and 524 deletions

View File

@ -0,0 +1,45 @@
package me.ash.reader.data.preference
import android.content.Context
import androidx.datastore.preferences.core.Preferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import me.ash.reader.R
import me.ash.reader.ui.ext.DataStoreKeys
import me.ash.reader.ui.ext.dataStore
import me.ash.reader.ui.ext.put
sealed class InitialFilterPreference(val value: Int) : Preference() {
object Starred : InitialFilterPreference(0)
object Unread : InitialFilterPreference(1)
object All : InitialFilterPreference(2)
override fun put(context: Context, scope: CoroutineScope) {
scope.launch {
context.dataStore.put(
DataStoreKeys.InitialFilter,
value
)
}
}
fun getDesc(context: Context): String =
when (this) {
Starred -> context.getString(R.string.starred)
Unread -> context.getString(R.string.unread)
All -> context.getString(R.string.all)
}
companion object {
val default = All
val values = listOf(Starred, Unread, All)
fun fromPreferences(preferences: Preferences) =
when (preferences[DataStoreKeys.InitialFilter.key]) {
0 -> Starred
1 -> Unread
2 -> All
else -> default
}
}
}

View File

@ -0,0 +1,42 @@
package me.ash.reader.data.preference
import android.content.Context
import androidx.datastore.preferences.core.Preferences
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import me.ash.reader.R
import me.ash.reader.ui.ext.DataStoreKeys
import me.ash.reader.ui.ext.dataStore
import me.ash.reader.ui.ext.put
sealed class InitialPagePreference(val value: Int) : Preference() {
object FeedsPage : InitialPagePreference(0)
object FlowPage : InitialPagePreference(1)
override fun put(context: Context, scope: CoroutineScope) {
scope.launch {
context.dataStore.put(
DataStoreKeys.InitialPage,
value
)
}
}
fun getDesc(context: Context): String =
when (this) {
FeedsPage -> context.getString(R.string.feeds_page)
FlowPage -> context.getString(R.string.flow_page)
}
companion object {
val default = FeedsPage
val values = listOf(FeedsPage, FlowPage)
fun fromPreferences(preferences: Preferences) =
when (preferences[DataStoreKeys.InitialPage.key]) {
0 -> FeedsPage
1 -> FlowPage
else -> default
}
}
}

View File

@ -45,6 +45,9 @@ fun Preferences.toSettings(): Settings {
),
flowArticleListTonalElevation = FlowArticleListTonalElevationPreference.fromPreferences(this),
initialPage = InitialPagePreference.fromPreferences(this),
initialFilter = InitialFilterPreference.fromPreferences(this),
languages = LanguagesPreference.fromPreferences(this),
)
}

View File

@ -45,6 +45,9 @@ data class Settings(
val flowArticleListDateStickyHeader: FlowArticleListDateStickyHeaderPreference = FlowArticleListDateStickyHeaderPreference.default,
val flowArticleListTonalElevation: FlowArticleListTonalElevationPreference = FlowArticleListTonalElevationPreference.default,
val initialPage: InitialPagePreference = InitialPagePreference.default,
val initialFilter: InitialFilterPreference = InitialFilterPreference.default,
val languages: LanguagesPreference = LanguagesPreference.default,
)
@ -94,6 +97,9 @@ fun SettingsProvider(
LocalFlowFilterBarPadding provides settings.flowFilterBarPadding,
LocalFlowFilterBarTonalElevation provides settings.flowFilterBarTonalElevation,
LocalInitialPage provides settings.initialPage,
LocalInitialFilter provides settings.initialFilter,
LocalLanguages provides settings.languages,
) {
content()
@ -156,5 +162,9 @@ val LocalFlowArticleListDateStickyHeader =
val LocalFlowArticleListTonalElevation =
compositionLocalOf<FlowArticleListTonalElevationPreference> { FlowArticleListTonalElevationPreference.default }
val LocalInitialPage = compositionLocalOf<InitialPagePreference> { InitialPagePreference.default }
val LocalInitialFilter =
compositionLocalOf<InitialFilterPreference> { InitialFilterPreference.default }
val LocalLanguages =
compositionLocalOf<LanguagesPreference> { LanguagesPreference.default }

View File

@ -4,7 +4,6 @@ import android.os.Build
import android.view.SoundEffectConstants
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
@ -34,8 +33,7 @@ fun FilterBar(
NavigationBar(
modifier = Modifier
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation))
.navigationBarsPadding(),
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation)),
tonalElevation = filterBarTonalElevation,
) {
Spacer(modifier = Modifier.width(filterBarPadding))

View File

@ -0,0 +1,69 @@
package me.ash.reader.ui.component.base
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.theme.palette.onDark
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Scaffold(
containerColor: Color = MaterialTheme.colorScheme.surface,
topBarTonalElevation: Dp = 0.dp,
containerTonalElevation: Dp = 0.dp,
navigationIcon: (@Composable () -> Unit)? = null,
actions: (@Composable RowScope.() -> Unit)? = null,
bottomBar: (@Composable () -> Unit)? = null,
floatingActionButton: (@Composable () -> Unit)? = null,
content: @Composable () -> Unit = {},
) {
androidx.compose.material3.Scaffold(
modifier = Modifier
.background(
MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation,
color = containerColor
)
)
.statusBarsPadding()
.run {
if (bottomBar != null || floatingActionButton != null) {
navigationBarsPadding()
} else {
this
}
},
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
containerTonalElevation,
color = containerColor
) onDark MaterialTheme.colorScheme.surface,
topBar = {
if (navigationIcon != null || actions != null) {
SmallTopAppBar(
title = {},
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation, color = containerColor
),
),
navigationIcon = { navigationIcon?.invoke() },
actions = { actions?.invoke(this) },
)
}
},
content = { content() },
bottomBar = { bottomBar?.invoke() },
floatingActionButton = { floatingActionButton?.invoke() },
)
}

View File

@ -85,7 +85,7 @@ sealed class DataStoreKeys<T> {
object NewVersionSize : DataStoreKeys<String>() {
override val key: Preferences.Key<String>
get() = stringPreferencesKey("newVersionSize")
get() = stringPreferencesKey("newVersionSizeString")
}
object NewVersionDownloadUrl : DataStoreKeys<String>() {

View File

@ -21,13 +21,13 @@ 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.SettingsPage
import me.ash.reader.ui.page.settings.color.ColorAndStyle
import me.ash.reader.ui.page.settings.color.DarkTheme
import me.ash.reader.ui.page.settings.color.feeds.FeedsPageStyle
import me.ash.reader.ui.page.settings.color.flow.FlowPageStyle
import me.ash.reader.ui.page.settings.interaction.Interaction
import me.ash.reader.ui.page.settings.languages.Languages
import me.ash.reader.ui.page.settings.tips.TipsAndSupport
import me.ash.reader.ui.page.settings.color.ColorAndStylePage
import me.ash.reader.ui.page.settings.color.DarkThemePage
import me.ash.reader.ui.page.settings.color.feeds.FeedsPageStylePage
import me.ash.reader.ui.page.settings.color.flow.FlowPageStylePage
import me.ash.reader.ui.page.settings.interaction.InteractionPage
import me.ash.reader.ui.page.settings.languages.LanguagesPage
import me.ash.reader.ui.page.settings.tips.TipsAndSupportPage
import me.ash.reader.ui.page.startup.StartupPage
import me.ash.reader.ui.theme.AppTheme
@ -124,31 +124,31 @@ fun HomeEntry(
// Color & Style
animatedComposable(route = RouteName.COLOR_AND_STYLE) {
ColorAndStyle(navController)
ColorAndStylePage(navController)
}
animatedComposable(route = RouteName.DARK_THEME) {
DarkTheme(navController)
DarkThemePage(navController)
}
animatedComposable(route = RouteName.FEEDS_PAGE_STYLE) {
FeedsPageStyle(navController)
FeedsPageStylePage(navController)
}
animatedComposable(route = RouteName.FLOW_PAGE_STYLE) {
FlowPageStyle(navController)
FlowPageStylePage(navController)
}
// Interaction
animatedComposable(route = RouteName.INTERACTION) {
Interaction(navController)
InteractionPage(navController)
}
// Languages
animatedComposable(route = RouteName.LANGUAGES) {
Languages(navController = navController)
LanguagesPage(navController = navController)
}
// Tips & Support
animatedComposable(route = RouteName.TIPS_AND_SUPPORT) {
TipsAndSupport(navController)
TipsAndSupportPage(navController)
}
}
}

View File

@ -1,11 +1,9 @@
package me.ash.reader.ui.page.home.feeds
import android.annotation.SuppressLint
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
@ -15,7 +13,8 @@ import androidx.compose.material.icons.outlined.KeyboardArrowRight
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.*
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
@ -38,7 +37,6 @@ import me.ash.reader.ui.component.base.Subtitle
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.findActivity
import me.ash.reader.ui.ext.getCurrentVersion
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.home.FilterState
import me.ash.reader.ui.page.home.HomeViewAction
@ -48,11 +46,9 @@ import me.ash.reader.ui.page.home.feeds.drawer.group.GroupOptionDrawer
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeDialog
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewAction
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewModel
import me.ash.reader.ui.theme.palette.onDark
@SuppressLint("FlowOperatorInvokedInComposition")
@OptIn(
ExperimentalMaterial3Api::class, com.google.accompanist.pager.ExperimentalPagerApi::class,
com.google.accompanist.pager.ExperimentalPagerApi::class,
androidx.compose.foundation.ExperimentalFoundationApi::class
)
@Composable
@ -119,52 +115,38 @@ fun FeedsPage(
context.findActivity()?.moveTaskToBack(false)
}
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(topBarTonalElevation.value.dp))
.statusBarsPadding(),
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
groupListTonalElevation.value.dp
) onDark MaterialTheme.colorScheme.surface,
topBar = {
SmallTopAppBar(
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation.value.dp
),
),
title = {},
navigationIcon = {
FeedbackIconButton(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Settings,
contentDescription = stringResource(R.string.settings),
tint = MaterialTheme.colorScheme.onSurface,
showBadge = newVersion.whetherNeedUpdate(currentVersion, skipVersion),
) {
navController.navigate(RouteName.SETTINGS) {
launchSingleTop = true
}
}
},
actions = {
FeedbackIconButton(
modifier = Modifier.rotate(if (isSyncing) angle else 0f),
imageVector = Icons.Rounded.Refresh,
contentDescription = stringResource(R.string.refresh),
tint = MaterialTheme.colorScheme.onSurface,
) {
if (!isSyncing) homeViewModel.dispatch(HomeViewAction.Sync)
}
FeedbackIconButton(
imageVector = Icons.Rounded.Add,
contentDescription = stringResource(R.string.subscribe),
tint = MaterialTheme.colorScheme.onSurface,
) {
subscribeViewModel.dispatch(SubscribeViewAction.Show)
}
me.ash.reader.ui.component.base.Scaffold(
topBarTonalElevation = topBarTonalElevation.value.dp,
containerTonalElevation = groupListTonalElevation.value.dp,
navigationIcon = {
FeedbackIconButton(
modifier = Modifier.size(20.dp),
imageVector = Icons.Outlined.Settings,
contentDescription = stringResource(R.string.settings),
tint = MaterialTheme.colorScheme.onSurface,
showBadge = newVersion.whetherNeedUpdate(currentVersion, skipVersion),
) {
navController.navigate(RouteName.SETTINGS) {
launchSingleTop = true
}
)
}
},
actions = {
FeedbackIconButton(
modifier = Modifier.rotate(if (isSyncing) angle else 0f),
imageVector = Icons.Rounded.Refresh,
contentDescription = stringResource(R.string.refresh),
tint = MaterialTheme.colorScheme.onSurface,
) {
if (!isSyncing) homeViewModel.dispatch(HomeViewAction.Sync)
}
FeedbackIconButton(
imageVector = Icons.Rounded.Add,
contentDescription = stringResource(R.string.subscribe),
tint = MaterialTheme.colorScheme.onSurface,
) {
subscribeViewModel.dispatch(SubscribeViewAction.Show)
}
},
content = {
LazyColumn {

View File

@ -2,7 +2,6 @@ package me.ash.reader.ui.page.home.flow
import androidx.activity.compose.BackHandler
import androidx.compose.animation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
@ -10,7 +9,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.DoneAll
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
@ -33,15 +32,12 @@ import me.ash.reader.ui.component.base.DisplayText
import me.ash.reader.ui.component.base.FeedbackIconButton
import me.ash.reader.ui.component.base.SwipeRefresh
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.home.FilterState
import me.ash.reader.ui.page.home.HomeViewAction
import me.ash.reader.ui.page.home.HomeViewModel
import me.ash.reader.ui.theme.palette.onDark
@OptIn(
ExperimentalMaterial3Api::class,
com.google.accompanist.pager.ExperimentalPagerApi::class,
androidx.compose.ui.ExperimentalComposeUiApi::class,
)
@ -105,75 +101,61 @@ fun FlowPage(
onSearch = false
}
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(topBarTonalElevation.value.dp))
.statusBarsPadding(),
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
articleListTonalElevation.value.dp
) onDark MaterialTheme.colorScheme.surface,
topBar = {
SmallTopAppBar(
title = {},
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
topBarTonalElevation.value.dp
),
),
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
me.ash.reader.ui.component.base.Scaffold(
topBarTonalElevation = topBarTonalElevation.value.dp,
containerTonalElevation = articleListTonalElevation.value.dp,
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
onSearch = false
if (navController.previousBackStackEntry == null) {
navController.navigate(RouteName.FEEDS) {
launchSingleTop = true
}
} else {
navController.popBackStack()
}
}
},
actions = {
AnimatedVisibility(
visible = !filterState.filter.isStarred(),
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically(),
) {
FeedbackIconButton(
imageVector = Icons.Rounded.DoneAll,
contentDescription = stringResource(R.string.mark_all_as_read),
tint = if (markAsRead) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface
},
) {
scope.launch {
viewState.listState.scrollToItem(0)
markAsRead = !markAsRead
onSearch = false
if (navController.previousBackStackEntry == null) {
navController.navigate(RouteName.FEEDS) {
launchSingleTop = true
}
} else {
navController.popBackStack()
}
}
},
actions = {
AnimatedVisibility(
visible = !filterState.filter.isStarred(),
enter = fadeIn() + expandVertically(),
exit = fadeOut() + shrinkVertically(),
) {
FeedbackIconButton(
imageVector = Icons.Rounded.DoneAll,
contentDescription = stringResource(R.string.mark_all_as_read),
tint = if (markAsRead) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface
},
) {
scope.launch {
viewState.listState.scrollToItem(0)
markAsRead = !markAsRead
onSearch = false
}
}
}
FeedbackIconButton(
imageVector = Icons.Rounded.Search,
contentDescription = stringResource(R.string.search),
tint = if (onSearch) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface
},
) {
scope.launch {
viewState.listState.scrollToItem(0)
onSearch = !onSearch
}
}
}
)
}
FeedbackIconButton(
imageVector = Icons.Rounded.Search,
contentDescription = stringResource(R.string.search),
tint = if (onSearch) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onSurface
},
) {
scope.launch {
viewState.listState.scrollToItem(0)
onSearch = !onSearch
}
}
},
content = {
SwipeRefresh(

View File

@ -11,7 +11,10 @@ import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material3.*
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -28,7 +31,6 @@ import me.ash.reader.ui.component.reader.reader
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.drawVerticalScrollbar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReadPage(
navController: NavHostController,
@ -54,9 +56,7 @@ fun ReadPage(
}
}
Scaffold(
containerColor = MaterialTheme.colorScheme.surface,
topBar = {},
me.ash.reader.ui.component.base.Scaffold(
content = {
Box(Modifier.fillMaxSize()) {
Box(
@ -102,8 +102,7 @@ fun ReadPage(
)
}
}
},
bottomBar = {}
}
)
}

View File

@ -1,14 +1,13 @@
package me.ash.reader.ui.page.settings
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.outlined.*
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material3.*
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -33,8 +32,6 @@ 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")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsPage(
navController: NavHostController,
@ -45,27 +42,16 @@ fun SettingsPage(
val skipVersion = LocalSkipVersionNumber.current
val currentVersion by remember { mutableStateOf(context.getCurrentVersion()) }
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -37,7 +37,7 @@ import me.ash.reader.ui.theme.palette.dynamic.extractTonalPalettesFromUserWallpa
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ColorAndStyle(
fun ColorAndStylePage(
navController: NavHostController,
) {
val context = LocalContext.current
@ -50,29 +50,16 @@ fun ColorAndStyle(
val wallpaperTonalPalettes = extractTonalPalettesFromUserWallpaper()
var radioButtonSelected by remember { mutableStateOf(if (themeIndex > 4) 0 else 1) }
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -1,13 +1,12 @@
package me.ash.reader.ui.page.settings.color
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
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.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
@ -29,7 +28,7 @@ import me.ash.reader.ui.theme.palette.onLight
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DarkTheme(
fun DarkThemePage(
navController: NavHostController,
) {
val context = LocalContext.current
@ -37,29 +36,16 @@ fun DarkTheme(
val amoledDarkTheme = LocalAmoledDarkTheme.current
val scope = rememberCoroutineScope()
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -10,7 +10,9 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -22,20 +24,19 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import me.ash.reader.R
import me.ash.reader.data.entity.Feed
import me.ash.reader.data.model.Filter
import me.ash.reader.data.entity.Group
import me.ash.reader.data.model.Filter
import me.ash.reader.data.preference.*
import me.ash.reader.ui.component.FilterBar
import me.ash.reader.ui.component.base.*
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.component.FilterBar
import me.ash.reader.ui.page.home.feeds.GroupItem
import me.ash.reader.ui.page.settings.SettingItem
import me.ash.reader.ui.theme.palette.onDark
import me.ash.reader.ui.theme.palette.onLight
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FeedsPageStyle(
fun FeedsPageStylePage(
navController: NavHostController,
) {
val context = LocalContext.current
@ -57,29 +58,16 @@ fun FeedsPageStyle(
var filterBarPaddingValue: Int? by remember { mutableStateOf(filterBarPadding) }
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -1,6 +1,5 @@
package me.ash.reader.ui.page.settings.color.flow
import android.annotation.SuppressLint
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@ -11,7 +10,10 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.DoneAll
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -27,19 +29,17 @@ import me.ash.reader.data.entity.ArticleWithFeed
import me.ash.reader.data.entity.Feed
import me.ash.reader.data.model.Filter
import me.ash.reader.data.preference.*
import me.ash.reader.ui.component.FilterBar
import me.ash.reader.ui.component.base.*
import me.ash.reader.ui.ext.surfaceColorAtElevation
import me.ash.reader.ui.component.FilterBar
import me.ash.reader.ui.page.home.flow.ArticleItem
import me.ash.reader.ui.page.settings.SettingItem
import me.ash.reader.ui.theme.palette.onDark
import me.ash.reader.ui.theme.palette.onLight
import java.util.*
@SuppressLint("FlowOperatorInvokedInComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FlowPageStyle(
fun FlowPageStylePage(
navController: NavHostController,
) {
val context = LocalContext.current
@ -66,29 +66,16 @@ fun FlowPageStyle(
var filterBarPaddingValue: Int? by remember { mutableStateOf(filterBarPadding) }
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -1,164 +0,0 @@
package me.ash.reader.ui.page.settings.interaction
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.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
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.component.base.*
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
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Interaction(
navController: NavHostController,
) {
val context = LocalContext.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 {
context.dataStore.put(DataStoreKeys.InitialPage, 0)
}
},
RadioDialogOption(
text = stringResource(R.string.flow_page),
selected = initialPage == 1,
) {
scope.launch {
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 {
context.dataStore.put(DataStoreKeys.InitialFilter, 0)
}
},
RadioDialogOption(
text = stringResource(R.string.unread),
selected = initialFilter == 1,
) {
scope.launch {
context.dataStore.put(DataStoreKeys.InitialFilter, 1)
}
},
RadioDialogOption(
text = stringResource(R.string.all),
selected = initialFilter == 2,
) {
scope.launch {
context.dataStore.put(DataStoreKeys.InitialFilter, 2)
}
},
),
) {
initialFilterDialogVisible = false
}
}

View File

@ -0,0 +1,106 @@
package me.ash.reader.ui.page.settings.interaction
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import me.ash.reader.R
import me.ash.reader.data.preference.InitialFilterPreference
import me.ash.reader.data.preference.InitialPagePreference
import me.ash.reader.data.preference.LocalInitialFilter
import me.ash.reader.data.preference.LocalInitialPage
import me.ash.reader.ui.component.base.*
import me.ash.reader.ui.page.settings.SettingItem
import me.ash.reader.ui.theme.palette.onLight
@Composable
fun InteractionPage(
navController: NavHostController,
) {
val context = LocalContext.current
val initialPage = LocalInitialPage.current
val initialFilter = LocalInitialFilter.current
val scope = rememberCoroutineScope()
var initialPageDialogVisible by remember { mutableStateOf(false) }
var initialFilterDialogVisible by remember { mutableStateOf(false) }
me.ash.reader.ui.component.base.Scaffold(
containerColor = MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface,
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
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 = initialPage.getDesc(context),
onClick = {
initialPageDialogVisible = true
},
) {}
SettingItem(
title = stringResource(R.string.initial_filter),
desc = initialFilter.getDesc(context),
onClick = {
initialFilterDialogVisible = true
},
) {}
}
}
}
)
RadioDialog(
visible = initialPageDialogVisible,
title = stringResource(R.string.initial_page),
options = InitialPagePreference.values.map {
RadioDialogOption(
text = it.getDesc(context),
selected = it == initialPage,
) {
it.put(context, scope)
}
},
) {
initialPageDialogVisible = false
}
RadioDialog(
visible = initialFilterDialogVisible,
title = stringResource(R.string.initial_filter),
options = InitialFilterPreference.values.map {
RadioDialogOption(
text = it.getDesc(context),
selected = it == initialFilter,
) {
it.put(context, scope)
}
},
) {
initialFilterDialogVisible = false
}
}

View File

@ -2,17 +2,17 @@ package me.ash.reader.ui.page.settings.languages
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.KeyboardArrowRight
import androidx.compose.material.icons.outlined.Lightbulb
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
@ -31,36 +31,23 @@ import me.ash.reader.ui.theme.palette.onLight
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Languages(
fun LanguagesPage(
navController: NavHostController,
) {
val context = LocalContext.current
val languages = LocalLanguages.current
val scope = rememberCoroutineScope()
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
content = {
LazyColumn {

View File

@ -42,15 +42,13 @@ import me.ash.reader.ui.ext.*
import me.ash.reader.ui.theme.palette.alwaysLight
import me.ash.reader.ui.theme.palette.onLight
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TipsAndSupport(
fun TipsAndSupportPage(
navController: NavHostController,
updateViewModel: UpdateViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val view = LocalView.current
val scope = rememberCoroutineScope()
var currentVersion by remember { mutableStateOf("") }
var clickTime by remember { mutableStateOf(System.currentTimeMillis() - 2000) }
var pressAMP by remember { mutableStateOf(16f) }
@ -63,38 +61,26 @@ fun TipsAndSupport(
currentVersion = context.getCurrentVersion().toString()
}
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface onLight MaterialTheme.colorScheme.inverseOnSurface)
.statusBarsPadding()
.navigationBarsPadding(),
me.ash.reader.ui.component.base.Scaffold(
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 = {
FeedbackIconButton(
modifier = Modifier.size(20.dp),
imageVector = Icons.Rounded.Balance,
contentDescription = stringResource(R.string.open_source_licenses),
tint = MaterialTheme.colorScheme.onSurface
) {
context.showToast(context.getString(R.string.coming_soon))
}
}
)
navigationIcon = {
FeedbackIconButton(
imageVector = Icons.Rounded.ArrowBack,
contentDescription = stringResource(R.string.back),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.popBackStack()
}
},
actions = {
FeedbackIconButton(
modifier = Modifier.size(20.dp),
imageVector = Icons.Rounded.Balance,
contentDescription = stringResource(R.string.open_source_licenses),
tint = MaterialTheme.colorScheme.onSurface
) {
context.showToast(context.getString(R.string.coming_soon))
}
},
content = {
LazyColumn(

View File

@ -1,7 +1,6 @@
package me.ash.reader.ui.page.settings.tips
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.provider.Settings
@ -38,7 +37,6 @@ import me.ash.reader.ui.component.base.Dialog
import me.ash.reader.ui.ext.collectAsStateValue
import me.ash.reader.ui.ext.installLatestApk
@SuppressLint("FlowOperatorInvokedInComposition")
@Composable
fun UpdateDialog(
updateViewModel: UpdateViewModel = hiltViewModel(),

View File

@ -2,8 +2,9 @@ package me.ash.reader.ui.page.startup
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.CheckCircleOutline
@ -28,7 +29,6 @@ import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.svg.SVGString
import me.ash.reader.ui.svg.WELCOME
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StartupPage(
navController: NavHostController,
@ -36,12 +36,7 @@ fun StartupPage(
val context = LocalContext.current
val scope = rememberCoroutineScope()
Scaffold(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface)
.statusBarsPadding()
.navigationBarsPadding(),
topBar = {},
me.ash.reader.ui.component.base.Scaffold(
content = {
LazyColumn {
item {
@ -87,16 +82,7 @@ fun StartupPage(
}
}
},
bottomBar = {
// Row(
// modifier = Modifier
// .fillMaxWidth()
// .padding(24.dp),
// horizontalArrangement = Arrangement.End,
// verticalAlignment = Alignment.CenterVertically,
// ) {
// }
},
bottomBar = null,
floatingActionButton = {
ExtendedFloatingActionButton(
onClick = {