mirror of https://github.com/Ashinch/ReadYou.git
Add FeedOptionDrawer
This commit is contained in:
parent
ada579377b
commit
eda76f4445
|
@ -50,6 +50,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.compose.animation:animation-graphics:$compose_version")
|
||||
implementation("com.google.accompanist:accompanist-flowlayout:0.24.3-alpha")
|
||||
implementation("com.google.accompanist:accompanist-navigation-animation:0.24.3-alpha")
|
||||
implementation "androidx.datastore:datastore-preferences:1.0.0"
|
||||
|
@ -83,7 +84,7 @@ dependencies {
|
|||
implementation "androidx.compose.ui:ui:$compose_version"
|
||||
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.0-alpha01"
|
||||
implementation "androidx.compose.material:material:1.2.0-alpha04"
|
||||
implementation "androidx.compose.material3:material3:1.0.0-alpha06"
|
||||
implementation "androidx.compose.material3:material3:1.0.0-alpha07"
|
||||
implementation "androidx.compose.material:material-icons-extended:$compose_version"
|
||||
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
|
||||
|
|
|
@ -6,13 +6,17 @@ import androidx.compose.animation.core.spring
|
|||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.google.accompanist.insets.ProvideWindowInsets
|
||||
import com.google.accompanist.insets.navigationBarsHeight
|
||||
import com.google.accompanist.insets.statusBarsPadding
|
||||
|
@ -20,11 +24,17 @@ import com.google.accompanist.navigation.animation.AnimatedNavHost
|
|||
import com.google.accompanist.navigation.animation.composable
|
||||
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import me.ash.reader.ui.page.home.FeedOptionDrawer
|
||||
import me.ash.reader.ui.page.home.HomePage
|
||||
import me.ash.reader.ui.page.settings.SettingsPage
|
||||
import me.ash.reader.ui.theme.AppTheme
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
val LocalDrawerState = staticCompositionLocalOf<ModalBottomSheetState> {
|
||||
error("CompositionLocal LocalDrawerState not present")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class, androidx.compose.material.ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun HomeEntry() {
|
||||
val navController = rememberAnimatedNavController()
|
||||
|
@ -32,110 +42,117 @@ fun HomeEntry() {
|
|||
AppTheme {
|
||||
ProvideWindowInsets {
|
||||
rememberSystemUiController().run {
|
||||
setStatusBarColor(MaterialTheme.colorScheme.surface, !isSystemInDarkTheme())
|
||||
setSystemBarsColor(MaterialTheme.colorScheme.surface, !isSystemInDarkTheme())
|
||||
setStatusBarColor(Color.Transparent, !isSystemInDarkTheme())
|
||||
setSystemBarsColor(Color.Transparent, !isSystemInDarkTheme())
|
||||
setNavigationBarColor(MaterialTheme.colorScheme.surface, !isSystemInDarkTheme())
|
||||
}
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.statusBarsPadding()
|
||||
Box {
|
||||
CompositionLocalProvider(
|
||||
LocalDrawerState provides rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
) {
|
||||
AnimatedNavHost(
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.surface),
|
||||
navController = navController,
|
||||
startDestination = RouteName.HOME,
|
||||
) {
|
||||
composable(
|
||||
route = RouteName.HOME,
|
||||
enterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.statusBarsPadding()
|
||||
) {
|
||||
HomePage(navController)
|
||||
}
|
||||
composable(
|
||||
route = RouteName.SETTINGS,
|
||||
enterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { -it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { -it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
) {
|
||||
SettingsPage(navController)
|
||||
AnimatedNavHost(
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.surface),
|
||||
navController = navController,
|
||||
startDestination = RouteName.HOME,
|
||||
) {
|
||||
composable(
|
||||
route = RouteName.HOME,
|
||||
enterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
) {
|
||||
HomePage(navController)
|
||||
}
|
||||
composable(
|
||||
route = RouteName.SETTINGS,
|
||||
enterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
exitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { -it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popEnterTransition = {
|
||||
slideInHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
initialOffsetX = { -it }
|
||||
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
popExitTransition = {
|
||||
slideOutHorizontally(
|
||||
animationSpec = spring(
|
||||
stiffness = Spring.StiffnessLow,
|
||||
dampingRatio = Spring.DampingRatioNoBouncy
|
||||
),
|
||||
targetOffsetX = { -it }
|
||||
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
|
||||
},
|
||||
) {
|
||||
SettingsPage(navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.navigationBarsHeight()
|
||||
.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
FeedOptionDrawer(drawerState = LocalDrawerState.current)
|
||||
}
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.navigationBarsHeight()
|
||||
.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
package me.ash.reader.ui.page.home
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.ChipDefaults
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.RssFeed
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import me.ash.reader.R
|
||||
import me.ash.reader.ui.page.home.feeds.subscribe.ResultViewPage
|
||||
import me.ash.reader.ui.widget.BottomDrawer
|
||||
import me.ash.reader.ui.widget.Subtitle
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun FeedOptionDrawer(
|
||||
modifier: Modifier = Modifier,
|
||||
drawerState: ModalBottomSheetState = androidx.compose.material.rememberModalBottomSheetState(
|
||||
ModalBottomSheetValue.Hidden
|
||||
),
|
||||
) {
|
||||
BottomDrawer(
|
||||
drawerState = drawerState,
|
||||
) {
|
||||
Column {
|
||||
Icon(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally),
|
||||
imageVector = Icons.Rounded.RssFeed,
|
||||
contentDescription = stringResource(R.string.subscribe),
|
||||
)
|
||||
Spacer(modifier = modifier.height(16.dp))
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = "Feed",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(modifier = modifier.height(16.dp))
|
||||
ResultViewPage(
|
||||
link = "https://joeycz.github.io/weekly/rss.xml",
|
||||
groups = emptyList(),
|
||||
selectedAllowNotificationPreset = true,
|
||||
selectedParseFullContentPreset = true,
|
||||
selectedGroupId = "selectedGroupId",
|
||||
newGroupContent = "",
|
||||
onNewGroupValueChange = { },
|
||||
newGroupSelected = false,
|
||||
changeNewGroupSelected = { },
|
||||
allowNotificationPresetOnClick = { },
|
||||
parseFullContentPresetOnClick = { },
|
||||
groupOnClick = { },
|
||||
onKeyboardAction = { },
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Subtitle(text = "More")
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
androidx.compose.material.FilterChip(
|
||||
modifier = modifier,
|
||||
colors = ChipDefaults.filterChipColors(
|
||||
backgroundColor = Color.Transparent,
|
||||
contentColor = MaterialTheme.colorScheme.error,
|
||||
leadingIconColor = MaterialTheme.colorScheme.error,
|
||||
disabledBackgroundColor = MaterialTheme.colorScheme.outline.copy(
|
||||
alpha = 0.7f
|
||||
),
|
||||
disabledContentColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||
disabledLeadingIconColor = MaterialTheme.colorScheme.outline.copy(
|
||||
alpha = 0.7f
|
||||
),
|
||||
selectedBackgroundColor = Color.Transparent,
|
||||
selectedContentColor = MaterialTheme.colorScheme.error,
|
||||
selectedLeadingIconColor = MaterialTheme.colorScheme.error
|
||||
),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colorScheme.error),
|
||||
selected = false,
|
||||
shape = CircleShape,
|
||||
onClick = {
|
||||
// focusManager.clearFocus()
|
||||
// onClick()
|
||||
},
|
||||
content = {
|
||||
Text(
|
||||
modifier = modifier.padding(
|
||||
start = if (false) 0.dp else 8.dp,
|
||||
top = 8.dp,
|
||||
end = 8.dp,
|
||||
bottom = 8.dp
|
||||
),
|
||||
text = "Delete",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = if (true) {
|
||||
MaterialTheme.colorScheme.error
|
||||
} else {
|
||||
MaterialTheme.colorScheme.error
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ import com.google.accompanist.pager.PagerState
|
|||
import me.ash.reader.R
|
||||
import me.ash.reader.data.constant.Filter
|
||||
import me.ash.reader.ui.extension.getName
|
||||
import me.ash.reader.ui.theme.LocalLightThemeColors
|
||||
import me.ash.reader.ui.widget.CanBeDisabledIconButton
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
|
@ -192,6 +193,9 @@ fun Item(
|
|||
onClick: () -> Unit = {},
|
||||
) {
|
||||
val view = LocalView.current
|
||||
val lightThemeColors = LocalLightThemeColors.current
|
||||
val lightPrimaryContainer = lightThemeColors.primaryContainer
|
||||
val lightOnSurface = lightThemeColors.onSurface
|
||||
|
||||
FilterChip(
|
||||
modifier = Modifier
|
||||
|
@ -204,9 +208,9 @@ fun Item(
|
|||
disabledBackgroundColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||
disabledContentColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||
disabledLeadingIconColor = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||
selectedBackgroundColor = MaterialTheme.colorScheme.primaryContainer,
|
||||
selectedContentColor = MaterialTheme.colorScheme.onSurface,
|
||||
selectedLeadingIconColor = MaterialTheme.colorScheme.onSurface
|
||||
selectedBackgroundColor = lightPrimaryContainer,
|
||||
selectedContentColor = lightOnSurface,
|
||||
selectedLeadingIconColor = lightOnSurface
|
||||
),
|
||||
selected = selected,
|
||||
selectedIcon = {
|
||||
|
@ -216,7 +220,7 @@ fun Item(
|
|||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.size(20.dp),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
tint = lightOnSurface,
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
|
@ -235,7 +239,7 @@ fun Item(
|
|||
text = if (selected) name.uppercase() else "",
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
color = if (selected) {
|
||||
MaterialTheme.colorScheme.onSurface
|
||||
lightOnSurface
|
||||
} else {
|
||||
MaterialTheme.colorScheme.outline
|
||||
},
|
||||
|
|
|
@ -2,9 +2,12 @@ package me.ash.reader.ui.page.home
|
|||
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
|
@ -26,7 +29,7 @@ import me.ash.reader.ui.page.home.read.ReadViewAction
|
|||
import me.ash.reader.ui.page.home.read.ReadViewModel
|
||||
import me.ash.reader.ui.widget.ViewPager
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@OptIn(ExperimentalPagerApi::class, androidx.compose.material.ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun HomePage(
|
||||
navController: NavHostController,
|
||||
|
@ -38,6 +41,7 @@ fun HomePage(
|
|||
val filterState = viewModel.filterState.collectAsStateValue()
|
||||
val readState = readViewModel.viewState.collectAsStateValue()
|
||||
val scope = rememberCoroutineScope()
|
||||
val drawerState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
context.findActivity()?.let { activity ->
|
||||
|
@ -92,66 +96,69 @@ fun HomePage(
|
|||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
ViewPager(
|
||||
modifier = Modifier.weight(1f),
|
||||
state = viewState.pagerState,
|
||||
composableList = listOf(
|
||||
{
|
||||
FeedsPage(navController = navController)
|
||||
},
|
||||
{
|
||||
FlowPage(navController = navController)
|
||||
},
|
||||
{
|
||||
ReadPage(
|
||||
navController = navController,
|
||||
btnBackOnClickListener = {
|
||||
viewModel.dispatch(
|
||||
HomeViewAction.ScrollToPage(
|
||||
scope = scope,
|
||||
targetPage = 1,
|
||||
callback = {
|
||||
readViewModel.dispatch(ReadViewAction.ClearArticle)
|
||||
}
|
||||
Box {
|
||||
Column {
|
||||
ViewPager(
|
||||
modifier = Modifier.weight(1f),
|
||||
state = viewState.pagerState,
|
||||
composableList = listOf(
|
||||
{
|
||||
FeedsPage(navController = navController)
|
||||
},
|
||||
{
|
||||
FlowPage(navController = navController)
|
||||
},
|
||||
{
|
||||
ReadPage(
|
||||
navController = navController,
|
||||
btnBackOnClickListener = {
|
||||
viewModel.dispatch(
|
||||
HomeViewAction.ScrollToPage(
|
||||
scope = scope,
|
||||
targetPage = 1,
|
||||
callback = {
|
||||
readViewModel.dispatch(ReadViewAction.ClearArticle)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
HomeBottomNavBar(
|
||||
modifier = Modifier
|
||||
.height(60.dp)
|
||||
.fillMaxWidth(),
|
||||
pagerState = viewState.pagerState,
|
||||
disabled = readState.articleWithFeed == null,
|
||||
isUnread = readState.articleWithFeed?.article?.isUnread ?: false,
|
||||
isStarred = readState.articleWithFeed?.article?.isStarred ?: false,
|
||||
isFullContent = readState.articleWithFeed?.feed?.isFullContent ?: false,
|
||||
unreadOnClick = {
|
||||
readViewModel.dispatch(ReadViewAction.MarkUnread(it))
|
||||
},
|
||||
),
|
||||
)
|
||||
HomeBottomNavBar(
|
||||
modifier = Modifier
|
||||
.height(60.dp)
|
||||
.fillMaxWidth(),
|
||||
pagerState = viewState.pagerState,
|
||||
disabled = readState.articleWithFeed == null,
|
||||
isUnread = readState.articleWithFeed?.article?.isUnread ?: false,
|
||||
isStarred = readState.articleWithFeed?.article?.isStarred ?: false,
|
||||
isFullContent = readState.articleWithFeed?.feed?.isFullContent ?: false,
|
||||
unreadOnClick = {
|
||||
readViewModel.dispatch(ReadViewAction.MarkUnread(it))
|
||||
},
|
||||
starredOnClick = {
|
||||
readViewModel.dispatch(ReadViewAction.MarkStarred(it))
|
||||
},
|
||||
fullContentOnClick = { afterIsFullContent ->
|
||||
readState.articleWithFeed?.let {
|
||||
if (afterIsFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
||||
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||
}
|
||||
},
|
||||
filter = filterState.filter,
|
||||
filterOnClick = {
|
||||
viewModel.dispatch(
|
||||
HomeViewAction.ChangeFilter(
|
||||
filterState.copy(
|
||||
filter = it
|
||||
starredOnClick = {
|
||||
readViewModel.dispatch(ReadViewAction.MarkStarred(it))
|
||||
},
|
||||
fullContentOnClick = { afterIsFullContent ->
|
||||
readState.articleWithFeed?.let {
|
||||
if (afterIsFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
||||
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||
}
|
||||
},
|
||||
filter = filterState.filter,
|
||||
filterOnClick = {
|
||||
viewModel.dispatch(
|
||||
HomeViewAction.ChangeFilter(
|
||||
filterState.copy(
|
||||
filter = it
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
FeedOptionDrawer(drawerState = drawerState)
|
||||
}
|
||||
}
|
|
@ -3,9 +3,11 @@ package me.ash.reader.ui.page.home.feeds
|
|||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ExpandLess
|
||||
import androidx.compose.material.icons.rounded.ExpandMore
|
||||
|
@ -18,9 +20,12 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import me.ash.reader.R
|
||||
import me.ash.reader.data.feed.Feed
|
||||
import me.ash.reader.ui.page.common.LocalDrawerState
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun GroupItem(
|
||||
modifier: Modifier = Modifier,
|
||||
|
@ -31,6 +36,8 @@ fun GroupItem(
|
|||
feedOnClick: (feed: Feed) -> Unit = {},
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(isExpanded) }
|
||||
val scope = rememberCoroutineScope()
|
||||
val drawerState = LocalDrawerState.current
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
@ -38,7 +45,16 @@ fun GroupItem(
|
|||
.padding(horizontal = 16.dp)
|
||||
.clip(RoundedCornerShape(32.dp))
|
||||
.background(MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.14f))
|
||||
.clickable { groupOnClick() }
|
||||
.combinedClickable(
|
||||
onClick = {
|
||||
groupOnClick()
|
||||
},
|
||||
onLongClick = {
|
||||
scope.launch {
|
||||
drawerState.show()
|
||||
}
|
||||
}
|
||||
)
|
||||
.padding(top = 22.dp)
|
||||
) {
|
||||
Row(
|
||||
|
|
|
@ -82,6 +82,7 @@ private fun Link(
|
|||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package me.ash.reader.ui.widget
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ModalBottomSheetDefaults
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun BottomDrawer(
|
||||
modifier: Modifier = Modifier,
|
||||
drawerState: ModalBottomSheetState = androidx.compose.material.rememberModalBottomSheetState(
|
||||
ModalBottomSheetValue.Hidden
|
||||
),
|
||||
content: @Composable () -> Unit = {},
|
||||
) {
|
||||
androidx.compose.material.ModalBottomSheetLayout(
|
||||
sheetState = drawerState,
|
||||
sheetBackgroundColor = Color.Transparent,
|
||||
sheetElevation = if (drawerState.isVisible) ModalBottomSheetDefaults.Elevation else 0.dp,
|
||||
sheetContent = {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(
|
||||
RoundedCornerShape(
|
||||
topStart = 28.0.dp,
|
||||
topEnd = 28.0.dp,
|
||||
bottomEnd = 0.0.dp,
|
||||
bottomStart = 0.0.dp
|
||||
)
|
||||
)
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.padding(horizontal = 28.dp)
|
||||
.navigationBarsPadding()
|
||||
) {
|
||||
Box {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(top = 8.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.size(38.dp, 4.dp)
|
||||
.background(MaterialTheme.colorScheme.outline.copy(alpha = 0.2f))
|
||||
.zIndex(1f)
|
||||
) {}
|
||||
}
|
||||
Column {
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
content()
|
||||
Spacer(modifier = Modifier.height(28.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
content = {}
|
||||
)
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package me.ash.reader.ui.widget
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
@ -39,6 +40,7 @@ fun SelectionChip(
|
|||
enabled: Boolean = true,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = CircleShape,
|
||||
border: BorderStroke? = null,
|
||||
selectedIcon: @Composable () -> Unit = {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.CheckCircle,
|
||||
|
@ -66,6 +68,7 @@ fun SelectionChip(
|
|||
selectedContentColor = MaterialTheme.colorScheme.onSurface,
|
||||
selectedLeadingIconColor = MaterialTheme.colorScheme.onSurface
|
||||
),
|
||||
border = border,
|
||||
interactionSource = interactionSource,
|
||||
enabled = enabled,
|
||||
selected = selected,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
buildscript {
|
||||
ext {
|
||||
compose_version = '1.2.0-alpha02'
|
||||
compose_version = '1.2.0-alpha06'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
Loading…
Reference in New Issue