diff --git a/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt b/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt index 75f42f8..bfa666d 100644 --- a/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt +++ b/app/src/main/java/me/ash/reader/data/repository/AbstractRssRepository.kt @@ -10,12 +10,12 @@ import androidx.work.WorkManager import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.mapLatest import me.ash.reader.data.dao.AccountDao import me.ash.reader.data.dao.ArticleDao import me.ash.reader.data.dao.FeedDao import me.ash.reader.data.dao.GroupDao import me.ash.reader.data.entity.* -import me.ash.reader.data.model.ImportantCount import me.ash.reader.ui.ext.currentAccountId import java.util.* @@ -99,7 +99,7 @@ abstract class AbstractRssRepository constructor( fun pullImportant( isStarred: Boolean = false, isUnread: Boolean = false, - ): Flow> { + ): Flow> { val accountId = context.currentAccountId Log.i( "RLog", @@ -111,6 +111,12 @@ abstract class AbstractRssRepository constructor( isUnread -> articleDao .queryImportantCountWhenIsUnread(accountId, isUnread) else -> articleDao.queryImportantCountWhenIsAll(accountId) + }.mapLatest { + mapOf( + *(it.map { + it.feedId to it.important + }.toTypedArray()) + ) }.flowOn(dispatcherIO) } diff --git a/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt b/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt index 7027374..f0d29d9 100644 --- a/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt +++ b/app/src/main/java/me/ash/reader/ui/component/FilterBar.kt @@ -4,6 +4,7 @@ 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 @@ -20,7 +21,6 @@ import me.ash.reader.ui.theme.palette.onDark @Composable fun FilterBar( - modifier: Modifier = Modifier, filter: Filter, filterBarStyle: Int, filterBarFilled: Boolean, @@ -33,7 +33,8 @@ fun FilterBar( NavigationBar( modifier = Modifier - .background(MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation)), + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(filterBarTonalElevation)) + .navigationBarsPadding(), tonalElevation = filterBarTonalElevation, ) { Spacer(modifier = Modifier.width(filterBarPadding)) diff --git a/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt b/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt index 773aed4..f707357 100644 --- a/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt +++ b/app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt @@ -31,14 +31,14 @@ fun RYScaffold( color = containerColor ) ) - .statusBarsPadding() - .run { - if (bottomBar != null || floatingActionButton != null) { - navigationBarsPadding() - } else { - this - } - }, + .statusBarsPadding(), +// .run { +// if (bottomBar != null || floatingActionButton != null) { +// navigationBarsPadding() +// } else { +// this +// } +// }, containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( containerTonalElevation, color = containerColor diff --git a/app/src/main/java/me/ash/reader/ui/ext/ContextExt.kt b/app/src/main/java/me/ash/reader/ui/ext/ContextExt.kt index 3c63125..8b084ba 100644 --- a/app/src/main/java/me/ash/reader/ui/ext/ContextExt.kt +++ b/app/src/main/java/me/ash/reader/ui/ext/ContextExt.kt @@ -67,7 +67,7 @@ fun Context.share(content: String) { }, getString(R.string.share))) } -fun Context.openURL(url: String? = null) { +fun Context.openURL(url: String?) { url?.takeIf { it.trim().isNotEmpty() } ?.let { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(it))) } } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt index 63ed5e2..b854541 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedItem.kt @@ -1,95 +1,99 @@ package me.ash.reader.ui.page.home.feeds +import RYExtensibleVisibility import android.view.HapticFeedbackConstants +import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Badge import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import me.ash.reader.data.entity.Feed import me.ash.reader.ui.component.FeedIcon import me.ash.reader.ui.page.home.feeds.drawer.feed.FeedOptionViewModel -import kotlin.math.ln +import me.ash.reader.ui.theme.ShapeBottom32 @OptIn( androidx.compose.foundation.ExperimentalFoundationApi::class, - androidx.compose.material.ExperimentalMaterialApi::class, ) @Composable fun FeedItem( feed: Feed, + alpha: Float = 1f, + badgeAlpha: Float = 1f, + isEnded: Boolean = false, + isExpanded: () -> Boolean, feedOptionViewModel: FeedOptionViewModel = hiltViewModel(), - tonalElevation: Dp, onClick: () -> Unit = {}, ) { val view = LocalView.current val scope = rememberCoroutineScope() - val tonalElevationAlpha by remember { - derivedStateOf { - (ln(tonalElevation.value + 1.4f) + 2f) / 100f - } - } - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 14.dp) - .clip(RoundedCornerShape(32.dp)) - .combinedClickable( - onClick = { - onClick() - }, - onLongClick = { - view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) - feedOptionViewModel.showDrawer(scope, feed.id) - } - ) - .padding(vertical = 14.dp), - ) { + RYExtensibleVisibility(visible = isExpanded()) { Row( modifier = Modifier .fillMaxWidth() - .padding(start = 14.dp, end = 6.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Row(modifier = Modifier.weight(1f)) { - FeedIcon(feed.name) - Text( - modifier = Modifier.padding(start = 12.dp, end = 6.dp), - text = feed.name, - style = MaterialTheme.typography.labelLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 1, - overflow = TextOverflow.Ellipsis, + .padding(horizontal = 16.dp) + .background( + color = MaterialTheme.colorScheme.secondary.copy(alpha = alpha), + shape = if (isEnded) ShapeBottom32 else RectangleShape, ) - } - if ((feed.important ?: 0) != 0) { - Badge( - containerColor = MaterialTheme.colorScheme.surfaceTint.copy( - alpha = tonalElevationAlpha - ), - contentColor = MaterialTheme.colorScheme.outline, - content = { - Text( - text = feed.important.toString(), - style = MaterialTheme.typography.labelSmall - ) + .combinedClickable( + onClick = { + onClick() }, + onLongClick = { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) + feedOptionViewModel.showDrawer(scope, feed.id) + } ) + .padding(horizontal = 14.dp) + .padding(top = 14.dp, bottom = if (isEnded) 22.dp else 14.dp), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 14.dp, end = 6.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Row(modifier = Modifier.weight(1f)) { + FeedIcon(feed.name) + Text( + modifier = Modifier.padding(start = 12.dp, end = 6.dp), + text = feed.name, + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + if ((feed.important ?: 0) != 0) { + Badge( + containerColor = MaterialTheme.colorScheme.surfaceTint.copy( + alpha = badgeAlpha + ), + contentColor = MaterialTheme.colorScheme.outline, + content = { + Text( + text = feed.important.toString(), + style = MaterialTheme.typography.labelSmall + ) + }, + ) + } } } } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt index 4ed4ee6..b144f93 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsPage.kt @@ -31,6 +31,7 @@ import me.ash.reader.data.preference.* import me.ash.reader.data.repository.SyncWorker.Companion.getIsSyncing import me.ash.reader.ui.component.FilterBar import me.ash.reader.ui.component.base.* +import me.ash.reader.ui.ext.alphaLN import me.ash.reader.ui.ext.collectAsStateValue import me.ash.reader.ui.ext.findActivity import me.ash.reader.ui.ext.getCurrentVersion @@ -41,9 +42,9 @@ import me.ash.reader.ui.page.home.feeds.drawer.feed.FeedOptionDrawer 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.SubscribeViewModel +import kotlin.math.ln @OptIn( - com.google.accompanist.pager.ExperimentalPagerApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class ) @Composable @@ -96,6 +97,24 @@ fun FeedsPage( } } + val feedBadgeAlpha by remember { derivedStateOf { (ln(groupListTonalElevation.value + 1.4f) + 2f) / 100f } } + val groupAlpha by remember { derivedStateOf { groupListTonalElevation.value.dp.alphaLN(weight = 1.2f) } } + val groupIndicatorAlpha by remember { + derivedStateOf { + groupListTonalElevation.value.dp.alphaLN( + weight = 1.4f + ) + } + } + + val groupsVisible = remember(feedsUiState.groupWithFeedList) { + mutableStateMapOf( + *(feedsUiState.groupWithFeedList.filterIsInstance().map { + it.group.id to groupListExpand.value + }.toTypedArray()) + ) + } + LaunchedEffect(Unit) { feedsViewModel.fetchAccount() } @@ -161,7 +180,7 @@ fun FeedsPage( item { Banner( title = filterUiState.filter.getName(), - desc = feedsUiState.importantCount.ifEmpty { stringResource(R.string.loading) }, + desc = feedsUiState.importantSum.ifEmpty { stringResource(R.string.loading) }, icon = filterUiState.filter.iconOutline, action = { Icon( @@ -189,14 +208,21 @@ fun FeedsPage( Spacer(modifier = Modifier.height(8.dp)) } itemsIndexed(feedsUiState.groupWithFeedList) { index, groupWithFeed -> -// Crossfade(targetState = groupWithFeed) { groupWithFeed -> - Column { - GroupItem( - isExpanded = groupListExpand.value, - tonalElevation = groupListTonalElevation.value.dp, - group = groupWithFeed.group, - feeds = groupWithFeed.feeds, - groupOnClick = { + when (groupWithFeed) { + is GroupFeedsView.Group -> { + if (index != 0) { + Spacer(modifier = Modifier.height(16.dp)) + } + GroupItem( + isExpanded = { groupsVisible[groupWithFeed.group.id] ?: false }, + group = groupWithFeed.group, + alpha = groupAlpha, + indicatorAlpha = groupIndicatorAlpha, + onExpanded = { + groupsVisible[groupWithFeed.group.id] = + !(groupsVisible[groupWithFeed.group.id] ?: false) + } + ) { filterChange( navController = navController, homeViewModel = homeViewModel, @@ -205,23 +231,27 @@ fun FeedsPage( feed = null, ) ) - }, - feedOnClick = { feed -> + } + } + is GroupFeedsView.Feed -> { + FeedItem( + feed = groupWithFeed.feed, + alpha = groupAlpha, + badgeAlpha = feedBadgeAlpha, + isEnded = index != feedsUiState.groupWithFeedList.lastIndex && feedsUiState.groupWithFeedList[index + 1] is GroupFeedsView.Group, + isExpanded = { groupsVisible[groupWithFeed.feed.groupId] ?: false }, + ) { filterChange( navController = navController, homeViewModel = homeViewModel, filterState = filterUiState.copy( group = null, - feed = feed, + feed = groupWithFeed.feed, ) ) } - ) - if (index != feedsUiState.groupWithFeedList.lastIndex) { - Spacer(modifier = Modifier.height(8.dp)) } } -// } } item { Spacer(modifier = Modifier.height(128.dp)) diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsViewModel.kt index 6fd8243..08d4e5a 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsViewModel.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/FeedsViewModel.kt @@ -2,6 +2,7 @@ package me.ash.reader.ui.page.home.feeds import android.util.Log import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.ui.util.fastForEach import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -10,7 +11,6 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import me.ash.reader.R import me.ash.reader.data.entity.Account -import me.ash.reader.data.entity.GroupWithFeed import me.ash.reader.data.module.DispatcherDefault import me.ash.reader.data.module.DispatcherIO import me.ash.reader.data.repository.AccountRepository @@ -67,42 +67,20 @@ class FeedsViewModel @Inject constructor( combine( rssRepository.get().pullFeeds(), rssRepository.get().pullImportant(isStarred, isUnread), - ) { groupWithFeedList, importantList -> - val groupImportantMap = mutableMapOf() - val feedImportantMap = mutableMapOf() - importantList.groupBy { it.groupId }.forEach { (i, list) -> - var groupImportantSum = 0 - list.forEach { - feedImportantMap[it.feedId] = it.important - groupImportantSum += it.important - } - groupImportantMap[i] = groupImportantSum - } - val groupsIt = groupWithFeedList.iterator() - while (groupsIt.hasNext()) { - val groupWithFeed = groupsIt.next() - val groupImportant = groupImportantMap[groupWithFeed.group.id] - if (groupImportant == null && (isStarred || isUnread)) { - groupsIt.remove() - } else { - groupWithFeed.group.important = groupImportant - val feedsIt = groupWithFeed.feeds.iterator() - while (feedsIt.hasNext()) { - val feed = feedsIt.next() - val feedImportant = feedImportantMap[feed.id] - if (feedImportant == null && (isStarred || isUnread)) { - feedsIt.remove() - } else { - feed.important = feedImportant - } - } + ) { groupWithFeedList, importantMap -> + groupWithFeedList.fastForEach { + var groupImportant = 0 + it.feeds.fastForEach { + it.important = importantMap[it.id] + groupImportant += it.important ?: 0 } + it.group.important = groupImportant } groupWithFeedList - }.onEach { groupWithFeedList -> + }.mapLatest { groupWithFeedList -> _feedsUiState.update { it.copy( - importantCount = groupWithFeedList.sumOf { it.group.important ?: 0 }.run { + importantSum = groupWithFeedList.sumOf { it.group.important ?: 0 }.run { when { isStarred -> stringsRepository.getQuantityString( R.plurals.starred_desc, @@ -121,8 +99,15 @@ class FeedsViewModel @Inject constructor( ) } }, - groupWithFeedList = groupWithFeedList, - feedsVisible = List(groupWithFeedList.size, init = { true }) + groupWithFeedList = groupWithFeedList.map { + mutableListOf(GroupFeedsView.Group(it.group)).apply { + addAll( + it.feeds.map { + GroupFeedsView.Feed(it) + } + ) + } + }.flatten(), ) } }.catch { @@ -133,9 +118,13 @@ class FeedsViewModel @Inject constructor( data class FeedsUiState( val account: Account? = null, - val importantCount: String = "", - val groupWithFeedList: List = emptyList(), - val feedsVisible: List = emptyList(), + val importantSum: String = "", + val groupWithFeedList: List = emptyList(), val listState: LazyListState = LazyListState(), val groupsVisible: Boolean = true, ) + +sealed class GroupFeedsView { + class Group(val group: me.ash.reader.data.entity.Group) : GroupFeedsView() + class Feed(val feed: me.ash.reader.data.entity.Feed) : GroupFeedsView() +} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt index 61f79d5..e41ef52 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/GroupItem.kt @@ -1,58 +1,56 @@ package me.ash.reader.ui.page.home.feeds -import RYExtensibleVisibility import android.view.HapticFeedbackConstants +import androidx.compose.animation.animateContentSize 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.icons.Icons import androidx.compose.material.icons.rounded.ExpandLess import androidx.compose.material.icons.rounded.ExpandMore import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import me.ash.reader.R -import me.ash.reader.data.entity.Feed import me.ash.reader.data.entity.Group -import me.ash.reader.ui.ext.alphaLN import me.ash.reader.ui.page.home.feeds.drawer.group.GroupOptionViewModel +import me.ash.reader.ui.theme.Shape32 +import me.ash.reader.ui.theme.ShapeTop32 @OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) @Composable fun GroupItem( - modifier: Modifier = Modifier, - tonalElevation: Dp, group: Group, - feeds: List, - isExpanded: Boolean = true, + alpha: Float = 1f, + indicatorAlpha: Float = 1f, + isExpanded: () -> Boolean, groupOptionViewModel: GroupOptionViewModel = hiltViewModel(), + onExpanded: () -> Unit = {}, groupOnClick: () -> Unit = {}, - feedOnClick: (feed: Feed) -> Unit = {}, ) { val view = LocalView.current val scope = rememberCoroutineScope() - var expanded by remember { mutableStateOf(isExpanded) } Column( modifier = Modifier + .animateContentSize() .fillMaxWidth() .padding(horizontal = 16.dp) - .clip(RoundedCornerShape(32.dp)) + .clip(if (isExpanded()) ShapeTop32 else Shape32) .background( - MaterialTheme.colorScheme.secondary.copy(alpha = tonalElevation.alphaLN(weight = 1.2f)) + MaterialTheme.colorScheme.secondary.copy(alpha = alpha) ) .combinedClickable( onClick = { @@ -66,7 +64,7 @@ fun GroupItem( .padding(top = 22.dp) ) { Row( - modifier = modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { @@ -86,38 +84,21 @@ fun GroupItem( .size(24.dp) .clip(CircleShape) .background( - MaterialTheme.colorScheme.surfaceTint.copy( - alpha = tonalElevation.alphaLN(weight = 1.4f) - ) + MaterialTheme.colorScheme.surfaceTint.copy(alpha = indicatorAlpha) ) .clickable { - expanded = !expanded + onExpanded() }, horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { Icon( - imageVector = if (expanded) Icons.Rounded.ExpandLess else Icons.Rounded.ExpandMore, - contentDescription = stringResource(if (expanded) R.string.expand_less else R.string.expand_more), + imageVector = if (isExpanded()) Icons.Rounded.ExpandLess else Icons.Rounded.ExpandMore, + contentDescription = stringResource(if (isExpanded()) R.string.expand_less else R.string.expand_more), tint = MaterialTheme.colorScheme.onSecondaryContainer, ) } } Spacer(modifier = Modifier.height(22.dp)) - RYExtensibleVisibility(visible = expanded) { - Column { - feeds.forEach { feed -> - FeedItem( - feed = feed, - tonalElevation = tonalElevation, - ) { - feedOnClick(feed) - } - } - if (feeds.isNotEmpty()) { - Spacer(modifier = Modifier.height(16.dp)) - } - } - } } } \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/drawer/feed/FeedOptionDrawer.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/drawer/feed/FeedOptionDrawer.kt index 5672846..f6f47b0 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/drawer/feed/FeedOptionDrawer.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/drawer/feed/FeedOptionDrawer.kt @@ -1,5 +1,6 @@ package me.ash.reader.ui.page.home.feeds.drawer.feed +import android.view.HapticFeedbackConstants import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.* import androidx.compose.material.ExperimentalMaterialApi @@ -13,6 +14,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -23,6 +25,7 @@ import me.ash.reader.ui.component.FeedIcon import me.ash.reader.ui.component.base.BottomDrawer import me.ash.reader.ui.component.base.TextFieldDialog import me.ash.reader.ui.ext.collectAsStateValue +import me.ash.reader.ui.ext.openURL import me.ash.reader.ui.ext.roundClick import me.ash.reader.ui.ext.showToast import me.ash.reader.ui.page.home.feeds.subscribe.ResultView @@ -34,6 +37,7 @@ fun FeedOptionDrawer( content: @Composable () -> Unit = {}, ) { val context = LocalContext.current + val view = LocalView.current val scope = rememberCoroutineScope() val feedOptionUiState = feedOptionViewModel.feedOptionUiState.collectAsStateValue() val feed = feedOptionUiState.feed @@ -77,7 +81,8 @@ fun FeedOptionDrawer( ResultView( link = feed?.url ?: stringResource(R.string.unknown), groups = feedOptionUiState.groups, - selectedAllowNotificationPreset = feedOptionUiState.feed?.isNotification ?: false, + selectedAllowNotificationPreset = feedOptionUiState.feed?.isNotification + ?: false, selectedParseFullContentPreset = feedOptionUiState.feed?.isFullContent ?: false, isMoveToGroup = true, showUnsubscribe = true, @@ -101,6 +106,10 @@ fun FeedOptionDrawer( feedOptionViewModel.showNewGroupDialog() }, onFeedUrlClick = { + context.openURL(feed?.url) + }, + onFeedUrlLongClick = { + view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP) feedOptionViewModel.showFeedUrlDialog() } ) diff --git a/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt b/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt index 692101e..cadeb24 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/feeds/subscribe/ResultView.kt @@ -1,15 +1,11 @@ package me.ash.reader.ui.page.home.feeds.subscribe import androidx.compose.animation.animateContentSize -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Article @@ -32,7 +28,6 @@ import me.ash.reader.R import me.ash.reader.data.entity.Group import me.ash.reader.ui.component.base.RYSelectionChip import me.ash.reader.ui.component.base.Subtitle -import me.ash.reader.ui.ext.roundClick import me.ash.reader.ui.theme.palette.alwaysLight @Composable @@ -51,7 +46,8 @@ fun ResultView( unsubscribeOnClick: () -> Unit = {}, onGroupClick: (groupId: String) -> Unit = {}, onAddNewGroup: () -> Unit = {}, - onFeedUrlClick: () -> Unit = {} + onFeedUrlClick: () -> Unit = {}, + onFeedUrlLongClick: () -> Unit = {}, ) { LaunchedEffect(Unit) { if (groups.isNotEmpty() && selectedGroupId.isEmpty()) onGroupClick(groups.first().id) @@ -60,7 +56,11 @@ fun ResultView( Column( modifier = modifier.verticalScroll(rememberScrollState()) ) { - EditableUrl(text = link, onFeedUrlClick) + EditableUrl( + text = link, + onClick = onFeedUrlClick, + onLongClick = onFeedUrlLongClick, + ) Spacer(modifier = Modifier.height(26.dp)) Preset( @@ -85,27 +85,30 @@ fun ResultView( } } +@OptIn(ExperimentalFoundationApi::class) @Composable private fun EditableUrl( text: String, - onClick: () -> Unit + onClick: () -> Unit, + onLongClick: () -> Unit, ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center ) { - SelectionContainer { - Text( - modifier = Modifier.roundClick { - onClick() - }, - text = text, - color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f), - style = MaterialTheme.typography.bodyMedium, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - } + Text( + modifier = Modifier + .clip(MaterialTheme.shapes.small) + .combinedClickable( + onClick = onClick, + onLongClick = onLongClick, + ), + text = text, + color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f), + style = MaterialTheme.typography.bodyMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) } } diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt index d741d1c..012a939 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt @@ -13,7 +13,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -25,14 +24,13 @@ import me.ash.reader.data.preference.* import me.ash.reader.ui.component.FeedIcon import me.ash.reader.ui.component.base.RYAsyncImage import me.ash.reader.ui.component.base.SIZE_1000 -import me.ash.reader.ui.theme.SHAPE_20 +import me.ash.reader.ui.theme.Shape20 @Composable fun ArticleItem( articleWithFeed: ArticleWithFeed, onClick: (ArticleWithFeed) -> Unit = {}, ) { - val context = LocalContext.current val articleListFeedIcon = LocalFlowArticleListFeedIcon.current val articleListFeedName = LocalFlowArticleListFeedName.current val articleListImage = LocalFlowArticleListImage.current @@ -42,12 +40,12 @@ fun ArticleItem( Column( modifier = Modifier .padding(horizontal = 12.dp) - .clip(SHAPE_20) + .clip(Shape20) .clickable { onClick(articleWithFeed) } .padding(horizontal = 12.dp, vertical = 12.dp) .alpha(if (articleWithFeed.article.isStarred || articleWithFeed.article.isUnread) 1f else 0.5f), ) { - // Upper + // Top Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, @@ -99,7 +97,7 @@ fun ArticleItem( } } - // Lower + // Bottom Row( modifier = Modifier.fillMaxWidth(), ) { @@ -142,7 +140,7 @@ fun ArticleItem( modifier = Modifier .padding(start = 10.dp) .size(80.dp) - .clip(SHAPE_20), + .clip(Shape20), data = articleWithFeed.article.img, scale = Scale.FILL, precision = Precision.INEXACT, diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPagePreview.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPagePreview.kt new file mode 100644 index 0000000..1408f40 --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPagePreview.kt @@ -0,0 +1,143 @@ +package me.ash.reader.ui.page.settings.color.feeds + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +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.MaterialTheme +import androidx.compose.material3.SmallTopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import me.ash.reader.R +import me.ash.reader.data.entity.Feed +import me.ash.reader.data.entity.Group +import me.ash.reader.data.model.Filter +import me.ash.reader.data.preference.FeedsGroupListExpandPreference +import me.ash.reader.data.preference.FeedsGroupListTonalElevationPreference +import me.ash.reader.data.preference.FeedsTopBarTonalElevationPreference +import me.ash.reader.ui.component.FilterBar +import me.ash.reader.ui.component.base.FeedbackIconButton +import me.ash.reader.ui.ext.alphaLN +import me.ash.reader.ui.ext.surfaceColorAtElevation +import me.ash.reader.ui.page.home.feeds.FeedItem +import me.ash.reader.ui.page.home.feeds.GroupItem +import me.ash.reader.ui.theme.palette.onDark +import kotlin.math.ln + +@Composable +fun FeedsPagePreview( + topBarTonalElevation: FeedsTopBarTonalElevationPreference, + groupListExpand: FeedsGroupListExpandPreference, + groupListTonalElevation: FeedsGroupListTonalElevationPreference, + filterBarStyle: Int, + filterBarFilled: Boolean, + filterBarPadding: Dp, + filterBarTonalElevation: Dp, +) { + var filter by remember { mutableStateOf(Filter.Unread) } + val feedBadgeAlpha by remember { derivedStateOf { (ln(groupListTonalElevation.value + 1.4f) + 2f) / 100f } } + val groupAlpha by remember { derivedStateOf { groupListTonalElevation.value.dp.alphaLN(weight = 1.2f) } } + val groupIndicatorAlpha by remember { + derivedStateOf { + groupListTonalElevation.value.dp.alphaLN( + weight = 1.4f + ) + } + } + + Column( + modifier = Modifier + .animateContentSize() + .background( + color = MaterialTheme.colorScheme.surfaceColorAtElevation( + groupListTonalElevation.value.dp + ) onDark MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(24.dp) + ) + ) { + 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 + ) + }, + actions = { + FeedbackIconButton( + imageVector = Icons.Rounded.Refresh, + contentDescription = stringResource(R.string.refresh), + tint = MaterialTheme.colorScheme.onSurface, + ) + FeedbackIconButton( + imageVector = Icons.Rounded.Add, + contentDescription = stringResource(R.string.subscribe), + tint = MaterialTheme.colorScheme.onSurface, + ) + } + ) + Spacer(modifier = Modifier.height(12.dp)) + GroupItem( + isExpanded = { groupListExpand.value }, + group = generateGroupPreview(), + alpha = groupAlpha, + indicatorAlpha = groupIndicatorAlpha, + ) + FeedItem( + feed = generateFeedPreview(), + alpha = groupAlpha, + badgeAlpha = feedBadgeAlpha, + isEnded = true, + isExpanded = { true }, + ) + Spacer(modifier = Modifier.height(12.dp)) + FilterBar( + filter = filter, + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding, + filterBarTonalElevation = filterBarTonalElevation, + ) { + filter = it + } + } +} + +@Stable +@Composable +fun generateFeedPreview(): Feed = + Feed( + id = "", + name = stringResource(R.string.preview_feed_name), + icon = "", + accountId = 0, + groupId = "", + url = "", + ).apply { + important = 100 + } + +@Stable +@Composable +fun generateGroupPreview(): Group = + Group( + id = "", + name = stringResource(R.string.defaults), + accountId = 0, + ) \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStylePage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStylePage.kt index 2c4095f..3a1a953 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStylePage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/feeds/FeedsPageStylePage.kt @@ -1,38 +1,25 @@ package me.ash.reader.ui.page.settings.color.feeds -import androidx.compose.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape 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.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 import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.Dp 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.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.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 @Composable @@ -270,88 +257,3 @@ fun FeedsPageStylePage( groupListTonalElevationDialogVisible = false } } - -@Composable -fun FeedsPagePreview( - topBarTonalElevation: FeedsTopBarTonalElevationPreference, - groupListExpand: FeedsGroupListExpandPreference, - groupListTonalElevation: FeedsGroupListTonalElevationPreference, - filterBarStyle: Int, - filterBarFilled: Boolean, - filterBarPadding: Dp, - filterBarTonalElevation: Dp, -) { - var filter by remember { mutableStateOf(Filter.Unread) } - - Column( - modifier = Modifier - .animateContentSize() - .background( - color = MaterialTheme.colorScheme.surfaceColorAtElevation( - groupListTonalElevation.value.dp - ) onDark MaterialTheme.colorScheme.surface, - shape = RoundedCornerShape(24.dp) - ) - ) { - 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 - ) {} - }, - actions = { - FeedbackIconButton( - imageVector = Icons.Rounded.Refresh, - contentDescription = stringResource(R.string.refresh), - tint = MaterialTheme.colorScheme.onSurface, - ) {} - FeedbackIconButton( - imageVector = Icons.Rounded.Add, - contentDescription = stringResource(R.string.subscribe), - tint = MaterialTheme.colorScheme.onSurface, - ) {} - } - ) - Spacer(modifier = Modifier.height(12.dp)) - GroupItem( - isExpanded = groupListExpand.value, - tonalElevation = groupListTonalElevation.value.dp, - group = Group( - id = "", - name = stringResource(R.string.defaults), - accountId = 0, - ), - feeds = listOf( - Feed( - id = "", - name = stringResource(R.string.preview_feed_name), - icon = "", - accountId = 0, - groupId = "", - url = "", - ).apply { - important = 100 - } - ), - ) - Spacer(modifier = Modifier.height(12.dp)) - FilterBar( - modifier = Modifier.padding(horizontal = 12.dp), - filter = filter, - filterBarStyle = filterBarStyle, - filterBarFilled = filterBarFilled, - filterBarPadding = filterBarPadding, - filterBarTonalElevation = filterBarTonalElevation, - ) { - filter = it - } - } -} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt new file mode 100644 index 0000000..d3101fb --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt @@ -0,0 +1,124 @@ +package me.ash.reader.ui.page.settings.color.flow + +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +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.MaterialTheme +import androidx.compose.material3.SmallTopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import me.ash.reader.R +import me.ash.reader.data.entity.Article +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.FlowArticleListTonalElevationPreference +import me.ash.reader.data.preference.FlowTopBarTonalElevationPreference +import me.ash.reader.ui.component.FilterBar +import me.ash.reader.ui.component.base.FeedbackIconButton +import me.ash.reader.ui.ext.surfaceColorAtElevation +import me.ash.reader.ui.page.home.flow.ArticleItem +import me.ash.reader.ui.theme.palette.onDark +import java.util.* + +@Composable +fun FlowPagePreview( + topBarTonalElevation: FlowTopBarTonalElevationPreference, + articleListTonalElevation: FlowArticleListTonalElevationPreference, + filterBarStyle: Int, + filterBarFilled: Boolean, + filterBarPadding: Dp, + filterBarTonalElevation: Dp, +) { + var filter by remember { mutableStateOf(Filter.Unread) } + + Column( + modifier = Modifier + .animateContentSize() + .background( + color = MaterialTheme.colorScheme.surfaceColorAtElevation( + articleListTonalElevation.value.dp + ) onDark MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(24.dp) + ) + ) { + 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 + ) {} + }, + actions = { + FeedbackIconButton( + imageVector = Icons.Rounded.DoneAll, + contentDescription = stringResource(R.string.mark_all_as_read), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + FeedbackIconButton( + imageVector = Icons.Rounded.Search, + contentDescription = stringResource(R.string.search), + tint = MaterialTheme.colorScheme.onSurface, + ) {} + } + ) + Spacer(modifier = Modifier.height(12.dp)) + ArticleItem( + articleWithFeed = generateArticleWithFeedPreview(), + ) + Spacer(modifier = Modifier.height(12.dp)) + FilterBar( + filter = filter, + filterBarStyle = filterBarStyle, + filterBarFilled = filterBarFilled, + filterBarPadding = filterBarPadding, + filterBarTonalElevation = filterBarTonalElevation, + ) { + filter = it + } + } +} + +@Stable +@Composable +fun generateArticleWithFeedPreview(): ArticleWithFeed = + ArticleWithFeed( + Article( + id = "", + title = stringResource(R.string.preview_article_title), + shortDescription = stringResource(R.string.preview_article_desc), + rawDescription = stringResource(R.string.preview_article_desc), + link = "", + feedId = "", + accountId = 0, + date = Date(1654053729L), + isStarred = true, + img = "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDJ8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60" + ), + feed = Feed( + id = "", + name = stringResource(R.string.preview_feed_name), + icon = "", + accountId = 0, + groupId = "", + url = "", + ), + ) diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStylePage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStylePage.kt index d8c7116..add9a0d 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStylePage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPageStylePage.kt @@ -1,6 +1,5 @@ package me.ash.reader.ui.page.settings.color.flow -import androidx.compose.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -8,34 +7,20 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape 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.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 import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import me.ash.reader.R -import me.ash.reader.data.entity.Article -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.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.* @Composable fun FlowPageStylePage( @@ -332,90 +317,3 @@ fun FlowPageStylePage( articleListTonalElevationDialogVisible = false } } - -@Composable -fun FlowPagePreview( - topBarTonalElevation: FlowTopBarTonalElevationPreference, - articleListTonalElevation: FlowArticleListTonalElevationPreference, - filterBarStyle: Int, - filterBarFilled: Boolean, - filterBarPadding: Dp, - filterBarTonalElevation: Dp, -) { - var filter by remember { mutableStateOf(Filter.Unread) } - - Column( - modifier = Modifier - .animateContentSize() - .background( - color = MaterialTheme.colorScheme.surfaceColorAtElevation( - articleListTonalElevation.value.dp - ) onDark MaterialTheme.colorScheme.surface, - shape = RoundedCornerShape(24.dp) - ) - ) { - 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 - ) {} - }, - actions = { - FeedbackIconButton( - imageVector = Icons.Rounded.DoneAll, - contentDescription = stringResource(R.string.mark_all_as_read), - tint = MaterialTheme.colorScheme.onSurface, - ) {} - FeedbackIconButton( - imageVector = Icons.Rounded.Search, - contentDescription = stringResource(R.string.search), - tint = MaterialTheme.colorScheme.onSurface, - ) {} - } - ) - Spacer(modifier = Modifier.height(12.dp)) - ArticleItem( - articleWithFeed = ArticleWithFeed( - Article( - id = "", - title = stringResource(R.string.preview_article_title), - shortDescription = stringResource(R.string.preview_article_desc), - rawDescription = stringResource(R.string.preview_article_desc), - link = "", - feedId = "", - accountId = 0, - date = Date(), - isStarred = true, - img = "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDJ8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60" - ), - feed = Feed( - id = "", - name = stringResource(R.string.preview_feed_name), - icon = "", - accountId = 0, - groupId = "", - url = "", - ), - ) - ) - Spacer(modifier = Modifier.height(12.dp)) - FilterBar( - modifier = Modifier.padding(horizontal = 12.dp), - filter = filter, - filterBarStyle = filterBarStyle, - filterBarFilled = filterBarFilled, - filterBarPadding = filterBarPadding, - filterBarTonalElevation = filterBarTonalElevation, - ) { - filter = it - } - } -} \ No newline at end of file diff --git a/app/src/main/java/me/ash/reader/ui/theme/Shapes.kt b/app/src/main/java/me/ash/reader/ui/theme/Shapes.kt index 670cab2..9905264 100644 --- a/app/src/main/java/me/ash/reader/ui/theme/Shapes.kt +++ b/app/src/main/java/me/ash/reader/ui/theme/Shapes.kt @@ -2,6 +2,7 @@ package me.ash.reader.ui.theme import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Shapes +import androidx.compose.runtime.Stable import androidx.compose.ui.unit.dp val Shapes = Shapes( @@ -12,4 +13,14 @@ val Shapes = Shapes( extraLarge = RoundedCornerShape(28.0.dp) ) -val SHAPE_20 = RoundedCornerShape(20.0.dp) \ No newline at end of file +@Stable +val Shape20 = RoundedCornerShape(20.0.dp) + +@Stable +val Shape32 = RoundedCornerShape(32.0.dp) + +@Stable +val ShapeTop32 = RoundedCornerShape(32.0.dp, 32.0.dp, 0.0.dp, 0.0.dp) + +@Stable +val ShapeBottom32 = RoundedCornerShape(0.0.dp, 0.0.dp, 32.0.dp, 32.0.dp)