diff --git a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainActivity.kt b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainActivity.kt index 28736d8c..a37a7fc6 100644 --- a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainActivity.kt +++ b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainActivity.kt @@ -150,6 +150,7 @@ fun MainScreen( user = user, onSignInClick = onSignInClick, onSignOutClick = onSignOutClick, + onRefreshClick = viewModel::refresh ) } diff --git a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainViewModel.kt b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainViewModel.kt index 5de33d2c..b3c9e41b 100644 --- a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainViewModel.kt +++ b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/main/MainViewModel.kt @@ -17,12 +17,16 @@ import fr.androidmakers.domain.repo.UserRepository import fr.paug.androidmakers.wear.applicationContext import fr.paug.androidmakers.wear.data.LocalPreferencesRepository import fr.paug.androidmakers.wear.ui.session.UISession +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.consumeAsFlow import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -40,21 +44,24 @@ private val DAY_1_DATE = LocalDate(year = 2024, month = Month.APRIL, dayOfMonth private val DAY_2_DATE = DAY_1_DATE.plus(1, DateTimeUnit.DAY) class MainViewModel( - application: Application, - private val userRepository: UserRepository, - localPreferencesRepository: LocalPreferencesRepository, - getAgendaUseCase: GetAgendaUseCase, - private val syncBookmarksUseCase: SyncBookmarksUseCase, - getFavoriteSessionsUseCase: GetFavoriteSessionsUseCase, + application: Application, + private val userRepository: UserRepository, + localPreferencesRepository: LocalPreferencesRepository, + getAgendaUseCase: GetAgendaUseCase, + private val syncBookmarksUseCase: SyncBookmarksUseCase, + getFavoriteSessionsUseCase: GetFavoriteSessionsUseCase, ) : AndroidViewModel(application) { private val _user = MutableStateFlow(null) val user: StateFlow = _user + private val refreshSignal = Channel() + init { viewModelScope.launch { _user.emit(userRepository.getUser()) maybeSyncBookmarks() + refreshSignal.send(Unit) } } @@ -67,24 +74,28 @@ class MainViewModel( } } - private val sessions: Flow?> = getAgendaUseCase() - .filter { it.isSuccess } - .map { it.getOrThrow() } - .combine(getFavoriteSessionsUseCase()) { agenda, favoriteSessions -> - agenda.toUISessions(favoriteSessions) - } - .combine(localPreferencesRepository.showOnlyBookmarkedSessions) { sessions, showOnlyBookmarked -> - if (showOnlyBookmarked) { - sessions.filter { it.isBookmarked } - } else { - sessions - } + @OptIn(ExperimentalCoroutinesApi::class) + private val sessions: Flow?> = refreshSignal.consumeAsFlow() + .flatMapLatest { getAgendaUseCase() } + .filter { it.isSuccess } + .map { it.getOrThrow() } + .combine(getFavoriteSessionsUseCase()) { agenda, favoriteSessions -> + agenda.toUISessions(favoriteSessions) + } + .combine(localPreferencesRepository.showOnlyBookmarkedSessions) { sessions, showOnlyBookmarked -> + if (showOnlyBookmarked) { + sessions.filter { it.isBookmarked } + } else { + sessions } - .stateIn(viewModelScope, SharingStarted.Lazily, null) + } + .stateIn(viewModelScope, SharingStarted.Lazily, null) - val sessionsDay1 = sessions.map { sessions -> sessions?.filter { it.session.startsAt.date == DAY_1_DATE } } + val sessionsDay1 = + sessions.map { sessions -> sessions?.filter { it.session.startsAt.date == DAY_1_DATE } } - val sessionsDay2 = sessions.map { sessions -> sessions?.filter { it.session.startsAt.date == DAY_2_DATE } } + val sessionsDay2 = + sessions.map { sessions -> sessions?.filter { it.session.startsAt.date == DAY_2_DATE } } /** * Get the day of the conference, based on the current date. @@ -107,33 +118,40 @@ class MainViewModel( fun signOut() { val googleSignInClient = GoogleSignIn.getClient( - applicationContext, - GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestIdToken("985196411897-r7edbi9jgo3hfupekcmdrg66inonj0o5.apps.googleusercontent.com") - .build() + applicationContext, + GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken("985196411897-r7edbi9jgo3hfupekcmdrg66inonj0o5.apps.googleusercontent.com") + .build() ) googleSignInClient.signOut() googleSignInClient.revokeAccess() Firebase.auth.signOut() _user.value = null } + + fun refresh() { + viewModelScope.launch { + maybeSyncBookmarks() + refreshSignal.send(Unit) + } + } } private fun Agenda.toUISessions(favoriteSessions: Set): List { return sessions.values.mapNotNull { session -> UISession( - session = session, - speakers = session.speakers.map { - speakers[it] ?: run { - Log.d(TAG, "Speaker $it not found") - return@mapNotNull null - } - }, - room = rooms[session.roomId] ?: run { - Log.d(TAG, "Room ${session.roomId} not found") + session = session, + speakers = session.speakers.map { + speakers[it] ?: run { + Log.d(TAG, "Speaker $it not found") return@mapNotNull null - }, - isBookmarked = session.id in favoriteSessions, + } + }, + room = rooms[session.roomId] ?: run { + Log.d(TAG, "Room ${session.roomId} not found") + return@mapNotNull null + }, + isBookmarked = session.id in favoriteSessions, ) } } diff --git a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/settings/SettingsScreen.kt b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/settings/SettingsScreen.kt index a8bcc679..8169f7b4 100644 --- a/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/settings/SettingsScreen.kt +++ b/wearApp/src/main/java/fr/paug/androidmakers/wear/ui/settings/SettingsScreen.kt @@ -35,6 +35,7 @@ fun SettingsScreen( user: User?, onSignInClick: () -> Unit, onSignOutClick: () -> Unit, + onRefreshClick: () -> Unit, ) { var showSignOutConfirmDialog by remember { mutableStateOf(false) } val columnState = rememberResponsiveColumnState( @@ -48,6 +49,14 @@ fun SettingsScreen( columnState = columnState, modifier = Modifier.fillMaxSize() ) { + item { + Chip( + modifier = Modifier.fillMaxWidth(), + label = { Text(stringResource(R.string.settings_refresh)) }, + onClick = onRefreshClick + ) + } + item { if (user == null) { Chip( @@ -133,5 +142,6 @@ private fun SettingsScreenPreview() { user = null, onSignInClick = {}, onSignOutClick = {}, + onRefreshClick = {}, ) } diff --git a/wearApp/src/main/res/values-fr/strings.xml b/wearApp/src/main/res/values-fr/strings.xml index b2586f2e..1cba20c2 100644 --- a/wearApp/src/main/res/values-fr/strings.xml +++ b/wearApp/src/main/res/values-fr/strings.xml @@ -8,4 +8,5 @@ Déconnexion Sessions favorites seulement Se déconnecter ? + Rafraîchir diff --git a/wearApp/src/main/res/values/strings.xml b/wearApp/src/main/res/values/strings.xml index 421a0602..45796766 100644 --- a/wearApp/src/main/res/values/strings.xml +++ b/wearApp/src/main/res/values/strings.xml @@ -10,4 +10,5 @@ Sign out Show favorites only Sign out? + Refresh