Twelve: VM housekeeping
* Reorder code
* Add missing flowOn and stateIn
* Make sure all flows that uses RequestStatus use non-null values
Change-Id: If3693ff54386d4d2d7872573f7762f64fffdfe8c
diff --git a/app/src/main/java/org/lineageos/twelve/ext/LinearProgressIndicator.kt b/app/src/main/java/org/lineageos/twelve/ext/LinearProgressIndicator.kt
index 6e6a78e..c533b1c 100644
--- a/app/src/main/java/org/lineageos/twelve/ext/LinearProgressIndicator.kt
+++ b/app/src/main/java/org/lineageos/twelve/ext/LinearProgressIndicator.kt
@@ -12,18 +12,9 @@
* @see LinearProgressIndicator.setProgressCompat
*/
fun <T : Any> LinearProgressIndicator.setProgressCompat(
- status: RequestStatus<T>?, animated: Boolean
+ status: RequestStatus<T>, animated: Boolean
) {
when (status) {
- null -> {
- if (!isIndeterminate) {
- hide()
- isIndeterminate = true
- }
-
- show()
- }
-
is RequestStatus.Loading -> {
status.progress?.also {
setProgressCompat(it, animated)
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
index c7a2183..b804736 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/AlbumFragment.kt
@@ -139,13 +139,6 @@
linearProgressIndicator.setProgressCompat(it, true)
when (it) {
- null -> {
- adapter.submitList(listOf())
-
- recyclerView.isVisible = false
- noElementsNestedScrollView.isVisible = false
- }
-
is RequestStatus.Loading -> {
// Do nothing
}
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/ArtistFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/ArtistFragment.kt
index 01c5078..49ba900 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/ArtistFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/ArtistFragment.kt
@@ -150,10 +150,6 @@
linearProgressIndicator.setProgressCompat(it, true)
when (it) {
- null -> {
- // Do nothing
- }
-
is RequestStatus.Loading -> {
// Do nothing
}
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/AudioBottomSheetDialogFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/AudioBottomSheetDialogFragment.kt
index d62924e..4d5c294 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/AudioBottomSheetDialogFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/AudioBottomSheetDialogFragment.kt
@@ -98,10 +98,6 @@
private suspend fun loadData() {
viewModel.audio.collect {
when (it) {
- null -> {
- // Do nothing
- }
-
is RequestStatus.Loading -> {
// Do nothing
}
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
index 981dc1c..19b7084 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/PlaylistFragment.kt
@@ -152,13 +152,6 @@
linearProgressIndicator.setProgressCompat(it, true)
when (it) {
- null -> {
- adapter.submitList(listOf())
-
- recyclerView.isVisible = false
- noElementsNestedScrollView.isVisible = false
- }
-
is RequestStatus.Loading -> {
// Do nothing
}
diff --git a/app/src/main/java/org/lineageos/twelve/fragments/SearchFragment.kt b/app/src/main/java/org/lineageos/twelve/fragments/SearchFragment.kt
index 8ac6481..6663985 100644
--- a/app/src/main/java/org/lineageos/twelve/fragments/SearchFragment.kt
+++ b/app/src/main/java/org/lineageos/twelve/fragments/SearchFragment.kt
@@ -171,13 +171,6 @@
linearProgressIndicator.setProgressCompat(it, true)
when (it) {
- null -> {
- adapter.submitList(listOf())
-
- recyclerView.isVisible = false
- noElementsLinearLayout.isVisible = false
- }
-
is RequestStatus.Loading -> {
// Do nothing
}
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/AddOrRemoveFromPlaylistsViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/AddOrRemoveFromPlaylistsViewModel.kt
index c98df8f..bffbdd2 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/AddOrRemoveFromPlaylistsViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/AddOrRemoveFromPlaylistsViewModel.kt
@@ -18,9 +18,11 @@
class AddOrRemoveFromPlaylistsViewModel(application: Application) : AudioViewModel(application) {
@OptIn(ExperimentalCoroutinesApi::class)
- val playlistToHasAudio = audioUri.filterNotNull().flatMapLatest {
- mediaRepository.audioPlaylistsStatus(it)
- }
+ val playlistToHasAudio = audioUri
+ .filterNotNull()
+ .flatMapLatest {
+ mediaRepository.audioPlaylistsStatus(it)
+ }
.flowOn(Dispatchers.IO)
.stateIn(
viewModelScope,
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
index 95908be..8a99120 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/AlbumViewModel.kt
@@ -12,25 +12,26 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
+import org.lineageos.twelve.models.RequestStatus
class AlbumViewModel(application: Application) : TwelveViewModel(application) {
private val albumUri = MutableStateFlow<Uri?>(null)
@OptIn(ExperimentalCoroutinesApi::class)
- val album = albumUri.flatMapLatest {
- it?.let {
+ val album = albumUri
+ .filterNotNull()
+ .flatMapLatest {
mediaRepository.album(it)
- } ?: flowOf(null)
- }
+ }
.flowOn(Dispatchers.IO)
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
- null
+ RequestStatus.Loading()
)
fun loadAlbum(albumUri: Uri) {
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/ArtistViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/ArtistViewModel.kt
index 934a8fb..830715e 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/ArtistViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/ArtistViewModel.kt
@@ -12,25 +12,26 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
+import org.lineageos.twelve.models.RequestStatus
class ArtistViewModel(application: Application) : TwelveViewModel(application) {
private val artistUri = MutableStateFlow<Uri?>(null)
@OptIn(ExperimentalCoroutinesApi::class)
- val artist = artistUri.flatMapLatest {
- it?.let {
+ val artist = artistUri
+ .filterNotNull()
+ .flatMapLatest {
mediaRepository.artist(it)
- } ?: flowOf(null)
- }
+ }
.flowOn(Dispatchers.IO)
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
- null
+ RequestStatus.Loading()
)
fun loadAlbum(artistUri: Uri) {
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/AudioViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/AudioViewModel.kt
index ae86333..75cf379 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/AudioViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/AudioViewModel.kt
@@ -12,26 +12,27 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
+import org.lineageos.twelve.models.RequestStatus
open class AudioViewModel(application: Application) : TwelveViewModel(application) {
protected val audioUri = MutableStateFlow<Uri?>(null)
@OptIn(ExperimentalCoroutinesApi::class)
- val audio = audioUri.flatMapLatest {
- it?.let {
+ val audio = audioUri
+ .filterNotNull()
+ .flatMapLatest {
mediaRepository.audio(it)
- } ?: flowOf(null)
- }
+ }
.flowOn(Dispatchers.IO)
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
- null
+ RequestStatus.Loading()
)
fun loadAudio(audioUri: Uri) {
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
index 2246669..31e8563 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/PlaylistViewModel.kt
@@ -12,26 +12,27 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
+import org.lineageos.twelve.models.RequestStatus
class PlaylistViewModel(application: Application) : TwelveViewModel(application) {
private val playlistUri = MutableStateFlow<Uri?>(null)
@OptIn(ExperimentalCoroutinesApi::class)
- val playlist = playlistUri.flatMapLatest {
- it?.let {
+ val playlist = playlistUri
+ .filterNotNull()
+ .flatMapLatest {
mediaRepository.playlist(it)
- } ?: flowOf(null)
- }
+ }
.flowOn(Dispatchers.IO)
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
- null
+ RequestStatus.Loading()
)
fun loadPlaylist(playlistUri: Uri) {
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/SearchViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/SearchViewModel.kt
index 744f655..f3f56e2 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/SearchViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/SearchViewModel.kt
@@ -6,15 +6,21 @@
package org.lineageos.twelve.viewmodels
import android.app.Application
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapLatest
+import kotlinx.coroutines.flow.stateIn
+import org.lineageos.twelve.models.RequestStatus
class SearchViewModel(application: Application) : TwelveViewModel(application) {
- private val searchQuery = MutableStateFlow<String?>(null)
+ private val searchQuery = MutableStateFlow("")
@OptIn(ExperimentalCoroutinesApi::class)
val searchResults = searchQuery
@@ -23,12 +29,18 @@
it
}
.flatMapLatest { query ->
- query?.trim()?.takeIf { it.isNotEmpty() }?.let {
+ query.trim().takeIf { it.isNotEmpty() }?.let {
mediaRepository.search("%${it}%")
- } ?: flowOf(null)
+ } ?: flowOf(RequestStatus.Success(listOf()))
}
+ .flowOn(Dispatchers.IO)
+ .stateIn(
+ viewModelScope,
+ SharingStarted.WhileSubscribed(),
+ RequestStatus.Loading()
+ )
- fun setSearchQuery(query: String?) {
+ fun setSearchQuery(query: String) {
searchQuery.value = query
}
}
diff --git a/app/src/main/java/org/lineageos/twelve/viewmodels/TwelveViewModel.kt b/app/src/main/java/org/lineageos/twelve/viewmodels/TwelveViewModel.kt
index 8831f7a..198d742 100644
--- a/app/src/main/java/org/lineageos/twelve/viewmodels/TwelveViewModel.kt
+++ b/app/src/main/java/org/lineageos/twelve/viewmodels/TwelveViewModel.kt
@@ -82,7 +82,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val mediaMetadata = mediaController.filterNotNull()
+ val mediaMetadata = mediaController
+ .filterNotNull()
.flatMapLatest { it.mediaMetadataFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -92,7 +93,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val mediaItem = mediaController.filterNotNull()
+ val mediaItem = mediaController
+ .filterNotNull()
.flatMapLatest { it.mediaItemFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -102,7 +104,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val isPlaying = mediaController.filterNotNull()
+ val isPlaying = mediaController
+ .filterNotNull()
.flatMapLatest { it.isPlayingFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -112,7 +115,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val shuffleMode = mediaController.filterNotNull()
+ val shuffleMode = mediaController
+ .filterNotNull()
.flatMapLatest { it.shuffleModeFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -122,7 +126,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val repeatMode = mediaController.filterNotNull()
+ val repeatMode = mediaController
+ .filterNotNull()
.flatMapLatest { it.repeatModeFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -132,7 +137,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val playbackParameters = mediaController.filterNotNull()
+ val playbackParameters = mediaController
+ .filterNotNull()
.flatMapLatest { it.playbackParametersFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -143,7 +149,8 @@
@androidx.annotation.OptIn(UnstableApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
- val currentTrackFormat = mediaController.filterNotNull()
+ val currentTrackFormat = mediaController
+ .filterNotNull()
.flatMapLatest { it.tracksFlow() }
.flowOn(Dispatchers.Main)
.mapLatest { tracks ->
@@ -169,18 +176,17 @@
initialValue = null
)
- val mimeType =
- combine(currentTrackFormat, mediaItem) { format, mediaItem ->
- format?.sampleMimeType
- ?: format?.containerMimeType
- ?: mediaItem?.localConfiguration?.mimeType
- }
- .flowOn(Dispatchers.IO)
- .stateIn(
- viewModelScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = null
- )
+ val mimeType = combine(currentTrackFormat, mediaItem) { format, mediaItem ->
+ format?.sampleMimeType
+ ?: format?.containerMimeType
+ ?: mediaItem?.localConfiguration?.mimeType
+ }
+ .flowOn(Dispatchers.IO)
+ .stateIn(
+ viewModelScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = null
+ )
@androidx.annotation.OptIn(UnstableApi::class)
@OptIn(ExperimentalCoroutinesApi::class)
@@ -202,7 +208,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- fun availableCommands() = mediaController.filterNotNull()
+ fun availableCommands() = mediaController
+ .filterNotNull()
.flatMapLatest { it.availableCommandsFlow() }
.flowOn(Dispatchers.Main)
.stateIn(
@@ -212,7 +219,8 @@
)
@OptIn(ExperimentalCoroutinesApi::class)
- val durationCurrentPositionMs = mediaController.filterNotNull()
+ val durationCurrentPositionMs = mediaController
+ .filterNotNull()
.flatMapLatest { mediaController ->
flow {
while (true) {