From ecbe98f9e410512d42556d224aedb61de72b6d16 Mon Sep 17 00:00:00 2001 From: Christophe Beyls Date: Sat, 2 May 2020 00:46:14 +0200 Subject: [PATCH] combine download schedule progress and result into LoadingState --- .../fosdem/activities/MainActivity.kt | 83 ++++++++++--------- .../java/be/digitalia/fosdem/api/FosdemApi.kt | 35 +++----- .../be/digitalia/fosdem/model/LoadingState.kt | 13 +++ 3 files changed, 68 insertions(+), 63 deletions(-) create mode 100644 app/src/main/java/be/digitalia/fosdem/model/LoadingState.kt diff --git a/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.kt b/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.kt index e9c096d..9d3e408 100644 --- a/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.kt +++ b/app/src/main/java/be/digitalia/fosdem/activities/MainActivity.kt @@ -37,6 +37,7 @@ import be.digitalia.fosdem.api.FosdemUrls import be.digitalia.fosdem.db.AppDatabase import be.digitalia.fosdem.fragments.* import be.digitalia.fosdem.model.DownloadScheduleResult +import be.digitalia.fosdem.model.LoadingState import be.digitalia.fosdem.utils.* import be.digitalia.fosdem.widgets.FadeOutViewMediator import com.google.android.material.navigation.NavigationView @@ -95,50 +96,52 @@ class MainActivity : AppCompatActivity(R.layout.main), CreateNfcAppDataCallback // Progress bar setup val progressBar: ProgressBar = findViewById(R.id.progress) val progressBarMediator = FadeOutViewMediator(progressBar) - FosdemApi.downloadScheduleProgress.observe(this) { progressValue -> - if (progressValue != 100) { - // Visible - progressBarMediator.isVisible = true - with(progressBar) { - if (progressValue == -1) { - isIndeterminate = true - } else { - isIndeterminate = false - progress = progressValue - } - } - } else { - // Invisible - progressBarMediator.isVisible = false - with(progressBar) { - isIndeterminate = false - progress = 100 - } - } - } - // Monitor the schedule download result - FosdemApi.downloadScheduleResult.observe(this) { singleEvent -> - val result = singleEvent.consume() ?: return@observe - val snackbar = when (result) { - is DownloadScheduleResult.Error -> { - Snackbar.make(contentView, R.string.schedule_loading_error, ERROR_MESSAGE_DISPLAY_DURATION) - .setAction(R.string.schedule_loading_retry_action) { FosdemApi.downloadSchedule(this) } - } - is DownloadScheduleResult.UpToDate -> { - Snackbar.make(contentView, R.string.events_download_up_to_date, Snackbar.LENGTH_LONG) - } - is DownloadScheduleResult.Success -> { - val eventsCount = result.eventsCount - val message = if (eventsCount == 0) { - getString(R.string.events_download_empty) - } else { - resources.getQuantityString(R.plurals.events_download_completed, eventsCount, eventsCount) + // Monitor the schedule download + FosdemApi.downloadScheduleState.observe(this) { state -> + when (state) { + is LoadingState.Loading -> { + progressBarMediator.isVisible = true + with(progressBar) { + val progressValue = state.progress + if (progressValue == -1) { + isIndeterminate = true + } else { + isIndeterminate = false + progress = progressValue + } + } + } + is LoadingState.Idle -> { + progressBarMediator.isVisible = false + with(progressBar) { + isIndeterminate = false + progress = 100 + } + + state.result.consume()?.let { result -> + val snackbar = when (result) { + is DownloadScheduleResult.Error -> { + Snackbar.make(contentView, R.string.schedule_loading_error, ERROR_MESSAGE_DISPLAY_DURATION) + .setAction(R.string.schedule_loading_retry_action) { FosdemApi.downloadSchedule(this) } + } + is DownloadScheduleResult.UpToDate -> { + Snackbar.make(contentView, R.string.events_download_up_to_date, Snackbar.LENGTH_LONG) + } + is DownloadScheduleResult.Success -> { + val eventsCount = result.eventsCount + val message = if (eventsCount == 0) { + getString(R.string.events_download_empty) + } else { + resources.getQuantityString(R.plurals.events_download_completed, eventsCount, eventsCount) + } + Snackbar.make(contentView, message, Snackbar.LENGTH_LONG) + } + } + snackbar.show() } - Snackbar.make(contentView, message, Snackbar.LENGTH_LONG) } } - snackbar.show() } // Setup drawer layout diff --git a/app/src/main/java/be/digitalia/fosdem/api/FosdemApi.kt b/app/src/main/java/be/digitalia/fosdem/api/FosdemApi.kt index f6da9b5..b5d789a 100644 --- a/app/src/main/java/be/digitalia/fosdem/api/FosdemApi.kt +++ b/app/src/main/java/be/digitalia/fosdem/api/FosdemApi.kt @@ -13,6 +13,7 @@ import be.digitalia.fosdem.db.AppDatabase import be.digitalia.fosdem.livedata.LiveDataFactory.scheduler import be.digitalia.fosdem.livedata.SingleEvent import be.digitalia.fosdem.model.DownloadScheduleResult +import be.digitalia.fosdem.model.LoadingState import be.digitalia.fosdem.model.RoomStatus import be.digitalia.fosdem.parsers.EventsParser import be.digitalia.fosdem.parsers.RoomStatusesParser @@ -42,8 +43,7 @@ object FosdemApi { private const val ROOM_STATUS_EXPIRATION_DELAY = 6L * DateUtils.MINUTE_IN_MILLIS private var downloadJob: Job? = null - private val _downloadScheduleProgress = MutableLiveData() - private val _downloadScheduleResult = MutableLiveData>() + private val _downloadScheduleState = MutableLiveData>() private var roomStatuses: LiveData>? = null /** @@ -67,7 +67,7 @@ object FosdemApi { @MainThread private suspend fun downloadScheduleInternal(context: Context) { - _downloadScheduleProgress.value = -1 + _downloadScheduleState.value = LoadingState.Loading() val res = try { val scheduleDao = AppDatabase.getInstance(context).scheduleDao val response = HttpUtils.get(FosdemUrls.schedule, scheduleDao.lastModifiedTag) { body, rawResponse -> @@ -77,7 +77,7 @@ object FosdemApi { ByteCountSource(body.source(), length / 10L) { byteCount -> // Cap percent to 100 val percent = (byteCount * 100L / length).toInt().coerceAtMost(100) - _downloadScheduleProgress.postValue(percent) + _downloadScheduleState.postValue(LoadingState.Loading(percent)) }.buffer() } else { body.source() @@ -87,31 +87,20 @@ object FosdemApi { scheduleDao.storeSchedule(events, rawResponse.lastModified) } when (response) { - is HttpUtils.Response.NotModified -> DownloadScheduleResult.UpToDate // Nothing to parse, the result is up-to-date - is HttpUtils.Response.Success -> DownloadScheduleResult.Success(response.body) + is HttpUtils.Response.NotModified -> DownloadScheduleResult.UpToDate // Nothing parsed, the result is up-to-date + is HttpUtils.Response.Success -> { + FosdemAlarmManager.onScheduleRefreshed() + DownloadScheduleResult.Success(response.body) + } } } catch (e: Exception) { DownloadScheduleResult.Error } - _downloadScheduleProgress.value = 100 - - if (res is DownloadScheduleResult.Success) { - FosdemAlarmManager.onScheduleRefreshed() - } - _downloadScheduleResult.value = SingleEvent(res) + _downloadScheduleState.value = LoadingState.Idle(SingleEvent(res)) } - /** - * @return The current schedule download progress: - * -1 : in progress, indeterminate - * 0..99: progress value - * 100 : download complete or inactive - */ - val downloadScheduleProgress: LiveData - get() = _downloadScheduleProgress - - val downloadScheduleResult: LiveData> - get() = _downloadScheduleResult + val downloadScheduleState: LiveData> + get() = _downloadScheduleState @MainThread fun getRoomStatuses(context: Context): LiveData> { diff --git a/app/src/main/java/be/digitalia/fosdem/model/LoadingState.kt b/app/src/main/java/be/digitalia/fosdem/model/LoadingState.kt new file mode 100644 index 0000000..d408764 --- /dev/null +++ b/app/src/main/java/be/digitalia/fosdem/model/LoadingState.kt @@ -0,0 +1,13 @@ +package be.digitalia.fosdem.model + +import be.digitalia.fosdem.livedata.SingleEvent + +sealed class LoadingState { + /** + * The current download progress: + * -1 : in progress, indeterminate + * 0..99: progress value in percents + */ + class Loading(val progress: Int = -1) : LoadingState() + class Idle(val result: SingleEvent) : LoadingState() +} \ No newline at end of file