Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 4a50c1f

Browse files
committed
Migrate SignIn to Flows
Change-Id: Ia5c8b28d837a72604790eee01e6091f30254b2ad
1 parent f09f4c6 commit 4a50c1f

32 files changed

+270
-291
lines changed

mobile/src/main/java/com/google/samples/apps/iosched/ui/MainActivityViewModel.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class MainActivityViewModel @Inject constructor(
5353
private val _navigationActions = Channel<MainNavigationAction>(Channel.CONFLATED)
5454
val navigationActions = _navigationActions.receiveAsFlow()
5555

56-
val pinnedSessionsJson: StateFlow<String> = currentUserInfoFlow.transformLatest { user ->
56+
val pinnedSessionsJson: StateFlow<String> = userInfo.transformLatest { user ->
5757
val uid = user?.getUid()
5858
if (uid != null) {
5959
loadPinnedSessionsUseCase(uid).collect { result ->
@@ -66,7 +66,7 @@ class MainActivityViewModel @Inject constructor(
6666
}
6767
}.stateIn(viewModelScope, WhileViewSubscribed, "")
6868

69-
val canSignedInUserDemoAr: StateFlow<Boolean> = currentUserInfoFlow.transformLatest {
69+
val canSignedInUserDemoAr: StateFlow<Boolean> = userInfo.transformLatest {
7070
val result = loadArDebugFlagUseCase(Unit)
7171
if (result is Result.Success) {
7272
emit(result.data)
@@ -89,7 +89,7 @@ class MainActivityViewModel @Inject constructor(
8989
}.stateIn(viewModelScope, WhileViewSubscribed, null)
9090

9191
fun onProfileClicked() {
92-
if (isSignedIn()) {
92+
if (isUserSignedInValue) {
9393
_navigationActions.tryOffer(MainNavigationAction.OpenSignOut)
9494
} else {
9595
_navigationActions.tryOffer(MainNavigationAction.OpenSignIn)

mobile/src/main/java/com/google/samples/apps/iosched/ui/feed/FeedFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class FeedFragment : MainNavigationFragment() {
171171
val countdownViewBinder = CountdownViewBinder()
172172
val momentViewBinder = MomentViewBinder(
173173
eventListener = model,
174-
userInfoLiveData = model.currentUserInfo,
174+
userInfo = model.userInfo,
175175
themeLiveData = model.theme
176176
)
177177
val sessionsViewBinder = FeedSessionsViewBinder(model)

mobile/src/main/java/com/google/samples/apps/iosched/ui/feed/FeedHeaderViewBinders.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import android.view.ViewGroup
2222
import android.widget.Button
2323
import androidx.core.view.isVisible
2424
import androidx.databinding.BindingAdapter
25-
import androidx.lifecycle.LiveData
2625
import androidx.recyclerview.widget.RecyclerView.ViewHolder
2726
import com.google.android.material.button.MaterialButton
2827
import com.google.samples.apps.iosched.R
@@ -63,14 +62,14 @@ class CountdownViewBinder : FeedItemViewBinder<CountdownItem, CountdownViewHolde
6362
// A Moment may be shown during or after the conference based on the current time
6463
class MomentViewBinder(
6564
private val eventListener: FeedEventListener,
66-
private val userInfoLiveData: LiveData<AuthenticatedUserInfo?>,
65+
private val userInfo: StateFlow<AuthenticatedUserInfo?>,
6766
private val themeLiveData: StateFlow<Theme>
6867
) : FeedItemViewBinder<Moment, MomentViewHolder>(Moment::class.java) {
6968

7069
override fun createViewHolder(parent: ViewGroup): MomentViewHolder {
7170
val binding =
7271
ItemFeedMomentBinding.inflate(LayoutInflater.from(parent.context), parent, false)
73-
return MomentViewHolder(binding, eventListener, userInfoLiveData, themeLiveData)
72+
return MomentViewHolder(binding, eventListener, userInfo, themeLiveData)
7473
}
7574

7675
override fun bindViewHolder(model: Moment, viewHolder: MomentViewHolder) {
@@ -88,15 +87,15 @@ class MomentViewBinder(
8887
class MomentViewHolder(
8988
private val binding: ItemFeedMomentBinding,
9089
private val eventListener: FeedEventListener,
91-
private val userInfoLiveData: LiveData<AuthenticatedUserInfo?>,
90+
private val userInfo: StateFlow<AuthenticatedUserInfo?>,
9291
private val themeLiveData: StateFlow<Theme>
9392
) : ViewHolder(binding.root) {
9493

9594
fun bind(item: Moment) {
9695
binding.executeAfter {
9796
moment = item
9897
theme = themeLiveData
99-
userInfo = userInfoLiveData
98+
userInfo = userInfo
10099
eventListener = this@MomentViewHolder.eventListener
101100
}
102101
}

mobile/src/main/java/com/google/samples/apps/iosched/ui/feed/FeedViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class FeedViewModel @Inject constructor(
129129
val timeZoneId = timeZoneIdFlow.asLiveData()
130130

131131
private val loadSessionsResult: StateFlow<Result<List<UserSession>>> =
132-
signInViewModelDelegate.observeUserId()
132+
signInViewModelDelegate.userId
133133
.flatMapLatest {
134134
// TODO(jdkoren): might need to show sessions for not signed in users too...
135135
loadStarredAndReservedSessionsUseCase(it)
@@ -186,7 +186,7 @@ class FeedViewModel @Inject constructor(
186186
combine(
187187
feedSessionsContainer,
188188
conferenceState,
189-
signInViewModelDelegate.currentUserInfoFlow
189+
signInViewModelDelegate.userInfo
190190
) { sessionsContainer: FeedSessions,
191191
conferenceState: ConferenceState,
192192
userInfo: AuthenticatedUserInfo?

mobile/src/main/java/com/google/samples/apps/iosched/ui/map/MapFragment.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import androidx.core.widget.NestedScrollView
3636
import androidx.fragment.app.DialogFragment
3737
import androidx.fragment.app.activityViewModels
3838
import androidx.fragment.app.viewModels
39-
import androidx.lifecycle.Observer
4039
import androidx.lifecycle.lifecycleScope
4140
import com.google.android.gms.maps.MapView
4241
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -53,6 +52,7 @@ import com.google.samples.apps.iosched.util.slideOffsetToAlpha
5352
import com.google.samples.apps.iosched.widget.BottomSheetBehavior
5453
import com.google.samples.apps.iosched.widget.BottomSheetBehavior.BottomSheetCallback
5554
import dagger.hilt.android.AndroidEntryPoint
55+
import kotlinx.coroutines.flow.collect
5656
import kotlinx.coroutines.launch
5757
import org.threeten.bp.Instant
5858
import javax.inject.Inject
@@ -154,12 +154,11 @@ class MapFragment : MainNavigationFragment() {
154154
setupProfileMenuItem(mainActivityViewModel, this@MapFragment)
155155

156156
menu.findItem(R.id.action_my_location)?.let { item ->
157-
viewModel.showMyLocationOption.observe(
158-
viewLifecycleOwner,
159-
Observer { option ->
160-
item.isVisible = (option == true)
157+
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
158+
viewModel.showMyLocationOption.collect { option ->
159+
item.isVisible = option
161160
}
162-
)
161+
}
163162
}
164163
setOnMenuItemClickListener { item ->
165164
if (item.itemId == R.id.action_my_location) {

mobile/src/main/java/com/google/samples/apps/iosched/ui/map/MapViewModel.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ import com.google.samples.apps.iosched.shared.result.Event
3838
import com.google.samples.apps.iosched.shared.result.successOr
3939
import com.google.samples.apps.iosched.shared.result.updateOnSuccess
4040
import com.google.samples.apps.iosched.ui.signin.SignInViewModelDelegate
41-
import com.google.samples.apps.iosched.util.combine
4241
import com.google.samples.apps.iosched.widget.BottomSheetBehavior
4342
import dagger.hilt.android.lifecycle.HiltViewModel
43+
import kotlinx.coroutines.flow.MutableStateFlow
44+
import kotlinx.coroutines.flow.combine
4445
import kotlinx.coroutines.launch
4546
import javax.inject.Inject
4647

@@ -88,9 +89,9 @@ class MapViewModel @Inject constructor(
8889
val selectedMarkerInfo: LiveData<MarkerInfo?>
8990
get() = _selectedMarkerInfo
9091

91-
private val myLocationOptedIn = MutableLiveData<Boolean>()
92+
private val myLocationOptedIn = MutableStateFlow<Boolean>(false)
9293

93-
val showMyLocationOption = currentUserInfo.combine(myLocationOptedIn) { info, optedIn ->
94+
val showMyLocationOption = userInfo.combine(myLocationOptedIn) { info, optedIn ->
9495
// Show the button to enable "My Location" when the user is an on-site attendee and he/she
9596
// is not opted into the feature yet.
9697
info != null && info.isRegistered() && !optedIn

mobile/src/main/java/com/google/samples/apps/iosched/ui/reservation/RemoveReservationViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class RemoveReservationViewModel @Inject constructor(
5757
_sessionId.value = sessionId
5858
loadUserSessionJob.cancelIfActive()
5959
loadUserSessionJob = viewModelScope.launch {
60-
loadUserSessionUseCase(getUserId() to sessionId).collect { loadResult ->
60+
loadUserSessionUseCase(userIdValue to sessionId).collect { loadResult ->
6161
loadResult.data?.userSession?.let {
6262
_userSession.value = it
6363
}
@@ -66,7 +66,7 @@ class RemoveReservationViewModel @Inject constructor(
6666
}
6767

6868
fun removeReservation() {
69-
val userId = getUserId() ?: return
69+
val userId = userIdValue ?: return
7070
val sessionId = _sessionId.value ?: return
7171
val userSession = _userSession.value
7272
viewModelScope.launch {

mobile/src/main/java/com/google/samples/apps/iosched/ui/schedule/ScheduleFragment.kt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import com.google.samples.apps.iosched.shared.analytics.AnalyticsActions
3939
import com.google.samples.apps.iosched.shared.analytics.AnalyticsHelper
4040
import com.google.samples.apps.iosched.shared.di.SearchScheduleEnabledFlag
4141
import com.google.samples.apps.iosched.shared.domain.sessions.ConferenceDayIndexer
42-
import com.google.samples.apps.iosched.shared.result.EventObserver
4342
import com.google.samples.apps.iosched.shared.util.TimeUtils
4443
import com.google.samples.apps.iosched.ui.MainActivityViewModel
4544
import com.google.samples.apps.iosched.ui.MainNavigationFragment
@@ -55,6 +54,7 @@ import com.google.samples.apps.iosched.ui.messages.setupSnackbarManager
5554
import com.google.samples.apps.iosched.ui.signin.NotificationsPreferenceDialogFragment
5655
import com.google.samples.apps.iosched.ui.signin.NotificationsPreferenceDialogFragment.Companion.DIALOG_NOTIFICATIONS_PREFERENCE
5756
import com.google.samples.apps.iosched.ui.signin.SignInDialogFragment
57+
import com.google.samples.apps.iosched.ui.signin.SignInNavigationAction.ShowNotificationPreferencesDialog
5858
import com.google.samples.apps.iosched.ui.signin.SignOutDialogFragment
5959
import com.google.samples.apps.iosched.ui.signin.setupProfileMenuItem
6060
import com.google.samples.apps.iosched.util.clearDecorations
@@ -66,6 +66,7 @@ import com.google.samples.apps.iosched.widget.FadingSnackbar
6666
import com.google.samples.apps.iosched.widget.JumpSmoothScroller
6767
import dagger.hilt.android.AndroidEntryPoint
6868
import kotlinx.coroutines.flow.collect
69+
import kotlinx.coroutines.launch
6970
import javax.inject.Inject
7071
import javax.inject.Named
7172

@@ -215,25 +216,24 @@ class ScheduleFragment : MainNavigationFragment() {
215216
}
216217
}
217218
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
218-
scheduleViewModel.navigationActions.collect {
219-
when (it) {
220-
is NavigateToSession -> openSessionDetail(it.sessionId)
221-
is NavigateToSignInDialogAction -> openSignInDialog()
222-
is NavigateToSignOutDialogAction -> openSignOutDialog()
223-
is ShowScheduleUiHints -> openScheduleUiHintsDialog()
219+
launch {
220+
scheduleViewModel.navigationActions.collect {
221+
when (it) {
222+
is NavigateToSession -> openSessionDetail(it.sessionId)
223+
is NavigateToSignInDialogAction -> openSignInDialog()
224+
is NavigateToSignOutDialogAction -> openSignOutDialog()
225+
is ShowScheduleUiHints -> openScheduleUiHintsDialog()
226+
}
224227
}
225228
}
226-
}
227-
228-
// TODO: Migrate to StateFlow
229-
scheduleViewModel.shouldShowNotificationsPrefAction.observe(
230-
viewLifecycleOwner,
231-
EventObserver {
232-
if (it) {
233-
openNotificationsPreferenceDialog()
229+
launch {
230+
scheduleViewModel.signInNavigationActions.collect {
231+
if (it == ShowNotificationPreferencesDialog) {
232+
openNotificationsPreferenceDialog()
233+
}
234234
}
235235
}
236-
)
236+
}
237237

238238
// Show an error message
239239
viewLifecycleOwner.lifecycleScope.launchWhenStarted {

mobile/src/main/java/com/google/samples/apps/iosched/ui/schedule/ScheduleViewModel.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ class ScheduleViewModel @Inject constructor(
128128
}
129129

130130
// Latest user ID
131-
private val userId = observeUserId().stateIn(viewModelScope, WhileViewSubscribed, null)
131+
private val currentUserId = userId.stateIn(viewModelScope, WhileViewSubscribed, null)
132132

133133
// Refresh sessions when needed and when the user changes
134134
private val loadSessionsResult: StateFlow<Result<LoadScheduleUserSessionsResult>> =
135-
loadDataSignal.combineTransform(userId) { _, userId ->
135+
loadDataSignal.combineTransform(currentUserId) { _, userId ->
136136
emitAll(
137137
loadScheduleUserSessionsUseCase(
138138
LoadScheduleUserSessionsParameters(userId)
@@ -260,7 +260,7 @@ class ScheduleViewModel @Inject constructor(
260260
}
261261

262262
override fun onStarClicked(userSession: UserSession) {
263-
if (!isSignedIn()) {
263+
if (!isUserSignedInValue) {
264264
Timber.d("Showing Sign-in dialog after star click")
265265
_navigationActions.tryOffer(ScheduleNavigationAction.NavigateToSignInDialogAction)
266266
return
@@ -287,7 +287,7 @@ class ScheduleViewModel @Inject constructor(
287287
)
288288

289289
viewModelScope.launch {
290-
userId.value?.let {
290+
currentUserId.value?.let {
291291
val result = starEventUseCase(
292292
StarEventParameter(
293293
it,

mobile/src/main/java/com/google/samples/apps/iosched/ui/search/SearchViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class SearchViewModel @Inject constructor(
108108
// Re-execute search when signed in user changes.
109109
// Required because we show star / reservation status.
110110
viewModelScope.launch {
111-
currentUserInfoFlow.collect {
111+
userInfo.collect {
112112
executeSearch()
113113
}
114114
}
@@ -139,7 +139,7 @@ class SearchViewModel @Inject constructor(
139139
delay(500)
140140
trace("search-path-viewmodel") {
141141
searchUseCase(
142-
SessionSearchUseCaseParams(getUserId(), textQuery, filters)
142+
SessionSearchUseCaseParams(userIdValue, textQuery, filters)
143143
).collect {
144144
processSearchResult(it)
145145
}

0 commit comments

Comments
 (0)