diff --git a/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/view/home/locker/Locker.kt b/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/view/home/locker/Locker.kt index 67de94bb..4338e470 100644 --- a/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/view/home/locker/Locker.kt +++ b/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/view/home/locker/Locker.kt @@ -41,18 +41,29 @@ fun Locker(page: LockerTabs, lockerDao: LockerDao = getKoin().get(), viewModel: } } - if (entriesState is LockerViewModel.LockerEntriesState.Loaded) { - when (page) { - LockerTabs.Apps -> { - LockerAppList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) }) - } + when (entriesState) { + is LockerViewModel.LockerEntriesState.Loaded -> { + when (page) { + LockerTabs.Apps -> { + LockerAppList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) }) + } - LockerTabs.Watchfaces -> { - LockerWatchfaceList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) }) + LockerTabs.Watchfaces -> { + LockerWatchfaceList(viewModel, onOpenModalSheet = { viewModel.openModalSheet(it) }) + } + } + } + is LockerViewModel.LockerEntriesState.Error -> { + Text("Error loading locker entries") + Button(onClick = { + viewModel.reloadLocker() + }) { + Text("Retry") } } - } else { - CircularProgressIndicator(modifier = Modifier.align(CenterHorizontally)) + is LockerViewModel.LockerEntriesState.Loading -> { + CircularProgressIndicator(modifier = Modifier.align(CenterHorizontally)) + } } } if (modalSheetState is LockerViewModel.ModalSheetState.Open) { diff --git a/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/viewmodel/LockerViewModel.kt b/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/viewmodel/LockerViewModel.kt index df733a9f..9f2454f7 100644 --- a/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/viewmodel/LockerViewModel.kt +++ b/android/shared/src/commonMain/kotlin/io/rebble/cobble/shared/ui/viewmodel/LockerViewModel.kt @@ -2,6 +2,7 @@ package io.rebble.cobble.shared.ui.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import io.rebble.cobble.shared.Logging import io.rebble.cobble.shared.database.dao.LockerDao import io.rebble.cobble.shared.database.entity.SyncedLockerEntryWithPlatforms import io.rebble.cobble.shared.domain.state.ConnectionStateManager @@ -13,14 +14,20 @@ import kotlinx.coroutines.sync.withLock class LockerViewModel(private val lockerDao: LockerDao): ViewModel() { open class LockerEntriesState { object Loading : LockerEntriesState() + object Error : LockerEntriesState() data class Loaded(val entries: List) : LockerEntriesState() } open class ModalSheetState { object Closed : ModalSheetState() data class Open(val viewModel: LockerItemViewModel) : ModalSheetState() } - val entriesState = lockerDao.getAllEntriesFlow().map { - LockerEntriesState.Loaded(it) + private val entriesFlow = lockerDao.getAllEntriesFlow() + private val reloadFlow = MutableStateFlow(Unit) + val entriesState: StateFlow = combine(entriesFlow, reloadFlow) { entries, _ -> + LockerEntriesState.Loaded(entries) as LockerEntriesState + }.catch { + Logging.e("Error loading locker entries", it) + emit(LockerEntriesState.Error) }.stateIn(viewModelScope + Dispatchers.IO, SharingStarted.Eagerly, LockerEntriesState.Loading) private var mutex = Mutex() @@ -49,4 +56,8 @@ class LockerViewModel(private val lockerDao: LockerDao): ViewModel() { fun closeModalSheet() { _modalSheetState.value = ModalSheetState.Closed } + + fun reloadLocker() { + reloadFlow.value = Unit + } } \ No newline at end of file