From fed72e53cd0f48d1f24afcfa040809dc3f07571f Mon Sep 17 00:00:00 2001 From: Tlaster Date: Sun, 7 Jun 2026 03:05:22 +0900 Subject: [PATCH 1/2] initial ui tweak --- .../dimension/flare/ui/component/SearchBar.kt | 11 ++ .../flare/ui/screen/home/DiscoverScreen.kt | 48 +++++-- .../ui/screen/home/HomeTimelineScreen.kt | 45 ++++++- .../ui/screen/home/NotificationScreen.kt | 33 ++++- .../flare/ui/screen/rss/RssDetailScreen.kt | 13 +- .../flare/ui/screen/status/StatusScreen.kt | 22 ++++ .../ui/screen/status/TwitterArticleScreen.kt | 16 ++- .../dev/dimension/flare/ui/theme/Theme.kt | 4 +- .../dimension/flare/ui/theme/Theme.android.kt | 2 +- .../status/LazyStatusVerticalStaggeredGrid.kt | 31 ++++- .../main/kotlin/dev/dimension/flare/App.kt | 2 +- .../dimension/flare/ui/component/Header.kt | 7 +- .../flare/ui/screen/home/DiscoverScreen.kt | 99 ++++++++++++++- .../ui/screen/home/HomeTimelineScreen.kt | 120 ++++++++++++------ .../ui/screen/home/NotificationScreen.kt | 27 +++- .../flare/data/model/AppearanceSettings.kt | 2 +- .../data/model/appearance/AppearanceKeys.kt | 2 +- 17 files changed, 400 insertions(+), 84 deletions(-) diff --git a/app/src/main/java/dev/dimension/flare/ui/component/SearchBar.kt b/app/src/main/java/dev/dimension/flare/ui/component/SearchBar.kt index f71284aa26..95b8b59dbe 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/SearchBar.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/SearchBar.kt @@ -42,6 +42,7 @@ import dev.dimension.flare.common.ImmutableListWrapper import dev.dimension.flare.common.PagingState import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.model.MicroBlogKey import dev.dimension.flare.ui.component.status.AdaptiveCard import dev.dimension.flare.ui.component.status.CommonStatusHeaderComponent @@ -55,6 +56,7 @@ import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.home.SearchHistoryPresenter import dev.dimension.flare.ui.presenter.home.SearchHistoryState import dev.dimension.flare.ui.presenter.invoke +import dev.dimension.flare.ui.theme.screenHorizontalPadding @Composable internal fun SearchBar( @@ -194,6 +196,15 @@ internal fun LazyStaggeredGridScope.searchContent( ) { LazyRow( horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = + Modifier + .let { + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, ) { items(itemCount) { val item = get(it) diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt index b6a0213f45..0c6720fe28 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt @@ -1,6 +1,7 @@ package dev.dimension.flare.ui.screen.home import androidx.activity.compose.BackHandler +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -20,6 +21,7 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -40,20 +42,22 @@ import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.common.isSuccess import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FlareDropdownMenu import dev.dimension.flare.ui.component.FlareScaffold +import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.SearchBar import dev.dimension.flare.ui.component.SearchBarState +import dev.dimension.flare.ui.component.listCardContainer import dev.dimension.flare.ui.component.placeholder import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.component.searchBarPresenter import dev.dimension.flare.ui.component.searchContent -import dev.dimension.flare.ui.component.status.AdaptiveCard import dev.dimension.flare.ui.component.status.CommonStatusHeaderComponent import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.UserPlaceholder @@ -87,8 +91,7 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { Row( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = screenHorizontalPadding), + .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally), verticalAlignment = Alignment.CenterVertically, ) { @@ -157,7 +160,6 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { LazyStatusVerticalStaggeredGrid( state = lazyListState, contentPadding = contentPadding, - forceCardMode = true, ) { if (isBigScreen) { state.accounts.onSuccess { accounts -> @@ -167,7 +169,9 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { ) { LazyRow( horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(bottom = 8.dp), + modifier = + Modifier + .padding(bottom = 8.dp), ) { items(accounts) { profile -> FilterChip( @@ -222,13 +226,26 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { ) { LazyRow( horizontalArrangement = Arrangement.spacedBy(8.dp), + modifier = + Modifier + .let { + if (!isBigScreen && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, ) { items( state.users, loadingContent = { - AdaptiveCard( + Box( modifier = Modifier + .listCardContainer() + .background(MaterialTheme.colorScheme.surfaceContainer) .width(256.dp), ) { UserPlaceholder( @@ -237,9 +254,11 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { } }, ) { item -> - AdaptiveCard( + Box( modifier = Modifier + .listCardContainer() + .background(MaterialTheme.colorScheme.surfaceContainer) .width(256.dp), ) { CommonStatusHeaderComponent( @@ -281,14 +300,27 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { FlowRow( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(4.dp), + modifier = + Modifier + .let { + if (!isBigScreen && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, ) { repeat( itemCount, ) { val hashtag = get(it) - AdaptiveCard( + Box( modifier = Modifier + .listCardContainer() + .background(MaterialTheme.colorScheme.surfaceContainer) .clickable { hashtag?.searchContent?.let { it1 -> state.commitSearch( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt index 39107ad92f..ce698a0853 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt @@ -2,6 +2,7 @@ package dev.dimension.flare.ui.screen.home import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalSharedTransitionApi +import androidx.compose.animation.animateColorAsState import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.layout.Arrangement @@ -33,7 +34,6 @@ import androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api @@ -42,6 +42,7 @@ import androidx.compose.material3.LeadingIconTab import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SecondaryScrollableTabRow +import androidx.compose.material3.TabRowDefaults import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults @@ -55,7 +56,6 @@ import androidx.compose.runtime.remember 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.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -72,6 +72,7 @@ import compose.icons.fontawesomeicons.solid.Sliders import dev.dimension.flare.R import dev.dimension.flare.common.onSuccess import dev.dimension.flare.data.model.BottomBarBehavior +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.data.model.tab.TimelineTabItemV2 import dev.dimension.flare.data.model.tab.resolveTimelineAppearance import dev.dimension.flare.ui.component.AvatarComponent @@ -84,10 +85,10 @@ import dev.dimension.flare.ui.component.LocalGlobalAppearance import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.TabIcon -import dev.dimension.flare.ui.component.TabRowIndicator import dev.dimension.flare.ui.component.platform.LocalWindowSizeClass import dev.dimension.flare.ui.component.platform.WindowSizeClass import dev.dimension.flare.ui.component.platform.isBigScreen +import dev.dimension.flare.ui.component.platform.isCompatScreen import dev.dimension.flare.ui.component.status.AdaptiveCard import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.status @@ -96,6 +97,7 @@ import dev.dimension.flare.ui.model.onError import dev.dimension.flare.ui.model.onLoading import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.model.takeSuccess +import dev.dimension.flare.ui.model.takeSuccessOr import dev.dimension.flare.ui.presenter.HomeTimelineWithTabsPresenter import dev.dimension.flare.ui.presenter.home.DeepLinkPresenter import dev.dimension.flare.ui.presenter.home.LoggedInPresenter @@ -104,6 +106,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.rememberTimelineItemPresenterWithLazyListState import dev.dimension.flare.ui.route.Route import dev.dimension.flare.ui.route.Router +import dev.dimension.flare.ui.theme.isLightTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.coroutines.launch import moe.tlaster.precompose.molecule.producePresenter @@ -219,9 +222,37 @@ internal fun HomeTimelineScreen( } else { TopAppBarDefaults.enterAlwaysScrollBehavior() } + val appearance = LocalTimelineAppearance.current + val displayMode = + remember( + state.tabState, + state.pagerState.takeSuccess()?.currentPage, + appearance, + ) { + state.tabState + .map { + it + .getOrNull(state.pagerState.takeSuccess()?.currentPage ?: 0) + ?.resolveTimelineAppearance(appearance) + ?.timelineDisplayMode ?: TimelineDisplayMode.Plain + }.takeSuccessOr(TimelineDisplayMode.Plain) + } + val color by animateColorAsState( + when (displayMode) { + TimelineDisplayMode.Plain if isLightTheme() && isCompatScreen() -> MaterialTheme.colorScheme.surface + else -> MaterialTheme.colorScheme.background + }, + label = "TopAppBarBackground", + ) FlareScaffold( topBar = { FlareTopAppBar( + colors = + TopAppBarDefaults.topAppBarColors( + containerColor = color, + scrolledContainerColor = color, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ), title = { state.pagerState.onSuccess { pagerState -> state.tabState.onSuccess { tabs -> @@ -239,12 +270,14 @@ internal fun HomeTimelineScreen( edgePadding = 0.dp, divider = {}, indicator = { - TabRowIndicator( - selectedIndex = + TabRowDefaults.SecondaryIndicator( + Modifier.tabIndicatorOffset( minOf( pagerState.currentPage, tabs.lastIndex, ), + matchContentSize = false, + ), ) }, minTabWidth = 48.dp, @@ -252,7 +285,7 @@ internal fun HomeTimelineScreen( state.tabState.onSuccess { tabs -> tabs.forEachIndexed { index, tab -> LeadingIconTab( - modifier = Modifier.clip(CircleShape), + modifier = Modifier, selectedContentColor = MaterialTheme.colorScheme.onSecondaryContainer, unselectedContentColor = LocalContentColor.current, selected = index == pagerState.currentPage, diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt index 5978576279..157b755423 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Badge import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @@ -16,6 +15,7 @@ import androidx.compose.material3.LeadingIconTab import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SecondaryScrollableTabRow +import androidx.compose.material3.TabRowDefaults import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable @@ -24,7 +24,6 @@ import androidx.compose.runtime.remember 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.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource @@ -33,18 +32,20 @@ import dev.dimension.flare.R import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.data.datasource.microblog.NotificationFilter import dev.dimension.flare.data.model.BottomBarBehavior +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.FlareTopAppBar import dev.dimension.flare.ui.component.LocalGlobalAppearance +import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.RefreshContainer -import dev.dimension.flare.ui.component.TabRowIndicator import dev.dimension.flare.ui.component.platform.isCompatScreen import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.status import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.home.AllNotificationPresenter import dev.dimension.flare.ui.presenter.invoke +import dev.dimension.flare.ui.theme.isLightTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.launch @@ -75,6 +76,24 @@ internal fun NotificationScreen() { FlareScaffold( topBar = { FlareTopAppBar( + colors = + when (LocalTimelineAppearance.current.timelineDisplayMode) { + TimelineDisplayMode.Plain if isLightTheme() && isCompatScreen() -> { + TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surface, + scrolledContainerColor = MaterialTheme.colorScheme.surface, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ) + } + + else -> { + TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background, + scrolledContainerColor = MaterialTheme.colorScheme.background, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ) + } + }, title = { if (state.notifications.size > 1) { SecondaryScrollableTabRow( @@ -86,8 +105,11 @@ internal fun NotificationScreen() { edgePadding = 0.dp, divider = {}, indicator = { - TabRowIndicator( - selectedIndex = state.selectedAccountIndex, + TabRowDefaults.SecondaryIndicator( + Modifier.tabIndicatorOffset( + state.selectedAccountIndex, + matchContentSize = false, + ), ) }, minTabWidth = 48.dp, @@ -96,7 +118,6 @@ internal fun NotificationScreen() { val account = item.profile val badge = item.badge LeadingIconTab( - modifier = Modifier.clip(CircleShape), selectedContentColor = MaterialTheme.colorScheme.onSecondaryContainer, unselectedContentColor = LocalContentColor.current, selected = state.selectedAccount?.key == account.key, diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/rss/RssDetailScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/rss/RssDetailScreen.kt index 21119139d4..beca33ad62 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/rss/RssDetailScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/rss/RssDetailScreen.kt @@ -72,6 +72,7 @@ import dev.dimension.flare.ui.presenter.home.rss.RssDetailPresenter import dev.dimension.flare.ui.presenter.home.rss.RssDetailTranslatePresenter import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.server.AiTLDRPresenter +import dev.dimension.flare.ui.theme.isLightTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding import io.ktor.http.Url import kotlinx.collections.immutable.persistentMapOf @@ -91,9 +92,15 @@ internal fun RssDetailScreen( val state by producePresenter(url) { presenter(url, descriptionHtml, descriptionTitle) } val uriHandler = LocalUriHandler.current val context = LocalContext.current + val color = + if (isLightTheme()) { + MaterialTheme.colorScheme.surface + } else { + MaterialTheme.colorScheme.background + } FlareScaffold( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), - containerColor = MaterialTheme.colorScheme.surface, + containerColor = color, topBar = { FlareTopAppBar( title = {}, @@ -103,8 +110,8 @@ internal fun RssDetailScreen( scrollBehavior = scrollBehavior, colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surface, - scrolledContainerColor = MaterialTheme.colorScheme.surface, + containerColor = color, + scrolledContainerColor = color, actionIconContentColor = MaterialTheme.colorScheme.primary, ), actions = { diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt index 7f620dfe1d..307d7824f0 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable @@ -20,6 +21,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.dimension.flare.R import dev.dimension.flare.data.model.BottomBarBehavior +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey import dev.dimension.flare.ui.component.BackButton @@ -29,10 +31,12 @@ import dev.dimension.flare.ui.component.LocalGlobalAppearance import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.platform.isBigScreen +import dev.dimension.flare.ui.component.platform.isCompatScreen import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.status import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.StatusContextPresenter +import dev.dimension.flare.ui.theme.isLightTheme import kotlinx.coroutines.launch import moe.tlaster.precompose.molecule.producePresenter @@ -56,6 +60,24 @@ internal fun StatusScreen( FlareScaffold( topBar = { FlareTopAppBar( + colors = + when (LocalTimelineAppearance.current.timelineDisplayMode) { + TimelineDisplayMode.Plain if isLightTheme() && isCompatScreen() -> { + TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.surface, + scrolledContainerColor = MaterialTheme.colorScheme.surface, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ) + } + + else -> { + TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.background, + scrolledContainerColor = MaterialTheme.colorScheme.background, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ) + } + }, scrollBehavior = topAppBarScrollBehavior, title = { Text(text = stringResource(id = R.string.status_title)) diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/TwitterArticleScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/TwitterArticleScreen.kt index bf63586559..8bba7944f9 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/TwitterArticleScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/TwitterArticleScreen.kt @@ -1,6 +1,5 @@ package dev.dimension.flare.ui.screen.status -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth @@ -27,7 +26,6 @@ import dev.dimension.flare.ui.component.FlareLargeFlexibleTopAppBar import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.RichText import dev.dimension.flare.ui.component.SubcomposeNetworkImage -import dev.dimension.flare.ui.component.listCard import dev.dimension.flare.ui.component.placeholder import dev.dimension.flare.ui.model.ClickContext import dev.dimension.flare.ui.model.UiState @@ -37,6 +35,7 @@ import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.home.xqt.TwitterArticlePresenter import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.screen.settings.AccountItem +import dev.dimension.flare.ui.theme.isLightTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding import dev.dimension.flare.ui.theme.single import moe.tlaster.precompose.molecule.producePresenter @@ -55,10 +54,23 @@ internal fun TwitterArticleScreen( val state by producePresenter(key = "$accountType-$tweetId-$articleId") { TwitterArticlePresenter(accountType, tweetId, articleId).invoke() } + val color = + if (isLightTheme()) { + MaterialTheme.colorScheme.surface + } else { + MaterialTheme.colorScheme.background + } FlareScaffold( modifier = Modifier.nestedScroll(topAppBarScrollBehavior.nestedScrollConnection), + containerColor = color, topBar = { FlareLargeFlexibleTopAppBar( + colors = + TopAppBarDefaults.topAppBarColors( + containerColor = color, + scrolledContainerColor = color, + actionIconContentColor = MaterialTheme.colorScheme.primary, + ), title = { state.data .onSuccess { diff --git a/app/src/main/java/dev/dimension/flare/ui/theme/Theme.kt b/app/src/main/java/dev/dimension/flare/ui/theme/Theme.kt index aee0e37f08..f1387401bb 100644 --- a/app/src/main/java/dev/dimension/flare/ui/theme/Theme.kt +++ b/app/src/main/java/dev/dimension/flare/ui/theme/Theme.kt @@ -56,7 +56,7 @@ private fun ColorScheme.withPureColorLightMode(): ColorScheme = surfaceContainerLowest = Color.White, surfaceContainerHighest = Color.White, onSurfaceVariant = MoreColors.Gray800, - outlineVariant = MoreColors.Gray700, + outlineVariant = MoreColors.Gray400, outline = MoreColors.Gray600, ) @@ -72,7 +72,7 @@ private fun ColorScheme.withPureColorDarkMode(): ColorScheme = surfaceContainerLowest = MoreColors.Gray900, surfaceContainerHighest = MoreColors.Gray900, onSurfaceVariant = MoreColors.Gray400, - outlineVariant = MoreColors.Gray300, + outlineVariant = MoreColors.Gray500, outline = MoreColors.Gray500, ) diff --git a/compose-ui/src/androidMain/kotlin/dev/dimension/flare/ui/theme/Theme.android.kt b/compose-ui/src/androidMain/kotlin/dev/dimension/flare/ui/theme/Theme.android.kt index 4cbdefbe12..d5137f0bc3 100644 --- a/compose-ui/src/androidMain/kotlin/dev/dimension/flare/ui/theme/Theme.android.kt +++ b/compose-ui/src/androidMain/kotlin/dev/dimension/flare/ui/theme/Theme.android.kt @@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Color public val LocalIsLightTheme: ProvidableCompositionLocal = staticCompositionLocalOf { false } @Composable -internal actual fun isLightTheme(): Boolean = LocalIsLightTheme.current +public actual fun isLightTheme(): Boolean = LocalIsLightTheme.current internal actual val PlatformContentColor: ProvidableCompositionLocal get() = LocalContentColor diff --git a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt index 05c709650d..6ac9384409 100644 --- a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt +++ b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.unit.dp import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.LocalTimelineAppearance +import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.theme.PlatformTheme import dev.dimension.flare.ui.theme.isLightTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding @@ -58,11 +59,33 @@ public fun LazyStatusVerticalStaggeredGrid( val displayMode = LocalTimelineAppearance.current.timelineDisplayMode val effectiveMode = when { - allowGalleryMode -> displayMode - displayMode == TimelineDisplayMode.Gallery -> TimelineDisplayMode.Card - else -> displayMode + displayMode == TimelineDisplayMode.Plain && isBigScreen() -> { + TimelineDisplayMode.Card + } + + forceCardMode -> { + TimelineDisplayMode.Card + } + + allowGalleryMode -> { + displayMode + } + + displayMode == TimelineDisplayMode.Gallery -> { + TimelineDisplayMode.Card + } + + else -> { + displayMode + } } - val paddingForColumnCalc = contentPadding + PaddingValues(horizontal = screenHorizontalPadding) + val paddingForColumnCalc = + contentPadding + + if (effectiveMode == TimelineDisplayMode.Plain) { + PaddingValues() + } else { + PaddingValues(horizontal = screenHorizontalPadding) + } val layoutDirection = LocalLayoutDirection.current val density = LocalDensity.current val viewportWidthPx by remember(state) { diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/App.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/App.kt index e215fb9e60..beb699b75b 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/App.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/App.kt @@ -118,7 +118,7 @@ internal fun WindowScope.FlareApp(backButtonState: NavigationBackButtonState) { modifier = Modifier .background( - FluentTheme.colors.background.layerOnMicaBaseAlt.secondary, + FluentTheme.colors.background.mica.base, ).fillMaxHeight() .width(72.dp) .verticalScroll(rememberScrollState()) diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/component/Header.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/component/Header.kt index a47984b904..362453fb2c 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/component/Header.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/component/Header.kt @@ -8,10 +8,13 @@ import io.github.composefluent.FluentTheme import io.github.composefluent.component.Text @Composable -fun Header(text: String) { +fun Header( + text: String, + modifier: Modifier = Modifier, +) { Text( text = text, style = FluentTheme.typography.bodyStrong, - modifier = Modifier.padding(top = 16.dp, bottom = 4.dp), + modifier = modifier.padding(top = 16.dp, bottom = 4.dp), ) } diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt index 2dee2d5bd5..88cbc3e500 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt @@ -43,6 +43,7 @@ import dev.dimension.flare.Res import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess import dev.dimension.flare.common.refreshSuspend +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.delete import dev.dimension.flare.hashtags import dev.dimension.flare.model.AccountType @@ -53,7 +54,9 @@ import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScrollBar import dev.dimension.flare.ui.component.Header +import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.placeholder +import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.component.status.CommonStatusHeaderComponent import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.UserPlaceholder @@ -64,6 +67,7 @@ import dev.dimension.flare.ui.presenter.home.DiscoverState import dev.dimension.flare.ui.presenter.home.SearchHistoryPresenter import dev.dimension.flare.ui.presenter.home.SearchHistoryState import dev.dimension.flare.ui.presenter.invoke +import dev.dimension.flare.ui.theme.screenHorizontalPadding import dev.dimension.flare.users import io.github.composefluent.ExperimentalFluentApi import io.github.composefluent.component.AutoSuggestBoxDefaults @@ -157,7 +161,10 @@ internal fun DiscoverScreen( ListItem( onClick = { state.selectedAccount?.let { user -> - toSearch(AccountType.Specific(user.key), it.keyword) + toSearch( + AccountType.Specific(user.key), + it.keyword, + ) } state.setHistoryExpanded(false) }, @@ -192,7 +199,15 @@ internal fun DiscoverScreen( LiteFilter( modifier = Modifier - .padding(top = 8.dp), + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }.padding(top = 8.dp), ) { accounts.forEach { profile -> PillButton( @@ -227,13 +242,36 @@ internal fun DiscoverScreen( item( span = StaggeredGridItemSpan.FullLine, ) { - Header(stringResource(Res.string.users)) + Header( + stringResource(Res.string.users), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) } item( span = StaggeredGridItemSpan.FullLine, ) { LazyHorizontalGrid( - modifier = Modifier.height(128.dp), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }.height(128.dp), rows = GridCells.Fixed(2), verticalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), @@ -275,14 +313,37 @@ internal fun DiscoverScreen( item( span = StaggeredGridItemSpan.FullLine, ) { - Header(stringResource(Res.string.users)) + Header( + stringResource(Res.string.users), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) } item( span = StaggeredGridItemSpan.FullLine, ) { LazyHorizontalGrid( - modifier = Modifier.height(128.dp), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }.height(128.dp), rows = GridCells.Fixed(2), verticalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), @@ -305,7 +366,20 @@ internal fun DiscoverScreen( item( span = StaggeredGridItemSpan.FullLine, ) { - Header(stringResource(Res.string.hashtags)) + Header( + stringResource(Res.string.hashtags), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) } item( span = StaggeredGridItemSpan.FullLine, @@ -313,6 +387,17 @@ internal fun DiscoverScreen( FlowRow( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(4.dp), + modifier = + Modifier + .let { + if (!isBigScreen() && + LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain + ) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, ) { repeat( itemCount, diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt index 06e37ce121..4e9914438f 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyRow @@ -34,12 +35,15 @@ import androidx.compose.ui.unit.dp import compose.icons.FontAwesomeIcons import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.ArrowsRotate +import compose.icons.fontawesomeicons.solid.ChevronDown import compose.icons.fontawesomeicons.solid.Plus import dev.dimension.flare.LocalWindowPadding import dev.dimension.flare.Res +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.data.model.tab.resolveTimelineAppearance import dev.dimension.flare.model.AccountType import dev.dimension.flare.refresh +import dev.dimension.flare.tab_settings_add_tab import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScrollBar import dev.dimension.flare.ui.component.LocalGlobalAppearance @@ -63,11 +67,14 @@ import dev.dimension.flare.ui.route.Router import dev.dimension.flare.ui.screen.compose.ComposeDialog import dev.dimension.flare.ui.theme.screenHorizontalPadding import io.github.composefluent.FluentTheme -import io.github.composefluent.component.LiteFilter +import io.github.composefluent.component.FlyoutPlacement +import io.github.composefluent.component.MenuFlyoutContainer +import io.github.composefluent.component.MenuFlyoutItem +import io.github.composefluent.component.MenuFlyoutSeparator import io.github.composefluent.component.NavigationDefaults -import io.github.composefluent.component.PillButton import io.github.composefluent.component.ProgressBar import io.github.composefluent.component.SubtleButton +import io.github.composefluent.component.Text import kotlinx.collections.immutable.toImmutableList import moe.tlaster.precompose.molecule.producePresenter import org.jetbrains.compose.resources.stringResource @@ -260,64 +267,101 @@ internal fun HomeTimelineScreen( modifier = Modifier .matchParentSize() - .background(FluentTheme.colors.background.mica.base) - .blur(32.dp), + .background( + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + FluentTheme.colors.background.card.secondary + } else { + FluentTheme.colors.background.mica.base + }, + ).blur(32.dp), ) - Row( + Box( modifier = Modifier .fillMaxWidth(1f) .padding(LocalWindowPadding.current) .padding(horizontal = screenHorizontalPadding), - verticalAlignment = Alignment.CenterVertically, ) { - LiteFilter( + MenuFlyoutContainer( modifier = Modifier - .weight(1f), - ) { - tabState.forEachIndexed { index, tab -> - PillButton( - selected = tab.id == currentTab.id, - onSelectedChanged = { - if (tab.id == currentTab.id) { - if (currentTabTimelineState.lazyListState.firstVisibleItemIndex == 0) { - currentTabTimelineState.refreshSync() - } else { - currentTabTimelineState.lazyListState.requestScrollToItem( - 0, - ) + .align(Alignment.CenterStart), + adaptivePlacement = true, + placement = FlyoutPlacement.Bottom, + flyout = { + tabState.forEachIndexed { index, tab -> + MenuFlyoutItem( + selected = tab.id == currentTab.id, + onSelectedChanged = { + if (it) { + if (tab.id == currentTab.id) { + if (currentTabTimelineState.lazyListState.firstVisibleItemIndex == 0) { + currentTabTimelineState.refreshSync() + } else { + currentTabTimelineState.lazyListState.requestScrollToItem( + 0, + ) + } + } else { + state.setSelectedIndex(index) + } + isFlyoutVisible = false } - } else { - state.setSelectedIndex(index) - } - }, - ) { - TabIcon( - tabItem = tab, + }, + text = { + UiText(tab.title) + }, + icon = { + TabIcon( + tabItem = tab, + ) + }, ) - UiText(tab.title) } - } - PillButton( - selected = false, - onSelectedChanged = { - onAddTab.invoke() + MenuFlyoutSeparator() + MenuFlyoutItem( + onClick = { + isFlyoutVisible = false + onAddTab.invoke() + }, + text = { + Text(stringResource(Res.string.tab_settings_add_tab)) + }, + icon = { + FAIcon( + FontAwesomeIcons.Solid.Plus, + contentDescription = null, + ) + }, + ) + }, + ) { + SubtleButton( + onClick = { + isFlyoutVisible = !isFlyoutVisible }, ) { + TabIcon(currentTab, size = 20.dp) + UiText(currentTab.title) FAIcon( - FontAwesomeIcons.Solid.Plus, + FontAwesomeIcons.Solid.ChevronDown, contentDescription = null, + modifier = Modifier.size(12.dp), ) } } - - SubtleButton(onClick = { - currentTabTimelineState.refreshSync() - }) { + SubtleButton( + modifier = + Modifier + .align(Alignment.CenterEnd), + onClick = { + currentTabTimelineState.refreshSync() + }, + ) { FAIcon( imageVector = FontAwesomeIcons.Solid.ArrowsRotate, contentDescription = stringResource(Res.string.refresh), + modifier = Modifier.size(16.dp), ) } } diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt index 7eb1349a39..05c1ed559e 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt @@ -18,14 +18,17 @@ import androidx.compose.ui.unit.dp import dev.dimension.flare.LocalWindowPadding import dev.dimension.flare.RegisterTabCallback import dev.dimension.flare.common.isRefreshing +import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.FlareScrollBar +import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.status import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.home.AllNotificationPresenter import dev.dimension.flare.ui.presenter.invoke +import dev.dimension.flare.ui.theme.screenHorizontalPadding import io.github.composefluent.component.Badge import io.github.composefluent.component.BadgeStatus import io.github.composefluent.component.LiteFilter @@ -58,7 +61,17 @@ internal fun NotificationScreen() { item( span = StaggeredGridItemSpan.FullLine, ) { - LiteFilter { + LiteFilter( + modifier = + Modifier + .let { + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) { state.notifications.forEach { item -> val profile = item.profile val badge = item.badge @@ -102,7 +115,17 @@ internal fun NotificationScreen() { item( span = StaggeredGridItemSpan.FullLine, ) { - LiteFilter { + LiteFilter( + modifier = + Modifier + .let { + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) { types.forEach { type -> PillButton( selected = state.selectedFilter == type, diff --git a/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/AppearanceSettings.kt b/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/AppearanceSettings.kt index 09c9e0bdd5..fdd4e6de75 100644 --- a/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/AppearanceSettings.kt +++ b/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/AppearanceSettings.kt @@ -36,7 +36,7 @@ internal data class AppearanceSettings( val postActionStyle: PostActionStyle = PostActionStyle.LeftAligned, val absoluteTimestamp: Boolean = false, val showPlatformLogo: Boolean = true, - val timelineDisplayMode: TimelineDisplayMode = TimelineDisplayMode.Card, + val timelineDisplayMode: TimelineDisplayMode = TimelineDisplayMode.Plain, ) { companion object { // for iOS diff --git a/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/appearance/AppearanceKeys.kt b/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/appearance/AppearanceKeys.kt index 91600d3511..28bce89093 100644 --- a/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/appearance/AppearanceKeys.kt +++ b/shared/src/commonMain/kotlin/dev/dimension/flare/data/model/appearance/AppearanceKeys.kt @@ -85,7 +85,7 @@ public object AppearanceKeys { public object TimelineDisplayMode : PerTimeline( "timeline.display_mode", - AppearanceTimelineDisplayMode.Card, + AppearanceTimelineDisplayMode.Plain, AppearanceTimelineDisplayMode.serializer(), ) From b085f160565e9511ad1b92a85846c2e50acde2f5 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Sun, 7 Jun 2026 12:36:09 +0900 Subject: [PATCH 2/2] tweak ui --- .../flare/ui/screen/home/DiscoverScreen.kt | 16 +- .../ui/screen/home/HomeTimelineScreen.kt | 44 ++--- .../ui/screen/home/NotificationScreen.kt | 3 +- .../flare/ui/component/ListCardModifier.kt | 21 +- .../flare/ui/component/status/AdaptiveCard.kt | 44 ++++- .../ui/screen/home/HomeTimelineScreen.kt | 137 +++++++++---- .../ui/screen/home/NotificationScreen.kt | 180 ++++++++++++++---- .../flare/ui/screen/home/ProfileScreen.kt | 10 +- 8 files changed, 325 insertions(+), 130 deletions(-) diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt index 0c6720fe28..f70a125529 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt @@ -1,7 +1,6 @@ package dev.dimension.flare.ui.screen.home import androidx.activity.compose.BackHandler -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -21,7 +20,6 @@ import androidx.compose.material3.FilterChip import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -53,11 +51,11 @@ import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.SearchBar import dev.dimension.flare.ui.component.SearchBarState -import dev.dimension.flare.ui.component.listCardContainer import dev.dimension.flare.ui.component.placeholder import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.component.searchBarPresenter import dev.dimension.flare.ui.component.searchContent +import dev.dimension.flare.ui.component.status.AdaptiveOutlinedCard import dev.dimension.flare.ui.component.status.CommonStatusHeaderComponent import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.UserPlaceholder @@ -241,11 +239,9 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { items( state.users, loadingContent = { - Box( + AdaptiveOutlinedCard( modifier = Modifier - .listCardContainer() - .background(MaterialTheme.colorScheme.surfaceContainer) .width(256.dp), ) { UserPlaceholder( @@ -254,11 +250,9 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { } }, ) { item -> - Box( + AdaptiveOutlinedCard( modifier = Modifier - .listCardContainer() - .background(MaterialTheme.colorScheme.surfaceContainer) .width(256.dp), ) { CommonStatusHeaderComponent( @@ -316,11 +310,9 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) { itemCount, ) { val hashtag = get(it) - Box( + AdaptiveOutlinedCard( modifier = Modifier - .listCardContainer() - .background(MaterialTheme.colorScheme.surfaceContainer) .clickable { hashtag?.searchContent?.let { it1 -> state.commitSearch( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt index ce698a0853..8b7a798f37 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt @@ -268,7 +268,7 @@ internal fun HomeTimelineScreen( tabs.lastIndex, ), edgePadding = 0.dp, - divider = {}, + divider = { }, indicator = { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset( @@ -282,34 +282,32 @@ internal fun HomeTimelineScreen( }, minTabWidth = 48.dp, ) { - state.tabState.onSuccess { tabs -> - tabs.forEachIndexed { index, tab -> - LeadingIconTab( - modifier = Modifier, - selectedContentColor = MaterialTheme.colorScheme.onSecondaryContainer, - unselectedContentColor = LocalContentColor.current, - selected = index == pagerState.currentPage, - onClick = { - scope.launch { - pagerState.scrollToPage(index) - } - }, - text = { - dev.dimension.flare.ui.component.Text( - tab.title, + tabs.forEachIndexed { index, tab -> + LeadingIconTab( + modifier = Modifier, + selectedContentColor = MaterialTheme.colorScheme.onSecondaryContainer, + unselectedContentColor = LocalContentColor.current, + selected = index == pagerState.currentPage, + onClick = { + scope.launch { + pagerState.scrollToPage(index) + } + }, + text = { + dev.dimension.flare.ui.component.Text( + tab.title, // modifier = // Modifier // .padding(8.dp), - ) - }, - icon = { - TabIcon(tab) - }, + ) + }, + icon = { + TabIcon(tab) + }, // colors = FilterChipDefaults.filterChipColors( // containerColor = MaterialTheme.colorScheme.surface, // ), - ) - } + ) } } } diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt index 157b755423..106a366f08 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.material3.Badge import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FilterChip +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.LeadingIconTab import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -103,7 +104,7 @@ internal fun NotificationScreen() { .fillMaxWidth(), selectedTabIndex = state.selectedAccountIndex, edgePadding = 0.dp, - divider = {}, + divider = { }, indicator = { TabRowDefaults.SecondaryIndicator( Modifier.tabIndicatorOffset( diff --git a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/ListCardModifier.kt b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/ListCardModifier.kt index b5714ef469..039730476c 100644 --- a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/ListCardModifier.kt +++ b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/ListCardModifier.kt @@ -3,6 +3,7 @@ package dev.dimension.flare.ui.component import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Shape import dev.dimension.flare.ui.theme.PlatformShapes import dev.dimension.flare.ui.theme.PlatformTheme @@ -10,22 +11,24 @@ import dev.dimension.flare.ui.theme.PlatformTheme public fun Modifier.listCard( index: Int = 0, totalCount: Int = 0, -): Modifier = +): Modifier = this.clip(listCardShape(index, totalCount)) + +@Composable +public fun listCardShape( + index: Int = 0, + totalCount: Int = 0, +): Shape = if (totalCount > 1) { // if first if (index == 0) { - clip( - shape = PlatformTheme.shapes.topCardShape, - ) + PlatformTheme.shapes.topCardShape } else if (index == totalCount - 1) { - clip( - shape = PlatformTheme.shapes.bottomCardShape, - ) + PlatformTheme.shapes.bottomCardShape } else { - clip(shape = PlatformTheme.shapes.listCardItemShape) + PlatformTheme.shapes.listCardItemShape } } else { - clip(shape = PlatformTheme.shapes.listCardContainerShape) + PlatformTheme.shapes.listCardContainerShape } @Composable diff --git a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/AdaptiveCard.kt b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/AdaptiveCard.kt index d4571cb638..295c7cfbbe 100644 --- a/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/AdaptiveCard.kt +++ b/compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/component/status/AdaptiveCard.kt @@ -1,21 +1,21 @@ package dev.dimension.flare.ui.component.status import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.ui.component.HorizontalDivider import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.listCard +import dev.dimension.flare.ui.component.listCardShape import dev.dimension.flare.ui.component.platform.PlatformCard import dev.dimension.flare.ui.theme.PlatformTheme -import dev.dimension.flare.ui.theme.screenHorizontalPadding @Composable public fun AdaptiveCard( @@ -60,3 +60,43 @@ public fun AdaptiveCard( } } } + +@Composable +public fun AdaptiveOutlinedCard( + modifier: Modifier = Modifier, + index: Int = 0, + totalCount: Int = 0, + respectTimelineMode: Boolean = false, + content: @Composable () -> Unit, +) { + val bigScreen = LocalMultipleColumns.current + val displayMode = LocalTimelineAppearance.current.timelineDisplayMode + if (bigScreen || displayMode != TimelineDisplayMode.Plain) { + AdaptiveCard( + modifier = modifier, + index = index, + totalCount = totalCount, + respectTimelineMode = respectTimelineMode, + content = content, + ) + } else { + Box( + modifier = + modifier + .listCard( + index = index, + totalCount = totalCount, + ).background(PlatformTheme.colorScheme.card) + .border( + 1.dp, + PlatformTheme.colorScheme.outline, + listCardShape( + index = index, + totalCount = totalCount, + ), + ), + ) { + content.invoke() + } + } +} diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt index 4e9914438f..d17357b41d 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -29,6 +30,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.blur +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.UriHandler import androidx.compose.ui.unit.dp @@ -37,6 +39,7 @@ import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.ArrowsRotate import compose.icons.fontawesomeicons.solid.ChevronDown import compose.icons.fontawesomeicons.solid.Plus +import compose.icons.fontawesomeicons.solid.Sliders import dev.dimension.flare.LocalWindowPadding import dev.dimension.flare.Res import dev.dimension.flare.data.model.TimelineDisplayMode @@ -73,10 +76,13 @@ import io.github.composefluent.component.MenuFlyoutItem import io.github.composefluent.component.MenuFlyoutSeparator import io.github.composefluent.component.NavigationDefaults import io.github.composefluent.component.ProgressBar +import io.github.composefluent.component.SelectorBar +import io.github.composefluent.component.SelectorBarItem import io.github.composefluent.component.SubtleButton import io.github.composefluent.component.Text import kotlinx.collections.immutable.toImmutableList import moe.tlaster.precompose.molecule.producePresenter +import org.apache.commons.lang3.SystemUtils import org.jetbrains.compose.resources.stringResource import dev.dimension.flare.ui.component.Text as UiText @@ -135,7 +141,9 @@ internal fun HomeTimelineScreen( }, LocalWindowSizeClass provides WindowSizeClass.Compact, ) { - Row { + Row( + modifier = Modifier.clipToBounds(), + ) { Box { Router( modifier = @@ -170,7 +178,13 @@ internal fun HomeTimelineScreen( }, modifier = Modifier - .align(Alignment.TopStart), + .let { + if (SystemUtils.IS_OS_WINDOWS) { + it.padding(top = LocalWindowPadding.current.calculateTopPadding()) + } else { + it + } + }.align(Alignment.TopStart), ) } } @@ -275,24 +289,23 @@ internal fun HomeTimelineScreen( }, ).blur(32.dp), ) - Box( + Row( modifier = Modifier .fillMaxWidth(1f) .padding(LocalWindowPadding.current) .padding(horizontal = screenHorizontalPadding), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - MenuFlyoutContainer( - modifier = - Modifier - .align(Alignment.CenterStart), - adaptivePlacement = true, - placement = FlyoutPlacement.Bottom, - flyout = { + if (isBigScreen()) { + SelectorBar( + modifier = Modifier.weight(1f), + ) { tabState.forEachIndexed { index, tab -> - MenuFlyoutItem( + SelectorBarItem( selected = tab.id == currentTab.id, - onSelectedChanged = { + onSelectedChange = { if (it) { if (tab.id == currentTab.id) { if (currentTabTimelineState.lazyListState.firstVisibleItemIndex == 0) { @@ -305,7 +318,6 @@ internal fun HomeTimelineScreen( } else { state.setSelectedIndex(index) } - isFlyoutVisible = false } }, text = { @@ -318,42 +330,91 @@ internal fun HomeTimelineScreen( }, ) } - MenuFlyoutSeparator() - MenuFlyoutItem( - onClick = { - isFlyoutVisible = false - onAddTab.invoke() - }, - text = { - Text(stringResource(Res.string.tab_settings_add_tab)) - }, - icon = { - FAIcon( - FontAwesomeIcons.Solid.Plus, - contentDescription = null, + } + } else { + MenuFlyoutContainer( + modifier = + Modifier + .weight(1f), + adaptivePlacement = true, + placement = FlyoutPlacement.BottomAlignedStart, + flyout = { + tabState.forEachIndexed { index, tab -> + MenuFlyoutItem( + selected = tab.id == currentTab.id, + onSelectedChanged = { + if (it) { + if (tab.id == currentTab.id) { + if (currentTabTimelineState.lazyListState.firstVisibleItemIndex == 0) { + currentTabTimelineState.refreshSync() + } else { + currentTabTimelineState.lazyListState.requestScrollToItem( + 0, + ) + } + } else { + state.setSelectedIndex(index) + } + isFlyoutVisible = false + } + }, + text = { + UiText(tab.title) + }, + icon = { + TabIcon( + tabItem = tab, + ) + }, ) + } + MenuFlyoutSeparator() + MenuFlyoutItem( + onClick = { + isFlyoutVisible = false + onAddTab.invoke() + }, + text = { + Text(stringResource(Res.string.tab_settings_add_tab)) + }, + icon = { + FAIcon( + FontAwesomeIcons.Solid.Plus, + contentDescription = null, + ) + }, + ) + }, + ) { + SubtleButton( + onClick = { + isFlyoutVisible = !isFlyoutVisible }, - ) - }, - ) { + ) { + TabIcon(currentTab, size = 20.dp) + UiText(currentTab.title) + FAIcon( + FontAwesomeIcons.Solid.ChevronDown, + contentDescription = null, + modifier = Modifier.size(8.dp), + ) + } + } + } + if (isBigScreen()) { SubtleButton( onClick = { - isFlyoutVisible = !isFlyoutVisible + onAddTab.invoke() }, ) { - TabIcon(currentTab, size = 20.dp) - UiText(currentTab.title) FAIcon( - FontAwesomeIcons.Solid.ChevronDown, - contentDescription = null, - modifier = Modifier.size(12.dp), + imageVector = FontAwesomeIcons.Solid.Sliders, + contentDescription = stringResource(Res.string.tab_settings_add_tab), + modifier = Modifier.size(16.dp), ) } } SubtleButton( - modifier = - Modifier - .align(Alignment.CenterEnd), onClick = { currentTabTimelineState.refreshSync() }, diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt index 05c1ed559e..5536b0cff0 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/NotificationScreen.kt @@ -2,10 +2,10 @@ package dev.dimension.flare.ui.screen.home import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState import androidx.compose.runtime.Composable @@ -15,14 +15,19 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import compose.icons.FontAwesomeIcons +import compose.icons.fontawesomeicons.Solid +import compose.icons.fontawesomeicons.solid.ChevronDown import dev.dimension.flare.LocalWindowPadding import dev.dimension.flare.RegisterTabCallback import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.data.model.TimelineDisplayMode import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.AvatarComponentDefaults +import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScrollBar import dev.dimension.flare.ui.component.LocalTimelineAppearance +import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.component.status.status import dev.dimension.flare.ui.model.onSuccess @@ -31,9 +36,15 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.theme.screenHorizontalPadding import io.github.composefluent.component.Badge import io.github.composefluent.component.BadgeStatus +import io.github.composefluent.component.FlyoutPlacement import io.github.composefluent.component.LiteFilter +import io.github.composefluent.component.MenuFlyoutContainer +import io.github.composefluent.component.MenuFlyoutItem import io.github.composefluent.component.PillButton import io.github.composefluent.component.ProgressBar +import io.github.composefluent.component.SelectorBar +import io.github.composefluent.component.SelectorBarItem +import io.github.composefluent.component.SubtleButton import io.github.composefluent.component.Text import kotlinx.coroutines.launch import moe.tlaster.precompose.molecule.producePresenter @@ -61,50 +72,139 @@ internal fun NotificationScreen() { item( span = StaggeredGridItemSpan.FullLine, ) { - LiteFilter( - modifier = - Modifier - .let { - if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { - it.padding(horizontal = screenHorizontalPadding) - } else { - it - } - }, - ) { - state.notifications.forEach { item -> - val profile = item.profile - val badge = item.badge - PillButton( - selected = state.selectedAccount?.key == profile.key, - onSelectedChanged = { - if (it) { - state.setAccount(profile) - } + if (isBigScreen()) { + SelectorBar( + modifier = + Modifier + .let { + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + ) { + state.notifications.forEach { item -> + val profile = item.profile + val badge = item.badge + SelectorBarItem( + selected = state.selectedAccount?.key == profile.key, + onSelectedChange = { + if (it) { + state.setAccount(profile) + } + }, + icon = { + AvatarComponent( + data = profile.avatar, + size = AvatarComponentDefaults.compatSize, + ) + }, + text = { + Text( + profile.handle.canonical, + maxLines = 1, + modifier = Modifier.padding(start = 8.dp), + ) + AnimatedVisibility(badge > 0) { + Badge( + status = BadgeStatus.Informational, + content = { + Text(badge.toString()) + }, + modifier = Modifier.padding(start = 8.dp), + ) + } + }, + ) + } + } + } else { + MenuFlyoutContainer( + adaptivePlacement = true, + placement = FlyoutPlacement.BottomAlignedStart, + flyout = { + state.notifications.forEach { item -> + val profile = item.profile + val badge = item.badge + MenuFlyoutItem( + selected = state.selectedAccount?.key == profile.key, + onSelectedChanged = { + if (it) { + state.setAccount(profile) + } + }, + icon = { + AvatarComponent( + data = profile.avatar, + size = AvatarComponentDefaults.compatSize, + ) + }, + text = { + Text( + profile.handle.canonical, + maxLines = 1, + modifier = Modifier.padding(start = 8.dp), + ) + AnimatedVisibility(badge > 0) { + Badge( + status = BadgeStatus.Informational, + content = { + Text(badge.toString()) + }, + modifier = Modifier.padding(start = 8.dp), + ) + } + }, + ) + } + }, + ) { + SubtleButton( + modifier = + Modifier + .let { + if (LocalTimelineAppearance.current.timelineDisplayMode == TimelineDisplayMode.Plain) { + it.padding(horizontal = screenHorizontalPadding) + } else { + it + } + }, + onClick = { + isFlyoutVisible = !isFlyoutVisible }, ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - AvatarComponent( - data = profile.avatar, - size = AvatarComponentDefaults.compatSize, - ) - Text( - profile.handle.canonical, - maxLines = 1, + AvatarComponent( + data = state.selectedAccount?.avatar, + size = AvatarComponentDefaults.compatSize, + ) + Text( + state.selectedAccount?.handle?.canonical ?: "Select Account", + maxLines = 1, + modifier = Modifier.padding(start = 8.dp), + ) + val badge = + remember( + state.notifications, + ) { + state.notifications.sumOf { + it.badge + } + } + AnimatedVisibility(badge > 0) { + Badge( + status = BadgeStatus.Informational, + content = { + Text(badge.toString()) + }, modifier = Modifier.padding(start = 8.dp), ) - AnimatedVisibility(badge > 0) { - Badge( - status = BadgeStatus.Informational, - content = { - Text(badge.toString()) - }, - modifier = Modifier.padding(start = 8.dp), - ) - } } + FAIcon( + FontAwesomeIcons.Solid.ChevronDown, + contentDescription = null, + modifier = Modifier.size(8.dp), + ) } } } diff --git a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/ProfileScreen.kt b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/ProfileScreen.kt index a068c35f3f..78be81809b 100644 --- a/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/ProfileScreen.kt +++ b/desktopApp/src/main/kotlin/dev/dimension/flare/ui/screen/home/ProfileScreen.kt @@ -49,7 +49,6 @@ import dev.dimension.flare.ui.component.LocalTimelineAppearance import dev.dimension.flare.ui.component.ProfileHeader import dev.dimension.flare.ui.component.ProfileHeaderLoading import dev.dimension.flare.ui.component.ProfileMenu -import dev.dimension.flare.ui.component.ignoreHorizontalParentPadding import dev.dimension.flare.ui.component.placeholder import dev.dimension.flare.ui.component.platform.isBigScreen import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid @@ -256,9 +255,6 @@ internal fun ProfileScreen( ) { Column { ProfileHeader( - modifier = - Modifier - .ignoreHorizontalParentPadding(screenHorizontalPadding), state = state.state, menu = { ProfileMenu( @@ -285,7 +281,11 @@ internal fun ProfileScreen( onFansListClick = onFansListClick, ) state.state.tabs.onSuccess { tabs -> - LiteFilter { + LiteFilter( + modifier = + Modifier + .padding(horizontal = screenHorizontalPadding), + ) { repeat(tabs.size) { index -> val tab = tabs.get(index) PillButton(