From 2a625a4360f10e4cf2d53960d8d99439ab44b3fc Mon Sep 17 00:00:00 2001
From: BoD <BoD@JRAF.org>
Date: Thu, 11 Apr 2024 15:28:27 +0200
Subject: [PATCH] Add a refresh button

---
 .../wear/ui/main/MainActivity.kt              |  1 +
 .../wear/ui/main/MainViewModel.kt             | 90 +++++++++++--------
 .../wear/ui/settings/SettingsScreen.kt        | 10 +++
 wearApp/src/main/res/values-fr/strings.xml    |  1 +
 wearApp/src/main/res/values/strings.xml       |  1 +
 5 files changed, 67 insertions(+), 36 deletions(-)

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<User?>(null)
 
   val user: StateFlow<User?> = _user
 
+  private val refreshSignal = Channel<Unit>()
+
   init {
     viewModelScope.launch {
       _user.emit(userRepository.getUser())
       maybeSyncBookmarks()
+      refreshSignal.send(Unit)
     }
   }
 
@@ -67,24 +74,28 @@ class MainViewModel(
     }
   }
 
-  private val sessions: Flow<List<UISession>?> = 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<List<UISession>?> = 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<String>): List<UISession> {
   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 @@
     <string name="settings_signOut">Déconnexion</string>
     <string name="settings_showBookmarksOnly">Sessions favorites seulement</string>
     <string name="settings_signOutConfirm">Se déconnecter ?</string>
+    <string name="settings_refresh">Rafraîchir</string>
 </resources>
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 @@
     <string name="settings_signOut">Sign out</string>
     <string name="settings_showBookmarksOnly">Show favorites only</string>
     <string name="settings_signOutConfirm">Sign out?</string>
+    <string name="settings_refresh">Refresh</string>
 </resources>