State hoisting for FlowPage and ReadPage
This commit is contained in:
parent
ac5e68bf86
commit
4c95f89b07
|
@ -26,20 +26,20 @@ import me.ash.reader.ui.widget.ViewPager
|
||||||
fun HomePage(
|
fun HomePage(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
extrasArticleId: Any? = null,
|
extrasArticleId: Any? = null,
|
||||||
viewModel: HomeViewModel = hiltViewModel(),
|
homeViewModel: HomeViewModel = hiltViewModel(),
|
||||||
readViewModel: ReadViewModel = hiltViewModel(),
|
readViewModel: ReadViewModel = hiltViewModel(),
|
||||||
feedOptionViewModel: FeedOptionViewModel = hiltViewModel(),
|
feedOptionViewModel: FeedOptionViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val viewState = viewModel.viewState.collectAsStateValue()
|
val viewState = homeViewModel.viewState.collectAsStateValue()
|
||||||
val filterState = viewModel.filterState.collectAsStateValue()
|
val filterState = homeViewModel.filterState.collectAsStateValue()
|
||||||
val syncState = viewModel.syncState.collectAsStateValue()
|
val syncState = homeViewModel.syncState.collectAsStateValue()
|
||||||
|
|
||||||
OpenArticleByExtras(extrasArticleId)
|
OpenArticleByExtras(extrasArticleId)
|
||||||
|
|
||||||
BackHandler(true) {
|
BackHandler(true) {
|
||||||
val currentPage = viewState.pagerState.currentPage
|
val currentPage = viewState.pagerState.currentPage
|
||||||
viewModel.dispatch(
|
homeViewModel.dispatch(
|
||||||
HomeViewAction.ScrollToPage(
|
HomeViewAction.ScrollToPage(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
targetPage = when (currentPage) {
|
targetPage = when (currentPage) {
|
||||||
|
@ -58,8 +58,8 @@ fun HomePage(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(viewModel.viewState) {
|
LaunchedEffect(homeViewModel.viewState) {
|
||||||
viewModel.viewState.collect {
|
homeViewModel.viewState.collect {
|
||||||
Log.i(
|
Log.i(
|
||||||
"RLog",
|
"RLog",
|
||||||
"HomePage: ${it.pagerState.currentPage}, ${it.pagerState.targetPage}, ${it.pagerState.currentPageOffset}"
|
"HomePage: ${it.pagerState.currentPage}, ${it.pagerState.targetPage}, ${it.pagerState.currentPageOffset}"
|
||||||
|
@ -78,13 +78,13 @@ fun HomePage(
|
||||||
filterState = filterState,
|
filterState = filterState,
|
||||||
syncState = syncState,
|
syncState = syncState,
|
||||||
onSyncClick = {
|
onSyncClick = {
|
||||||
viewModel.dispatch(HomeViewAction.Sync)
|
homeViewModel.dispatch(HomeViewAction.Sync)
|
||||||
},
|
},
|
||||||
onFilterChange = {
|
onFilterChange = {
|
||||||
viewModel.dispatch(HomeViewAction.ChangeFilter(it))
|
homeViewModel.dispatch(HomeViewAction.ChangeFilter(it))
|
||||||
},
|
},
|
||||||
onScrollToPage = {
|
onScrollToPage = {
|
||||||
viewModel.dispatch(
|
homeViewModel.dispatch(
|
||||||
HomeViewAction.ScrollToPage(
|
HomeViewAction.ScrollToPage(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
targetPage = it,
|
targetPage = it,
|
||||||
|
@ -94,10 +94,47 @@ fun HomePage(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
FlowPage(navController = navController)
|
FlowPage(
|
||||||
|
navController = navController,
|
||||||
|
filterState = filterState,
|
||||||
|
onScrollToPage = {
|
||||||
|
homeViewModel.dispatch(
|
||||||
|
HomeViewAction.ScrollToPage(
|
||||||
|
scope = scope,
|
||||||
|
targetPage = it,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onFilterChange = {
|
||||||
|
homeViewModel.dispatch(HomeViewAction.ChangeFilter(it))
|
||||||
|
},
|
||||||
|
onItemClick = {
|
||||||
|
readViewModel.dispatch(ReadViewAction.ScrollToItem(0))
|
||||||
|
readViewModel.dispatch(ReadViewAction.InitData(it))
|
||||||
|
if (it.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
||||||
|
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||||
|
readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||||
|
homeViewModel.dispatch(
|
||||||
|
HomeViewAction.ScrollToPage(
|
||||||
|
scope = scope,
|
||||||
|
targetPage = 2,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ReadPage(navController = navController)
|
ReadPage(
|
||||||
|
navController = navController,
|
||||||
|
onScrollToPage = { targetPage, callback ->
|
||||||
|
homeViewModel.dispatch(
|
||||||
|
HomeViewAction.ScrollToPage(
|
||||||
|
scope = scope,
|
||||||
|
targetPage = targetPage,
|
||||||
|
callback = callback
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,6 @@ import androidx.compose.material.icons.rounded.Search
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
@ -25,14 +24,11 @@ import androidx.paging.LoadState
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.data.article.ArticleWithFeed
|
||||||
import me.ash.reader.ui.extension.collectAsStateValue
|
import me.ash.reader.ui.extension.collectAsStateValue
|
||||||
import me.ash.reader.ui.extension.getName
|
import me.ash.reader.ui.extension.getName
|
||||||
import me.ash.reader.ui.page.home.FilterBar
|
import me.ash.reader.ui.page.home.FilterBar
|
||||||
import me.ash.reader.ui.page.home.HomeViewAction
|
import me.ash.reader.ui.page.home.FilterState
|
||||||
import me.ash.reader.ui.page.home.HomeViewModel
|
|
||||||
import me.ash.reader.ui.page.home.read.ReadViewAction
|
|
||||||
import me.ash.reader.ui.page.home.read.ReadViewModel
|
|
||||||
import me.ash.reader.ui.widget.LottieAnimation
|
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
ExperimentalMaterial3Api::class,
|
ExperimentalMaterial3Api::class,
|
||||||
|
@ -43,22 +39,21 @@ fun FlowPage(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
flowViewModel: FlowViewModel = hiltViewModel(),
|
flowViewModel: FlowViewModel = hiltViewModel(),
|
||||||
homeViewModel: HomeViewModel = hiltViewModel(),
|
filterState: FilterState,
|
||||||
readViewModel: ReadViewModel = hiltViewModel(),
|
onFilterChange: (filterState: FilterState) -> Unit = {},
|
||||||
|
onScrollToPage: (targetPage: Int) -> Unit = {},
|
||||||
|
onItemClick: (item: ArticleWithFeed) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val viewState = flowViewModel.viewState.collectAsStateValue()
|
val viewState = flowViewModel.viewState.collectAsStateValue()
|
||||||
val filterState = homeViewModel.filterState.collectAsStateValue()
|
|
||||||
val pagingItems = viewState.pagingData.collectAsLazyPagingItems()
|
val pagingItems = viewState.pagingData.collectAsLazyPagingItems()
|
||||||
var markAsRead by remember { mutableStateOf(false) }
|
var markAsRead by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(homeViewModel.filterState) {
|
LaunchedEffect(filterState) {
|
||||||
homeViewModel.filterState.collect { state ->
|
flowViewModel.dispatch(
|
||||||
flowViewModel.dispatch(
|
FlowViewAction.FetchData(filterState)
|
||||||
FlowViewAction.FetchData(state)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LaunchedEffect(viewState.listState.isScrollInProgress) {
|
// LaunchedEffect(viewState.listState.isScrollInProgress) {
|
||||||
|
@ -81,14 +76,7 @@ fun FlowPage(
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = { onScrollToPage(0) }) {
|
||||||
homeViewModel.dispatch(
|
|
||||||
HomeViewAction.ScrollToPage(
|
|
||||||
scope = scope,
|
|
||||||
targetPage = 0,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Rounded.ArrowBack,
|
imageVector = Icons.Rounded.ArrowBack,
|
||||||
contentDescription = stringResource(R.string.back),
|
contentDescription = stringResource(R.string.back),
|
||||||
|
@ -131,12 +119,14 @@ fun FlowPage(
|
||||||
},
|
},
|
||||||
content = {
|
content = {
|
||||||
Crossfade(targetState = pagingItems) { pagingItems ->
|
Crossfade(targetState = pagingItems) { pagingItems ->
|
||||||
if (pagingItems.loadState.source.refresh is LoadState.NotLoading && pagingItems.itemCount == 0) {
|
// if (pagingItems.loadState.source.refresh is LoadState.NotLoading && pagingItems.itemCount == 0) {
|
||||||
LottieAnimation(
|
// LottieAnimation(
|
||||||
modifier = Modifier.alpha(0.7f).padding(80.dp),
|
// modifier = Modifier
|
||||||
url = "https://assets7.lottiefiles.com/packages/lf20_l4ny0jjm.json",
|
// .alpha(0.7f)
|
||||||
)
|
// .padding(80.dp),
|
||||||
}
|
// url = "https://assets7.lottiefiles.com/packages/lf20_l4ny0jjm.json",
|
||||||
|
// )
|
||||||
|
// }
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = viewState.listState,
|
state = viewState.listState,
|
||||||
) {
|
) {
|
||||||
|
@ -178,17 +168,7 @@ fun FlowPage(
|
||||||
pagingItems = pagingItems,
|
pagingItems = pagingItems,
|
||||||
) {
|
) {
|
||||||
markAsRead = false
|
markAsRead = false
|
||||||
readViewModel.dispatch(ReadViewAction.ScrollToItem(0))
|
onItemClick(it)
|
||||||
readViewModel.dispatch(ReadViewAction.InitData(it))
|
|
||||||
if (it.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
|
||||||
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
|
||||||
readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
|
||||||
homeViewModel.dispatch(
|
|
||||||
HomeViewAction.ScrollToPage(
|
|
||||||
scope = scope,
|
|
||||||
targetPage = 2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
|
@ -207,11 +187,9 @@ fun FlowPage(
|
||||||
filter = filterState.filter,
|
filter = filterState.filter,
|
||||||
filterOnClick = {
|
filterOnClick = {
|
||||||
markAsRead = false
|
markAsRead = false
|
||||||
homeViewModel.dispatch(
|
onFilterChange(
|
||||||
HomeViewAction.ChangeFilter(
|
filterState.copy(
|
||||||
filterState.copy(
|
filter = it
|
||||||
filter = it
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package me.ash.reader.ui.page.home.read
|
package me.ash.reader.ui.page.home.read
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
@ -8,49 +7,49 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import me.ash.reader.data.article.Article
|
import me.ash.reader.data.article.ArticleWithFeed
|
||||||
import me.ash.reader.data.feed.Feed
|
|
||||||
import me.ash.reader.formatToString
|
import me.ash.reader.formatToString
|
||||||
import me.ash.reader.ui.extension.roundClick
|
import me.ash.reader.ui.extension.roundClick
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Header(
|
fun Header(
|
||||||
context: Context,
|
articleWithFeed: ArticleWithFeed,
|
||||||
article: Article,
|
|
||||||
feed: Feed
|
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.roundClick {
|
.roundClick {
|
||||||
context.startActivity(
|
context.startActivity(
|
||||||
Intent(Intent.ACTION_VIEW, Uri.parse(article.link))
|
Intent(Intent.ACTION_VIEW, Uri.parse(articleWithFeed.article.link))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.padding(12.dp)
|
.padding(12.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = article.date.formatToString(context, atHourMinute = true),
|
text = articleWithFeed.article.date.formatToString(context, atHourMinute = true),
|
||||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
text = article.title,
|
text = articleWithFeed.article.title,
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
style = MaterialTheme.typography.headlineLarge,
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
article.author?.let {
|
articleWithFeed.article.author?.let {
|
||||||
Text(
|
Text(
|
||||||
text = article.author,
|
text = articleWithFeed.article.author,
|
||||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = feed.name,
|
text = articleWithFeed.feed.name,
|
||||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package me.ash.reader.ui.page.home.read
|
package me.ash.reader.ui.page.home.read
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Headphones
|
import androidx.compose.material.icons.outlined.Headphones
|
||||||
import androidx.compose.material.icons.outlined.MoreVert
|
import androidx.compose.material.icons.outlined.MoreVert
|
||||||
|
@ -14,20 +15,14 @@ import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.data.article.ArticleWithFeed
|
import me.ash.reader.data.article.ArticleWithFeed
|
||||||
import me.ash.reader.ui.extension.collectAsStateValue
|
import me.ash.reader.ui.extension.collectAsStateValue
|
||||||
import me.ash.reader.ui.page.home.HomeViewAction
|
|
||||||
import me.ash.reader.ui.page.home.HomeViewModel
|
|
||||||
import me.ash.reader.ui.widget.LottieAnimation
|
|
||||||
import me.ash.reader.ui.widget.WebView
|
import me.ash.reader.ui.widget.WebView
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@ -36,10 +31,8 @@ fun ReadPage(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
readViewModel: ReadViewModel = hiltViewModel(),
|
readViewModel: ReadViewModel = hiltViewModel(),
|
||||||
homeViewModel: HomeViewModel = hiltViewModel(),
|
onScrollToPage: (targetPage: Int, callback: () -> Unit) -> Unit = { _, _ -> },
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
val viewState = readViewModel.viewState.collectAsStateValue()
|
val viewState = readViewModel.viewState.collectAsStateValue()
|
||||||
var isScrollDown by remember { mutableStateOf(false) }
|
var isScrollDown by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
@ -92,14 +85,18 @@ fun ReadPage(
|
||||||
contentAlignment = Alignment.TopCenter
|
contentAlignment = Alignment.TopCenter
|
||||||
) {
|
) {
|
||||||
TopBar(
|
TopBar(
|
||||||
viewState.articleWithFeed == null || !isScrollDown,
|
isShow = viewState.articleWithFeed == null || !isScrollDown,
|
||||||
homeViewModel,
|
onScrollToPage = onScrollToPage,
|
||||||
scope,
|
onClearArticle = {
|
||||||
readViewModel,
|
readViewModel.dispatch(ReadViewAction.ClearArticle)
|
||||||
viewState
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Content(viewState, viewState.articleWithFeed, context)
|
Content(
|
||||||
|
content = viewState.content ?: "",
|
||||||
|
articleWithFeed = viewState.articleWithFeed,
|
||||||
|
LazyListState = viewState.listState,
|
||||||
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
@ -107,9 +104,18 @@ fun ReadPage(
|
||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
) {
|
) {
|
||||||
BottomBar(
|
BottomBar(
|
||||||
viewState.articleWithFeed != null && !isScrollDown,
|
isShow = viewState.articleWithFeed != null && !isScrollDown,
|
||||||
viewState.articleWithFeed,
|
articleWithFeed = viewState.articleWithFeed,
|
||||||
readViewModel
|
unreadOnClick = {
|
||||||
|
readViewModel.dispatch(ReadViewAction.MarkUnread(it))
|
||||||
|
},
|
||||||
|
starredOnClick = {
|
||||||
|
readViewModel.dispatch(ReadViewAction.MarkStarred(it))
|
||||||
|
},
|
||||||
|
fullContentOnClick = { afterIsFullContent ->
|
||||||
|
if (afterIsFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
||||||
|
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,10 +127,9 @@ fun ReadPage(
|
||||||
@Composable
|
@Composable
|
||||||
private fun TopBar(
|
private fun TopBar(
|
||||||
isShow: Boolean,
|
isShow: Boolean,
|
||||||
homeViewModel: HomeViewModel,
|
isShowActions: Boolean = false,
|
||||||
scope: CoroutineScope,
|
onScrollToPage: (targetPage: Int, callback: () -> Unit) -> Unit = { _, _ -> },
|
||||||
readViewModel: ReadViewModel,
|
onClearArticle: () -> Unit = {},
|
||||||
viewState: ReadViewState
|
|
||||||
) {
|
) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = isShow,
|
visible = isShow,
|
||||||
|
@ -138,15 +143,9 @@ private fun TopBar(
|
||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
homeViewModel.dispatch(
|
onScrollToPage(1) {
|
||||||
HomeViewAction.ScrollToPage(
|
onClearArticle()
|
||||||
scope = scope,
|
}
|
||||||
targetPage = 1,
|
|
||||||
callback = {
|
|
||||||
readViewModel.dispatch(ReadViewAction.ClearArticle)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Rounded.Close,
|
imageVector = Icons.Rounded.Close,
|
||||||
|
@ -156,7 +155,7 @@ private fun TopBar(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
viewState.articleWithFeed?.let {
|
if (isShowActions) {
|
||||||
IconButton(onClick = {}) {
|
IconButton(onClick = {}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(22.dp),
|
modifier = Modifier.size(22.dp),
|
||||||
|
@ -178,60 +177,25 @@ private fun TopBar(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun BottomBar(
|
|
||||||
isShow: Boolean,
|
|
||||||
articleWithFeed: ArticleWithFeed?,
|
|
||||||
readViewModel: ReadViewModel
|
|
||||||
) {
|
|
||||||
articleWithFeed?.let {
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = isShow,
|
|
||||||
enter = fadeIn() + expandVertically(),
|
|
||||||
exit = fadeOut() + shrinkVertically(),
|
|
||||||
) {
|
|
||||||
ReadBar(
|
|
||||||
disabled = false,
|
|
||||||
isUnread = articleWithFeed.article.isUnread,
|
|
||||||
isStarred = articleWithFeed.article.isStarred,
|
|
||||||
isFullContent = articleWithFeed.feed.isFullContent,
|
|
||||||
unreadOnClick = {
|
|
||||||
readViewModel.dispatch(ReadViewAction.MarkUnread(it))
|
|
||||||
},
|
|
||||||
starredOnClick = {
|
|
||||||
readViewModel.dispatch(ReadViewAction.MarkStarred(it))
|
|
||||||
},
|
|
||||||
fullContentOnClick = { afterIsFullContent ->
|
|
||||||
if (afterIsFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
|
||||||
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Content(
|
private fun Content(
|
||||||
viewState: ReadViewState,
|
content: String,
|
||||||
articleWithFeed: ArticleWithFeed?,
|
articleWithFeed: ArticleWithFeed?,
|
||||||
context: Context
|
LazyListState: LazyListState = rememberLazyListState(),
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
if (articleWithFeed == null) {
|
if (articleWithFeed == null) {
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
LottieAnimation(
|
// LottieAnimation(
|
||||||
modifier = Modifier
|
// modifier = Modifier
|
||||||
.alpha(0.7f)
|
// .alpha(0.7f)
|
||||||
.padding(80.dp),
|
// .padding(80.dp),
|
||||||
url = "https://assets8.lottiefiles.com/packages/lf20_jm7mv1ib.json",
|
// url = "https://assets8.lottiefiles.com/packages/lf20_jm7mv1ib.json",
|
||||||
)
|
// )
|
||||||
} else {
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = viewState.listState,
|
state = LazyListState,
|
||||||
) {
|
) {
|
||||||
val article = articleWithFeed.article
|
|
||||||
val feed = articleWithFeed.feed
|
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
}
|
}
|
||||||
|
@ -241,14 +205,14 @@ private fun Content(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 12.dp)
|
.padding(horizontal = 12.dp)
|
||||||
) {
|
) {
|
||||||
Header(context, article, feed)
|
Header(articleWithFeed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
Spacer(modifier = Modifier.height(22.dp))
|
Spacer(modifier = Modifier.height(22.dp))
|
||||||
Crossfade(targetState = viewState.content) { content ->
|
Crossfade(targetState = content) { content ->
|
||||||
WebView(
|
WebView(
|
||||||
content = content ?: "",
|
content = content
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(50.dp))
|
Spacer(modifier = Modifier.height(50.dp))
|
||||||
}
|
}
|
||||||
|
@ -262,3 +226,29 @@ private fun Content(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BottomBar(
|
||||||
|
isShow: Boolean,
|
||||||
|
articleWithFeed: ArticleWithFeed?,
|
||||||
|
unreadOnClick: (afterIsUnread: Boolean) -> Unit = {},
|
||||||
|
starredOnClick: (afterIsStarred: Boolean) -> Unit = {},
|
||||||
|
fullContentOnClick: (afterIsFullContent: Boolean) -> Unit = {},
|
||||||
|
) {
|
||||||
|
articleWithFeed?.let {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = isShow,
|
||||||
|
enter = fadeIn() + expandVertically(),
|
||||||
|
exit = fadeOut() + shrinkVertically(),
|
||||||
|
) {
|
||||||
|
ReadBar(
|
||||||
|
disabled = false,
|
||||||
|
isUnread = articleWithFeed.article.isUnread,
|
||||||
|
isStarred = articleWithFeed.article.isStarred,
|
||||||
|
isFullContent = articleWithFeed.feed.isFullContent,
|
||||||
|
unreadOnClick = unreadOnClick,
|
||||||
|
starredOnClick = starredOnClick,
|
||||||
|
fullContentOnClick = fullContentOnClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user