Skip to content

Commit 07147cb

Browse files
authored
Merge pull request #1256 from DimensionDev/feature/ios_weblogin
add web login for ios
2 parents bb111d4 + 2e8b089 commit 07147cb

Some content is hidden

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

43 files changed

+1076
-623
lines changed

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

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import dev.chrisbanes.haze.hazeSource
4848
import dev.chrisbanes.haze.rememberHazeState
4949
import dev.dimension.flare.R
5050
import dev.dimension.flare.common.onSuccess
51+
import dev.dimension.flare.data.model.TimelineTabItem
5152
import dev.dimension.flare.model.AccountType
5253
import dev.dimension.flare.ui.component.AvatarComponent
5354
import dev.dimension.flare.ui.component.FAIcon
@@ -67,7 +68,7 @@ import dev.dimension.flare.ui.model.map
6768
import dev.dimension.flare.ui.model.onError
6869
import dev.dimension.flare.ui.model.onSuccess
6970
import dev.dimension.flare.ui.presenter.HomeTimelineWithTabsPresenter
70-
import dev.dimension.flare.ui.presenter.TimelineItemPresenter
71+
import dev.dimension.flare.ui.presenter.TimelineItemPresenterWithLazyListState
7172
import dev.dimension.flare.ui.presenter.invoke
7273
import dev.dimension.flare.ui.theme.screenHorizontalPadding
7374
import kotlinx.coroutines.launch
@@ -86,28 +87,6 @@ internal fun HomeTimelineScreen(
8687
timelinePresenter(accountType)
8788
}
8889
val scope = rememberCoroutineScope()
89-
state.pagerState.onSuccess { pagerState ->
90-
state.tabState.onSuccess { tabState ->
91-
LaunchedEffect(pagerState.currentPage >= tabState.size) {
92-
if (pagerState.currentPage >= tabState.size) {
93-
scope.launch {
94-
pagerState.scrollToPage(0)
95-
}
96-
}
97-
}
98-
val currentTab = tabState.elementAtOrNull(pagerState.currentPage)
99-
if (currentTab != null) {
100-
val lazyListState = currentTab.lazyListState
101-
RegisterTabCallback(
102-
lazyListState = lazyListState,
103-
onRefresh = {
104-
currentTab.refreshSync()
105-
state.changeLogState.dismissChangeLog()
106-
},
107-
)
108-
}
109-
}
110-
}
11190

11291
val topAppBarScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
11392
FlareScaffold(
@@ -154,17 +133,17 @@ internal fun HomeTimelineScreen(
154133
},
155134
text = {
156135
TabTitle(
157-
tab.timelineTabItem.metaData.title,
136+
tab.metaData.title,
158137
// modifier =
159138
// Modifier
160139
// .padding(8.dp),
161140
)
162141
},
163142
icon = {
164143
TabIcon(
165-
accountType = tab.timelineTabItem.account,
166-
icon = tab.timelineTabItem.metaData.icon,
167-
title = tab.timelineTabItem.metaData.title,
144+
accountType = tab.account,
145+
icon = tab.metaData.icon,
146+
title = tab.metaData.title,
168147
)
169148
},
170149
// colors = FilterChipDefaults.filterChipColors(
@@ -221,18 +200,28 @@ internal fun HomeTimelineScreen(
221200
modifier = Modifier.nestedScroll(topAppBarScrollBehavior.nestedScrollConnection),
222201
) { contentPadding ->
223202
state.pagerState.onSuccess { pagerState ->
224-
state.tabState.onSuccess { tabs ->
203+
state.tabState.onSuccess { tabState ->
204+
205+
LaunchedEffect(pagerState.currentPage >= tabState.size) {
206+
if (pagerState.currentPage >= tabState.size) {
207+
scope.launch {
208+
pagerState.scrollToPage(0)
209+
}
210+
}
211+
}
212+
225213
HorizontalPager(
226214
state = pagerState,
227215
key = { index ->
228-
tabs.getOrNull(index)?.timelineTabItem?.key ?: "timeline_$index"
216+
tabState.getOrNull(index)?.key ?: "timeline_$index"
229217
},
230218
) { index ->
231219
TimelineItemContent(
232-
state = tabs[index],
220+
item = tabState[index],
233221
contentPadding = contentPadding,
234222
modifier = Modifier.fillMaxWidth(),
235223
changeLogState = state.changeLogState,
224+
isCurrentlyVisible = pagerState.currentPage == index,
236225
)
237226
}
238227
}
@@ -242,11 +231,27 @@ internal fun HomeTimelineScreen(
242231

243232
@Composable
244233
internal fun TimelineItemContent(
245-
state: TimelineItemPresenter.State,
234+
item: TimelineTabItem,
246235
modifier: Modifier = Modifier,
247236
contentPadding: PaddingValues = PaddingValues(0.dp),
248237
changeLogState: ChangeLogState? = null,
238+
isCurrentlyVisible: Boolean = true,
249239
) {
240+
val state by producePresenter(
241+
"timeline_${item.key}",
242+
) {
243+
remember { TimelineItemPresenterWithLazyListState(item) }
244+
.invoke()
245+
}
246+
if (isCurrentlyVisible) {
247+
RegisterTabCallback(
248+
lazyListState = state.lazyListState,
249+
onRefresh = {
250+
state.refreshSync()
251+
changeLogState?.dismissChangeLog()
252+
},
253+
)
254+
}
250255
val hazeState = rememberHazeState()
251256
val scope = rememberCoroutineScope()
252257
RefreshContainer(

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import dev.dimension.flare.ui.component.FlareLargeFlexibleTopAppBar
1818
import dev.dimension.flare.ui.component.FlareScaffold
1919
import dev.dimension.flare.ui.component.TabTitle
2020
import dev.dimension.flare.ui.model.onError
21-
import dev.dimension.flare.ui.presenter.TimelineItemPresenter
2221
import dev.dimension.flare.ui.presenter.home.UserPresenter
2322
import dev.dimension.flare.ui.presenter.home.UserState
2423
import dev.dimension.flare.ui.presenter.invoke
@@ -34,12 +33,12 @@ internal fun TimelineScreen(
3433
val state by producePresenter(key = "timeline_${tabItem.key}") {
3534
timelinePresenter(tabItem)
3635
}
37-
RegisterTabCallback(
38-
lazyListState = state.lazyListState,
39-
onRefresh = {
40-
state.refreshSync()
41-
},
42-
)
36+
// RegisterTabCallback(
37+
// lazyListState = state.lazyListState,
38+
// onRefresh = {
39+
// state.refreshSync()
40+
// },
41+
// )
4342
val topAppBarScrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
4443
FlareScaffold(
4544
topBar = {
@@ -66,7 +65,7 @@ internal fun TimelineScreen(
6665
modifier = Modifier.nestedScroll(topAppBarScrollBehavior.nestedScrollConnection),
6766
) { contentPadding ->
6867
TimelineItemContent(
69-
state = state,
68+
item = tabItem,
7069
contentPadding = contentPadding,
7170
modifier = Modifier.fillMaxSize(),
7271
)
@@ -76,14 +75,13 @@ internal fun TimelineScreen(
7675
@Composable
7776
private fun timelinePresenter(tabItem: TimelineTabItem) =
7877
run {
79-
val state = remember(tabItem.key) { TimelineItemPresenter(tabItem) }.invoke()
8078
val accountState =
8179
remember(tabItem.account) {
8280
UserPresenter(
8381
accountType = tabItem.account,
8482
userKey = null,
8583
)
8684
}.invoke()
87-
object : UserState by accountState, TimelineItemPresenter.State by state {
85+
object : UserState by accountState {
8886
}
8987
}

compose-ui/src/commonMain/kotlin/dev/dimension/flare/data/model/TabSettings.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.datastore.core.okio.OkioSerializer
44
import dev.dimension.flare.model.AccountType
55
import dev.dimension.flare.model.MicroBlogKey
66
import dev.dimension.flare.model.PlatformType
7+
import dev.dimension.flare.ui.model.UiAccount
78
import dev.dimension.flare.ui.model.UiRssSource
89
import dev.dimension.flare.ui.model.UiUserV2
910
import dev.dimension.flare.ui.presenter.home.HomeTimelinePresenter
@@ -241,7 +242,7 @@ public sealed class TimelineTabItem : TabItem() {
241242
PlatformType.VVo -> vvo(user.key)
242243
}
243244

244-
public fun defaultSecondary(user: UiUserV2): ImmutableList<TabItem> {
245+
public fun defaultSecondary(user: UiAccount): ImmutableList<TabItem> {
245246
val result =
246247
listOf(
247248
RssTabItem(
@@ -254,11 +255,11 @@ public sealed class TimelineTabItem : TabItem() {
254255
),
255256
) +
256257
when (user.platformType) {
257-
PlatformType.Mastodon -> defaultMastodonSecondaryItems(user.key)
258-
PlatformType.Misskey -> defaultMisskeySecondaryItems(user.key)
259-
PlatformType.Bluesky -> defaultBlueskySecondaryItems(user.key)
260-
PlatformType.xQt -> defaultXqtSecondaryItems(user.key)
261-
PlatformType.VVo -> defaultVVOSecondaryItems(user.key)
258+
PlatformType.Mastodon -> defaultMastodonSecondaryItems(user.accountKey)
259+
PlatformType.Misskey -> defaultMisskeySecondaryItems(user.accountKey)
260+
PlatformType.Bluesky -> defaultBlueskySecondaryItems(user.accountKey)
261+
PlatformType.xQt -> defaultXqtSecondaryItems(user.accountKey)
262+
PlatformType.VVo -> defaultVVOSecondaryItems(user.accountKey)
262263
}
263264
return result.toImmutableList()
264265
}

compose-ui/src/commonMain/kotlin/dev/dimension/flare/ui/presenter/HomeTabsPresenter.kt

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,27 @@ package dev.dimension.flare.ui.presenter
22

33
import androidx.compose.runtime.Composable
44
import androidx.compose.runtime.Immutable
5-
import androidx.compose.runtime.getValue
65
import androidx.compose.runtime.remember
76
import dev.dimension.flare.data.model.DirectMessageTabItem
87
import dev.dimension.flare.data.model.NotificationTabItem
98
import dev.dimension.flare.data.model.ProfileTabItem
109
import dev.dimension.flare.data.model.TabItem
1110
import dev.dimension.flare.data.model.TimelineTabItem
11+
import dev.dimension.flare.data.repository.AccountRepository
1212
import dev.dimension.flare.data.repository.SettingsRepository
13+
import dev.dimension.flare.data.repository.activeAccountFlow
1314
import dev.dimension.flare.model.AccountType
1415
import dev.dimension.flare.ui.model.UiState
1516
import dev.dimension.flare.ui.model.collectAsUiState
1617
import dev.dimension.flare.ui.model.map
17-
import dev.dimension.flare.ui.model.zipState
1818
import dev.dimension.flare.ui.presenter.HomeTabsPresenter.State.HomeTabState.HomeTabItem
19-
import dev.dimension.flare.ui.presenter.home.ActiveAccountPresenter
2019
import dev.dimension.flare.ui.presenter.home.DirectMessageBadgePresenter
2120
import dev.dimension.flare.ui.presenter.home.NotificationBadgePresenter
2221
import kotlinx.collections.immutable.ImmutableList
2322
import kotlinx.collections.immutable.persistentListOf
2423
import kotlinx.collections.immutable.toImmutableList
24+
import kotlinx.coroutines.flow.combine
25+
import kotlinx.coroutines.flow.distinctUntilChangedBy
2526
import org.koin.core.component.KoinComponent
2627
import org.koin.core.component.inject
2728

@@ -54,33 +55,27 @@ public class HomeTabsPresenter :
5455
}
5556

5657
private val settingsRepository by inject<SettingsRepository>()
57-
58-
@Composable
59-
override fun body(): State {
60-
val activeAccount = remember { ActiveAccountPresenter() }.body()
61-
val tabSettings by settingsRepository.tabSettings.collectAsUiState()
62-
val tabs =
63-
remember(tabSettings, activeAccount.user) {
64-
zipState(
65-
tabSettings,
66-
activeAccount.user,
67-
onError = {
68-
UiState.Success(
69-
State.HomeTabState(
70-
primary =
71-
TimelineTabItem.guest
72-
.map {
73-
HomeTabItem(it)
74-
}.toImmutableList(),
75-
secondary = persistentListOf(),
76-
extraProfileRoute = null,
77-
secondaryIconOnly = true,
78-
),
79-
)
80-
},
81-
) { settings, user ->
58+
private val accountRepository by inject<AccountRepository>()
59+
private val tabsFlow by lazy {
60+
activeAccountFlow(accountRepository)
61+
.combine(
62+
settingsRepository.tabSettings.distinctUntilChangedBy { it.secondaryItems },
63+
) { account, tabsState ->
64+
println("Active account changed: $account, tabsState: $tabsState")
65+
if (account == null) {
66+
State.HomeTabState(
67+
primary =
68+
TimelineTabItem.guest
69+
.map {
70+
HomeTabItem(it)
71+
}.toImmutableList(),
72+
secondary = persistentListOf(),
73+
extraProfileRoute = null,
74+
secondaryIconOnly = true,
75+
)
76+
} else {
8277
val secondary =
83-
settings.secondaryItems ?: TimelineTabItem.defaultSecondary(user)
78+
tabsState.secondaryItems ?: TimelineTabItem.defaultSecondary(account)
8479
State.HomeTabState(
8580
primary =
8681
TimelineTabItem.default
@@ -96,14 +91,22 @@ public class HomeTabsPresenter :
9691
HomeTabItem(
9792
tabItem =
9893
ProfileTabItem(
99-
accountKey = user.key,
100-
userKey = user.key,
94+
accountKey = account.accountKey,
95+
userKey = account.accountKey,
10196
),
10297
),
103-
secondaryIconOnly = settings.secondaryItems == null,
98+
secondaryIconOnly = tabsState.secondaryItems == null,
10499
)
105100
}
106-
}.map {
101+
}
102+
}
103+
104+
@Composable
105+
override fun body(): State {
106+
val tabs =
107+
remember(tabsFlow) {
108+
tabsFlow
109+
}.collectAsUiState().value.map {
107110
it.copy(
108111
primary =
109112
it.primary

0 commit comments

Comments
 (0)