Feature: Introduce ModelRepository and ModelsManagementViewModel; update AppModule

This commit is contained in:
Han Yin 2025-04-14 12:54:17 -07:00
parent aedf442632
commit 6e82bb37d3
3 changed files with 189 additions and 11 deletions

View File

@ -0,0 +1,51 @@
package com.example.llama.revamp.data.repository
import android.content.Context
import android.net.Uri
import com.example.llama.revamp.data.model.ModelInfo
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton
interface ModelRepository {
suspend fun getModels(): List<ModelInfo>
suspend fun deleteModel(modelId: String)
suspend fun deleteModels(modelIds: Collection<String>)
suspend fun importModel(uri: Uri): ModelInfo
suspend fun getStorageMetrics(): StorageMetrics
}
@Singleton
class ModelRepositoryImpl @Inject constructor(
@ApplicationContext private val context: Context,
// TODO-han.yin: Add model DAO
) : ModelRepository {
override suspend fun getModels(): List<ModelInfo> {
// In a real implementation, this would load from database
return ModelInfo.getSampleModels()
}
override suspend fun deleteModel(modelId: String) {
// Stub - would delete from filesystem and database
}
override suspend fun deleteModels(modelIds: Collection<String>) {
// Stub - would delete from filesystem and database
}
override suspend fun importModel(uri: Uri): ModelInfo {
// Stub - would copy file and extract metadata
return ModelInfo.getSampleModels().first()
}
override suspend fun getStorageMetrics(): StorageMetrics {
// Stub - would calculate from actual storage
return StorageMetrics(14.6f, 32.0f)
}
}
data class StorageMetrics(
val usedGB: Float,
val totalGB: Float
)

View File

@ -2,8 +2,11 @@ package com.example.llama.revamp.di
import android.content.Context import android.content.Context
import com.example.llama.revamp.data.local.AppDatabase import com.example.llama.revamp.data.local.AppDatabase
import com.example.llama.revamp.data.repository.ModelRepository
import com.example.llama.revamp.data.repository.ModelRepositoryImpl
import com.example.llama.revamp.engine.InferenceEngine import com.example.llama.revamp.engine.InferenceEngine
import com.example.llama.revamp.monitoring.PerformanceMonitor import com.example.llama.revamp.monitoring.PerformanceMonitor
import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
@ -13,19 +16,24 @@ import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
object AppModule { abstract class AppModule {
@Provides @Binds
@Singleton abstract fun bindsModelsRepository(impl: ModelRepositoryImpl): ModelRepository
fun provideInferenceEngine() = InferenceEngine()
@Provides companion object {
@Singleton @Provides
fun providePerformanceMonitor(@ApplicationContext context: Context) = PerformanceMonitor(context) @Singleton
fun provideInferenceEngine() = InferenceEngine()
@Provides @Provides
fun provideAppDatabase(@ApplicationContext context: Context) = AppDatabase.getDatabase(context) @Singleton
fun providePerformanceMonitor(@ApplicationContext context: Context) = PerformanceMonitor(context)
@Provides @Provides
fun providesSystemPromptDao(appDatabase: AppDatabase) = appDatabase.systemPromptDao() fun provideAppDatabase(@ApplicationContext context: Context) = AppDatabase.getDatabase(context)
@Provides
fun providesSystemPromptDao(appDatabase: AppDatabase) = appDatabase.systemPromptDao()
}
} }

View File

@ -0,0 +1,119 @@
package com.example.llama.revamp.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.llama.revamp.data.model.ModelInfo
import com.example.llama.revamp.data.repository.ModelRepository
import com.example.llama.revamp.data.repository.StorageMetrics
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class ModelsManagementViewModel @Inject constructor(
private val modelRepository: ModelRepository
) : ViewModel() {
// Sort order state
private val _sortOrder = MutableStateFlow(ModelSortOrder.NAME_ASC)
val sortOrder: StateFlow<ModelSortOrder> = _sortOrder.asStateFlow()
// Available models
private val _availableModels = MutableStateFlow<List<ModelInfo>>(emptyList())
val availableModels: StateFlow<List<ModelInfo>> = _availableModels.asStateFlow()
// Storage metrics
private val _storageMetrics = MutableStateFlow(StorageMetrics(0f, 0f))
val storageMetrics: StateFlow<StorageMetrics> = _storageMetrics.asStateFlow()
init {
// Initial data load
viewModelScope.launch {
loadModels()
loadStorageMetrics()
}
// Observe sort order changes and apply sorting
viewModelScope.launch {
sortOrder.collect { order -> sortModels(order) }
}
}
private fun loadModels() {
// TODO-han.yin: Stub for now. Would load from the repository
_availableModels.value = ModelInfo.getSampleModels()
sortModels(_sortOrder.value)
}
private fun loadStorageMetrics() {
// TODO-han.yin: Stub for now. Would load from storage
_storageMetrics.value = StorageMetrics(14.6f, 32.0f)
}
private fun sortModels(order: ModelSortOrder) {
val sorted = when (order) {
ModelSortOrder.NAME_ASC -> _availableModels.value.sortedBy { it.name }
ModelSortOrder.NAME_DESC -> _availableModels.value.sortedByDescending { it.name }
ModelSortOrder.SIZE_ASC -> _availableModels.value.sortedBy { it.sizeInBytes }
ModelSortOrder.SIZE_DESC -> _availableModels.value.sortedByDescending { it.sizeInBytes }
ModelSortOrder.LAST_USED -> _availableModels.value.sortedByDescending { it.lastUsed ?: 0 }
}
_availableModels.value = sorted
}
fun setSortOrder(order: ModelSortOrder) {
_sortOrder.value = order
}
fun viewModelDetails(modelId: String) {
// TODO-han.yin: Stub for now. Would navigate to model details screen or show dialog
}
fun deleteModel(modelId: String) {
// Remove model from list
_availableModels.value = _availableModels.value.filter { it.id != modelId }
viewModelScope.launch {
// TODO-han.yin: Stub for now this would delete from storage
modelRepository.deleteModel(modelId)
updateStorageMetrics()
}
}
fun deleteModels(models: Map<String, ModelInfo>) {
val modelIds = models.keys
_availableModels.value = _availableModels.value.filter { !modelIds.contains(it.id) }
viewModelScope.launch {
modelRepository.deleteModels(modelIds)
updateStorageMetrics()
}
}
fun importLocalModel() {
// TODO-han.yin: Stub for now. Would open file picker and import model
}
private fun updateStorageMetrics() {
// Recalculate storage metrics after model changes
// TODO-han.yin: Stub for now. Would query actual storage
val totalSize = _availableModels.value.sumOf { it.sizeInBytes }
_storageMetrics.value = StorageMetrics(
(totalSize / 1_000_000_000.0).toFloat(),
32.0f
)
}
}
enum class ModelSortOrder {
NAME_ASC,
NAME_DESC,
SIZE_ASC,
SIZE_DESC,
LAST_USED
}