108 lines
4.0 KiB
Kotlin
108 lines
4.0 KiB
Kotlin
package emu.skyline
|
|
|
|
import android.content.Context
|
|
import android.net.Uri
|
|
import android.util.Log
|
|
import androidx.documentfile.provider.DocumentFile
|
|
import androidx.lifecycle.LiveData
|
|
import androidx.lifecycle.MutableLiveData
|
|
import androidx.lifecycle.ViewModel
|
|
import androidx.lifecycle.viewModelScope
|
|
import emu.skyline.data.AppItem
|
|
import emu.skyline.data.DataItem
|
|
import emu.skyline.data.HeaderItem
|
|
import emu.skyline.loader.RomFile
|
|
import emu.skyline.loader.RomFormat
|
|
import emu.skyline.utils.loadSerializedList
|
|
import emu.skyline.utils.serialize
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.launch
|
|
import java.io.File
|
|
import java.io.IOException
|
|
|
|
sealed class MainState {
|
|
object Loading : MainState()
|
|
class Loaded(val items : List<DataItem>) : MainState()
|
|
class Error(val ex : Exception) : MainState()
|
|
}
|
|
|
|
class MainViewModel : ViewModel() {
|
|
companion object {
|
|
private val TAG = MainViewModel::class.java.simpleName
|
|
}
|
|
|
|
private val mutableState = MutableLiveData<MainState>()
|
|
val state : LiveData<MainState> = mutableState
|
|
|
|
var searchBarAnimated = false
|
|
|
|
/**
|
|
* This adds all files in [directory] with [extension] as an entry using [RomFile] to load metadata
|
|
*/
|
|
private fun addEntries(context : Context, extension : String, romFormat : RomFormat, directory : DocumentFile, romElements : ArrayList<DataItem>, found : Boolean = false) : Boolean {
|
|
var foundCurrent = found
|
|
|
|
directory.listFiles().forEach { file ->
|
|
if (file.isDirectory) {
|
|
foundCurrent = addEntries(context, extension, romFormat, file, romElements, foundCurrent)
|
|
} else {
|
|
if (extension.equals(file.name?.substringAfterLast("."), ignoreCase = true)) {
|
|
RomFile(context, romFormat, file.uri).let { romFile ->
|
|
if (!foundCurrent) romElements.add(HeaderItem(romFormat.name))
|
|
romElements.add(AppItem(romFile.appEntry))
|
|
|
|
foundCurrent = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return foundCurrent
|
|
}
|
|
|
|
/**
|
|
* This refreshes the contents of the adapter by either trying to load cached adapter data or searches for them to recreate a list
|
|
*
|
|
* @param loadFromFile If this is false then trying to load cached adapter data is skipped entirely
|
|
*/
|
|
fun loadRoms(context : Context, loadFromFile : Boolean, searchLocation : Uri) {
|
|
if (mutableState.value == MainState.Loading) return
|
|
|
|
mutableState.postValue(MainState.Loading)
|
|
|
|
val romsFile = File(context.filesDir.canonicalPath + "/roms.bin")
|
|
|
|
viewModelScope.launch(Dispatchers.IO) {
|
|
if (loadFromFile) {
|
|
try {
|
|
mutableState.postValue(MainState.Loaded(loadSerializedList(romsFile)))
|
|
return@launch
|
|
} catch (e : Exception) {
|
|
Log.w(TAG, "Ran into exception while loading: ${e.message}")
|
|
}
|
|
}
|
|
|
|
try {
|
|
val searchDocument = DocumentFile.fromTreeUri(context, searchLocation)!!
|
|
|
|
val romElements = ArrayList<DataItem>()
|
|
addEntries(context, "nro", RomFormat.NRO, searchDocument, romElements)
|
|
addEntries(context, "nso", RomFormat.NSO, searchDocument, romElements)
|
|
addEntries(context, "nca", RomFormat.NCA, searchDocument, romElements)
|
|
addEntries(context, "xci", RomFormat.XCI, searchDocument, romElements)
|
|
addEntries(context, "nsp", RomFormat.NSP, searchDocument, romElements)
|
|
|
|
try {
|
|
romElements.serialize(romsFile)
|
|
} catch (e : IOException) {
|
|
Log.w(TAG, "Ran into exception while saving: ${e.message}")
|
|
}
|
|
|
|
mutableState.postValue(MainState.Loaded(romElements))
|
|
} catch (e : Exception) {
|
|
mutableState.postValue(MainState.Error(e))
|
|
}
|
|
}
|
|
}
|
|
}
|