Skip to content

Commit 7e15e37

Browse files
committed
in conv list: show loading spinner as long as request is running
Problem The shimmer loading skeleton (and the pull-to-refresh spinner) were dismissed after the first emission from the local Room database — even if that emission was an empty list. The network fetch still running in the background was invisible to the user, causing an empty-state flash followed by the actual data appearing. Changes ConversationsListViewModel.kt Removed _isShimmerVisible: MutableStateFlow(true) (which was toggled off prematurely on any DB emission). Added _isLoadingRooms: MutableStateFlow(true) — set to true when getRooms() starts, false only after the repository Job fully completes (both local DB and network sync are done). isShimmerVisible is now a combine of _isLoadingRooms and getRoomsStateFlow: shimmer is visible while loading is in progress AND the room list is still empty. This means: Initial load with no cached data → shimmer stays until the network fetch finishes. Subsequent pull-to-refresh with existing data → shimmer doesn't re-appear (list isn't empty), but the swipe indicator handles that. Moved getRoomsStateFlow declaration before isShimmerVisible to fix initialization order. ConversationsListActivity.kt Removed isRefreshingState.value = false from the GetRoomsSuccessState branch (which fired too early, after the first DB emission). Added a isLoadingRooms collector: isRefreshingState is set to false only when isLoadingRooms becomes false, i.e. after the full load cycle completes. AI-assistant: Github Copilot 1.8.2-243 (Claude Sonnet 4.6) Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
1 parent dfdd453 commit 7e15e37

2 files changed

Lines changed: 30 additions & 11 deletions

File tree

app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,6 @@ class ConversationsListActivity : BaseActivity() {
384384
private fun initObservers() {
385385
conversationsListViewModel.getRoomsViewState.observe(this) { state ->
386386
when (state) {
387-
is ConversationsListViewModel.GetRoomsSuccessState -> {
388-
isRefreshingState.value = false
389-
}
390-
391387
is ConversationsListViewModel.GetRoomsErrorState -> {
392388
isRefreshingState.value = false
393389
handleHttpExceptions(state.throwable)
@@ -397,6 +393,14 @@ class ConversationsListActivity : BaseActivity() {
397393
}
398394
}
399395

396+
lifecycleScope.launch {
397+
conversationsListViewModel.isLoadingRooms.collect { isLoading ->
398+
if (!isLoading) {
399+
isRefreshingState.value = false
400+
}
401+
}
402+
}
403+
400404
lifecycleScope.launch {
401405
conversationsListViewModel.getRoomsFlow
402406
.onEach { list ->

app/src/main/java/com/nextcloud/talk/conversationlist/viewmodels/ConversationsListViewModel.kt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,30 @@ class ConversationsListViewModel @Inject constructor(
139139
_getRoomsViewState.value = GetRoomsErrorState(it)
140140
}
141141

142-
private val _isShimmerVisible = MutableStateFlow(true)
142+
private val _isLoadingRooms = MutableStateFlow(true)
143143

144144
/**
145-
* Drives the shimmer skeleton visibility. Set to false as soon as the first room-list
146-
* emission arrives (same subscription as [getRoomsStateFlow] so it hides in the same
147-
* coroutine step that populates [conversationListEntriesFlow].
145+
* True while a [getRooms] call is in progress (from start until the fetch-Job completes,
146+
* i.e. after both the local-DB and the network-sync emissions have been produced).
148147
*/
149-
val isShimmerVisible: StateFlow<Boolean> = _isShimmerVisible.asStateFlow()
148+
val isLoadingRooms: StateFlow<Boolean> = _isLoadingRooms.asStateFlow()
150149

151150
val getRoomsStateFlow = repository
152151
.roomListFlow
153-
.onEach { _isShimmerVisible.value = false }
154152
.stateIn(viewModelScope, SharingStarted.Eagerly, listOf())
155153

154+
/**
155+
* Drives the shimmer skeleton visibility. Visible while rooms are still being loaded for
156+
* the first time (no data in the list yet). Hidden as soon as either the room list is
157+
* non-empty or the loading job has fully completed.
158+
*/
159+
val isShimmerVisible: StateFlow<Boolean> = combine(
160+
_isLoadingRooms,
161+
getRoomsStateFlow
162+
) { isLoading, rooms ->
163+
isLoading && rooms.isEmpty()
164+
}.stateIn(viewModelScope, SharingStarted.Eagerly, true)
165+
156166
private val _federationInvitationHintVisible = MutableStateFlow(false)
157167
val federationInvitationHintVisible: StateFlow<Boolean> = _federationInvitationHintVisible.asStateFlow()
158168

@@ -406,7 +416,12 @@ class ConversationsListViewModel @Inject constructor(
406416
fun getRooms(user: User) {
407417
val startNanoTime = System.nanoTime()
408418
Log.d(TAG, "fetchData - getRooms - calling: $startNanoTime")
409-
repository.getRooms(user)
419+
_isLoadingRooms.value = true
420+
val job = repository.getRooms(user)
421+
viewModelScope.launch {
422+
job.join()
423+
_isLoadingRooms.value = false
424+
}
410425
}
411426

412427
fun checkIfThreadsExist() {

0 commit comments

Comments
 (0)