ultrasonic-app-subsonic-and.../ultrasonic/src/main/kotlin/org/moire/ultrasonic/fragment/GenericListModel.kt

126 lines
3.8 KiB
Kotlin
Raw Normal View History

package org.moire.ultrasonic.fragment
import android.app.Application
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ServerSetting
import org.moire.ultrasonic.domain.MusicFolder
import org.moire.ultrasonic.service.MusicService
import org.moire.ultrasonic.service.MusicServiceFactory
import org.moire.ultrasonic.util.CommunicationError
import org.moire.ultrasonic.util.Settings
/**
* An abstract Model, which can be extended to retrieve a list of items from the API
*/
open class GenericListModel(application: Application) :
AndroidViewModel(application), KoinComponent {
val activeServerProvider: ActiveServerProvider by inject()
val activeServer: ServerSetting
get() = activeServerProvider.getActiveServer()
val context: Context
get() = getApplication<Application>().applicationContext
var currentListIsSortable = true
var showHeader = true
@Suppress("UNUSED_PARAMETER")
open fun showSelectFolderHeader(args: Bundle?): Boolean {
return true
}
internal val musicFolders: MutableLiveData<List<MusicFolder>> = MutableLiveData(listOf())
/**
* Helper function to check online status
*/
fun isOffline(): Boolean {
return ActiveServerProvider.isOffline()
}
/**
* Refreshes the cached items from the server
*/
fun refresh(swipe: SwipeRefreshLayout, bundle: Bundle?) {
backgroundLoadFromServer(true, swipe, bundle ?: Bundle())
}
/**
* Trigger a load() and notify the UI that we are loading
*/
fun backgroundLoadFromServer(
refresh: Boolean,
swipe: SwipeRefreshLayout,
bundle: Bundle = Bundle()
) {
viewModelScope.launch {
swipe.isRefreshing = true
loadFromServer(refresh, swipe, bundle)
swipe.isRefreshing = false
}
}
/**
* Calls the load() function with error handling
*/
suspend fun loadFromServer(refresh: Boolean, swipe: SwipeRefreshLayout, bundle: Bundle) =
withContext(Dispatchers.IO) {
val musicService = MusicServiceFactory.getMusicService()
val isOffline = ActiveServerProvider.isOffline()
val useId3Tags = Settings.shouldUseId3Tags
try {
load(isOffline, useId3Tags, musicService, refresh, bundle)
} catch (all: Exception) {
handleException(all, swipe.context)
}
}
private fun handleException(exception: Exception, context: Context) {
Handler(Looper.getMainLooper()).post {
CommunicationError.handleError(exception, context)
}
}
/**
* This is the central function you need to implement if you want to extend this class
*/
open fun load(
isOffline: Boolean,
useId3Tags: Boolean,
musicService: MusicService,
refresh: Boolean,
args: Bundle
) {
// Update the list of available folders if enabled
if (showSelectFolderHeader(args) && !isOffline && !useId3Tags) {
musicFolders.postValue(
musicService.getMusicFolders(refresh)
)
}
}
/**
* Retrieves the available Music Folders in a LiveData
*/
fun getMusicFolders(): LiveData<List<MusicFolder>> {
return musicFolders
}
}