Skip to content

Commit aa12de5

Browse files
authored
Merge pull request #1063 from DimensionDev/feature/mix_timeline
mixed timeline
2 parents 8982255 + 2b5b6bc commit aa12de5

File tree

155 files changed

+3593
-3935
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

155 files changed

+3593
-3935
lines changed

app/src/main/java/dev/dimension/flare/data/model/TabSettings.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ internal val TitleType.Localized.resId: Int
4545
TitleType.Localized.LocalizedKey.DirectMessage -> R.string.dm_list_title
4646
TitleType.Localized.LocalizedKey.Rss -> R.string.rss_title
4747
TitleType.Localized.LocalizedKey.Antenna -> R.string.home_tab_antennas_title
48+
TitleType.Localized.LocalizedKey.MixedTimeline -> R.string.home_tab_mixed_timeline_title
4849
}
4950

5051
internal fun IconType.Material.MaterialIcon.toIcon(): ImageVector =

app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedsScreen.kt

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import compose.icons.fontawesomeicons.solid.ThumbtackSlash
4141
import compose.icons.fontawesomeicons.solid.Trash
4242
import dev.dimension.flare.R
4343
import dev.dimension.flare.data.model.Bluesky
44-
import dev.dimension.flare.data.model.HomeTimelineTabItem
4544
import dev.dimension.flare.data.model.IconType
4645
import dev.dimension.flare.data.model.TabMetaData
4746
import dev.dimension.flare.data.model.TitleType
@@ -314,11 +313,8 @@ private fun presenter(
314313
val currentTabs =
315314
accountState.user.flatMap { user ->
316315
tabSettings.map {
317-
it.homeTabs
318-
.getOrDefault(
319-
user.key,
320-
listOf(HomeTimelineTabItem(accountType = AccountType.Specific(user.key))),
321-
).filterIsInstance<Bluesky.FeedTabItem>()
316+
it.mainTabs
317+
.filterIsInstance<Bluesky.FeedTabItem>()
322318
.map { it.uri }
323319
.toImmutableList()
324320
}
@@ -349,28 +345,17 @@ private fun presenter(
349345
appScope.launch {
350346
settingsRepository.updateTabSettings {
351347
copy(
352-
homeTabs =
353-
homeTabs + (
354-
user.key to
355-
homeTabs
356-
.getOrDefault(
357-
user.key,
358-
defaultValue =
359-
listOf(
360-
HomeTimelineTabItem(accountType),
361-
),
362-
).plus(
363-
Bluesky.FeedTabItem(
364-
account = AccountType.Specific(user.key),
365-
uri = item.id,
366-
metaData =
367-
TabMetaData(
368-
title = TitleType.Text(item.title),
369-
icon = IconType.Material(IconType.Material.MaterialIcon.Feeds),
370-
),
371-
),
372-
)
373-
),
348+
mainTabs =
349+
mainTabs +
350+
Bluesky.FeedTabItem(
351+
account = AccountType.Specific(user.key),
352+
uri = item.id,
353+
metaData =
354+
TabMetaData(
355+
title = TitleType.Text(item.title),
356+
icon = IconType.Material(IconType.Material.MaterialIcon.Feeds),
357+
),
358+
),
374359
)
375360
}
376361
}
@@ -382,24 +367,14 @@ private fun presenter(
382367
appScope.launch {
383368
settingsRepository.updateTabSettings {
384369
copy(
385-
homeTabs =
386-
homeTabs + (
387-
user.key to
388-
homeTabs
389-
.getOrDefault(
390-
user.key,
391-
defaultValue =
392-
listOf(
393-
HomeTimelineTabItem(accountType),
394-
),
395-
).filter {
396-
if (it is Bluesky.FeedTabItem) {
397-
it.uri != item.id
398-
} else {
399-
true
400-
}
401-
}
402-
),
370+
mainTabs =
371+
mainTabs.filter {
372+
if (it is Bluesky.FeedTabItem) {
373+
it.uri != item.id
374+
} else {
375+
true
376+
}
377+
},
403378
)
404379
}
405380
}

app/src/main/java/dev/dimension/flare/ui/screen/home/HomeEntryBuilder.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ internal fun EntryProviderBuilder<NavKey>.homeEntryBuilder(
8585
TabSettingScreen(
8686
accountType = args.accountType,
8787
onBack = onBack,
88+
toAddRssSource = {
89+
navigate(Route.Rss.Create)
90+
}
8891
)
8992
}
9093
entry<Route.AccountSelection>(

app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import androidx.compose.runtime.Immutable
3636
import androidx.compose.runtime.LaunchedEffect
3737
import androidx.compose.runtime.derivedStateOf
3838
import androidx.compose.runtime.getValue
39+
import androidx.compose.runtime.key
3940
import androidx.compose.runtime.mutableStateOf
4041
import androidx.compose.runtime.remember
4142
import androidx.compose.runtime.rememberCoroutineScope
@@ -55,7 +56,7 @@ import dev.dimension.flare.R
5556
import dev.dimension.flare.common.PagingState
5657
import dev.dimension.flare.common.isRefreshing
5758
import dev.dimension.flare.common.onSuccess
58-
import dev.dimension.flare.data.model.HomeTimelineTabItem
59+
import dev.dimension.flare.data.model.MixedTimelineTabItem
5960
import dev.dimension.flare.data.model.TimelineTabItem
6061
import dev.dimension.flare.data.repository.SettingsRepository
6162
import dev.dimension.flare.model.AccountType
@@ -69,10 +70,8 @@ import dev.dimension.flare.ui.component.platform.isBigScreen
6970
import dev.dimension.flare.ui.component.status.AdaptiveCard
7071
import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid
7172
import dev.dimension.flare.ui.component.status.status
72-
import dev.dimension.flare.ui.model.UiState
7373
import dev.dimension.flare.ui.model.UiTimeline
7474
import dev.dimension.flare.ui.model.collectAsUiState
75-
import dev.dimension.flare.ui.model.flatMap
7675
import dev.dimension.flare.ui.model.map
7776
import dev.dimension.flare.ui.model.onError
7877
import dev.dimension.flare.ui.model.onSuccess
@@ -85,6 +84,7 @@ import dev.dimension.flare.ui.theme.screenHorizontalPadding
8584
import kotlinx.collections.immutable.toImmutableList
8685
import kotlinx.coroutines.flow.distinctUntilChanged
8786
import kotlinx.coroutines.flow.drop
87+
import kotlinx.coroutines.flow.map
8888
import kotlinx.coroutines.flow.mapNotNull
8989
import kotlinx.coroutines.launch
9090
import moe.tlaster.precompose.molecule.producePresenter
@@ -218,25 +218,17 @@ internal fun HomeTimelineScreen(
218218
) { contentPadding ->
219219
state.pagerState.onSuccess { pagerState ->
220220
state.tabState.onSuccess { tabs ->
221-
if (tabs.size == 1) {
222-
// workaround for a bug in HorizontalPager with Drawer
223-
// https://issuetracker.google.com/issues/167408603
221+
HorizontalPager(
222+
state = pagerState,
223+
key = { index ->
224+
tabs.getOrNull(index)?.timelineTabItem?.key ?: "timeline_$index"
225+
},
226+
) { index ->
224227
TimelineItemContent(
225-
state = tabs[0],
228+
state = tabs[index],
226229
contentPadding = contentPadding,
227230
modifier = Modifier.fillMaxWidth(),
228231
)
229-
} else {
230-
HorizontalPager(
231-
state = pagerState,
232-
) { index ->
233-
val tab = tabs[index]
234-
TimelineItemContent(
235-
state = tab,
236-
contentPadding = contentPadding,
237-
modifier = Modifier.fillMaxWidth(),
238-
)
239-
}
240232
}
241233
}
242234
}
@@ -350,35 +342,36 @@ private fun timelinePresenter(
350342
userKey = null,
351343
)
352344
}.invoke()
353-
val tabSettings by settingsRepository.tabSettings.collectAsUiState()
354-
val tabs =
355-
remember(accountType, accountState, tabSettings) {
356-
accountState.user.flatMap(
357-
onError = {
358-
UiState.Success(
359-
listOf(HomeTimelineTabItem(accountType = AccountType.Guest)),
360-
)
361-
},
362-
) { user ->
363-
tabSettings.map {
364-
it.homeTabs.getOrDefault(
365-
user.key,
366-
listOf(HomeTimelineTabItem(accountType = AccountType.Specific(user.key))),
367-
)
368-
}
345+
val tabs by remember {
346+
settingsRepository.tabSettings
347+
.map { settings ->
348+
listOfNotNull(
349+
if (settings.enableMixedTimeline) {
350+
MixedTimelineTabItem(
351+
subTimelineTabItem = settings.mainTabs,
352+
)
353+
} else {
354+
null
355+
},
356+
) + settings.mainTabs
357+
}.map {
358+
it.toImmutableList()
369359
}
370-
}
371-
val pagerState =
372-
tabs.map {
373-
rememberPagerState { it.size }
374-
}
360+
}.collectAsUiState()
375361
val tabState =
376362
tabs.map {
377363
it
378364
.map {
379-
timelineItemPresenter(it)
365+
// use key inorder to force update when the list is changed
366+
key(it.key) {
367+
timelineItemPresenter(it)
368+
}
380369
}.toImmutableList()
381370
}
371+
val pagerState =
372+
tabState.map {
373+
rememberPagerState { it.size }
374+
}
382375

383376
object : UserState by accountState {
384377
val pagerState = pagerState
@@ -389,16 +382,15 @@ private fun timelinePresenter(
389382
@Composable
390383
internal fun timelineItemPresenter(timelineTabItem: TimelineTabItem): TimelineItemState {
391384
val changeLogState = changeLogPresenter()
392-
val timelinePresenter =
393-
remember(timelineTabItem) {
385+
val state =
386+
remember(timelineTabItem.key) {
394387
timelineTabItem.createPresenter()
395-
}
388+
}.invoke()
396389
val badge =
397-
remember(timelineTabItem) {
390+
remember(timelineTabItem.account) {
398391
NotificationBadgePresenter(timelineTabItem.account)
399392
}.invoke()
400393
val scope = rememberCoroutineScope()
401-
val state = timelinePresenter()
402394
var showNewToots by remember { mutableStateOf(false) }
403395
state.listState.onSuccess {
404396
LaunchedEffect(Unit) {

0 commit comments

Comments
 (0)