UI: enrich ModelManagementState; extract filename to show correct importing UI
This commit is contained in:
parent
adfbfe3ffb
commit
025e3d2417
|
|
@ -1,12 +1,18 @@
|
||||||
package com.example.llama.revamp.viewmodel
|
package com.example.llama.revamp.viewmodel
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.example.llama.revamp.data.model.ModelInfo
|
import com.example.llama.revamp.data.model.ModelInfo
|
||||||
import com.example.llama.revamp.data.repository.ModelRepository
|
import com.example.llama.revamp.data.repository.ModelRepository
|
||||||
import com.example.llama.revamp.data.repository.StorageMetrics
|
import com.example.llama.revamp.data.repository.StorageMetrics
|
||||||
|
import com.example.llama.revamp.util.getFileNameFromUri
|
||||||
|
import com.example.llama.revamp.util.getFileSizeFromUri
|
||||||
|
import com.example.llama.revamp.viewmodel.ModelManagementState.Deletion
|
||||||
|
import com.example.llama.revamp.viewmodel.ModelManagementState.Importation
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
|
@ -15,10 +21,12 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.io.FileNotFoundException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ModelsManagementViewModel @Inject constructor(
|
class ModelsManagementViewModel @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
private val modelRepository: ModelRepository
|
private val modelRepository: ModelRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
|
@ -66,44 +74,36 @@ class ModelsManagementViewModel @Inject constructor(
|
||||||
// TODO-han.yin: Stub for now. Would navigate to model details screen or show dialog
|
// TODO-han.yin: Stub for now. Would navigate to model details screen or show dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteModel(modelId: String) =
|
private val _managementState = MutableStateFlow<ModelManagementState>(ModelManagementState.Idle)
|
||||||
viewModelScope.launch {
|
val managementState: StateFlow<ModelManagementState> = _managementState.asStateFlow()
|
||||||
modelRepository.deleteModel(modelId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteModels(models: Map<String, ModelInfo>) =
|
fun resetManagementState() {
|
||||||
viewModelScope.launch {
|
_managementState.value = ModelManagementState.Idle
|
||||||
modelRepository.deleteModels(models.keys.toList())
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private val _importState = MutableStateFlow<ModelImportState>(ModelImportState.Idle)
|
|
||||||
val importState: StateFlow<ModelImportState> = _importState.asStateFlow()
|
|
||||||
|
|
||||||
fun importLocalModel(uri: Uri) =
|
fun importLocalModel(uri: Uri) =
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
// Get filename for progress updates
|
val fileName = getFileNameFromUri(context, uri) ?: throw FileNotFoundException("File size N/A")
|
||||||
val filename = uri.lastPathSegment ?: throw Exception("Model name unknown")
|
val fileSize = getFileSizeFromUri(context, uri) ?: throw FileNotFoundException("File name N/A")
|
||||||
_importState.value = ModelImportState.Importing(0f, filename)
|
_managementState.value = Importation.Importing(0f, fileName)
|
||||||
|
|
||||||
// Import with progress reporting
|
// Import with progress reporting
|
||||||
val model = modelRepository.importModel(uri) { progress ->
|
val model = modelRepository.importModel(uri, fileName, fileSize) { progress ->
|
||||||
_importState.value = ModelImportState.Importing(progress, filename)
|
_managementState.value = Importation.Importing(progress, fileName)
|
||||||
}
|
}
|
||||||
_importState.value = ModelImportState.Success(model)
|
_managementState.value = Importation.Success(model)
|
||||||
|
|
||||||
// Reset state after a delay
|
// Reset state after a delay
|
||||||
delay(1000)
|
delay(SUCCESS_RESET_TIMEOUT_MS)
|
||||||
_importState.value = ModelImportState.Idle
|
_managementState.value = ModelManagementState.Idle
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
_importState.value = ModelImportState.Error(e.message ?: "Unknown error")
|
_managementState.value = Importation.Error(
|
||||||
|
message = e.message ?: "Unknown error importing $uri",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetImportState() {
|
|
||||||
_importState.value = ModelImportState.Idle
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importFromHuggingFace() {
|
fun importFromHuggingFace() {
|
||||||
// TODO-han.yin: Stub for now. Would need to investigate HuggingFace APIs
|
// TODO-han.yin: Stub for now. Would need to investigate HuggingFace APIs
|
||||||
}
|
}
|
||||||
|
|
@ -112,6 +112,7 @@ class ModelsManagementViewModel @Inject constructor(
|
||||||
private val TAG = ModelsManagementViewModel::class.java.simpleName
|
private val TAG = ModelsManagementViewModel::class.java.simpleName
|
||||||
|
|
||||||
private const val SUBSCRIPTION_TIMEOUT_MS = 5000L
|
private const val SUBSCRIPTION_TIMEOUT_MS = 5000L
|
||||||
|
private const val SUCCESS_RESET_TIMEOUT_MS = 1000L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,9 +124,19 @@ enum class ModelSortOrder {
|
||||||
LAST_USED
|
LAST_USED
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class ModelImportState {
|
sealed class ModelManagementState {
|
||||||
object Idle : ModelImportState()
|
object Idle : ModelManagementState()
|
||||||
data class Importing(val progress: Float = 0f, val filename: String = "") : ModelImportState()
|
|
||||||
data class Success(val model: ModelInfo) : ModelImportState()
|
sealed class Importation : ModelManagementState() {
|
||||||
data class Error(val message: String) : ModelImportState()
|
data class Importing(val progress: Float = 0f, val filename: String = "") : Importation()
|
||||||
|
data class Success(val model: ModelInfo) : Importation()
|
||||||
|
data class Error(val message: String) : Importation()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Deletion : ModelManagementState() {
|
||||||
|
data class Confirming(val models: Map<String, ModelInfo>): ModelManagementState()
|
||||||
|
data class Deleting(val progress: Float = 0f, val models: Map<String, ModelInfo>) : ModelManagementState()
|
||||||
|
data class Success(val models: List<ModelInfo>) : Deletion()
|
||||||
|
data class Error(val message: String) : Deletion()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue