1package com.peachpasswords.ui.vault23import androidx.lifecycle.SavedStateHandle4import androidx.lifecycle.ViewModel5import androidx.lifecycle.viewModelScope6import com.peachpasswords.vault.VaultEntry7import com.peachpasswords.vault.VaultRepository8import dagger.hilt.android.lifecycle.HiltViewModel9import kotlinx.coroutines.Job10import kotlinx.coroutines.delay11import kotlinx.coroutines.flow.MutableStateFlow12import kotlinx.coroutines.flow.SharingStarted13import kotlinx.coroutines.flow.StateFlow14import kotlinx.coroutines.flow.asStateFlow15import kotlinx.coroutines.flow.map16import kotlinx.coroutines.flow.stateIn17import kotlinx.coroutines.launch18import javax.inject.Inject1920212223242526272829@HiltViewModel30class NotesModeViewModel @Inject constructor(31 private val vault: VaultRepository,32 savedStateHandle: SavedStateHandle,33) : ViewModel() {34 private val id: String = savedStateHandle.get<String>("id").orEmpty()3536 val entry: StateFlow<VaultEntry?> =37 vault.entries.map { list -> list.firstOrNull { it.id == id } }38 .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), vault.getEntry(id))3940 private val _savedPulse = MutableStateFlow(0L)41 42 val savedPulse: StateFlow<Long> = _savedPulse.asStateFlow()4344 private var saveJob: Job? = null4546 47 fun onContentChanged(plainText: String) =48 scheduleSave { it.copy(notes = plainText.ifBlank { null }) }4950 51525354 fun onTitleChanged(title: String) =55 scheduleSave { it.copy(title = title) }5657 58 fun saveTitleNow(title: String) {59 saveJob?.cancel()60 commit { it.copy(title = title) }61 }6263 64 fun saveNow(title: String, plainText: String) {65 saveJob?.cancel()66 commit {67 it.copy(68 title = title.ifBlank { "Untitled" },69 notes = plainText.ifBlank { null },70 )71 }72 }7374 fun delete(onDone: () -> Unit) {75 viewModelScope.launch {76 runCatching { vault.deleteEntry(id) }77 onDone()78 }79 }8081 private fun scheduleSave(patch: (VaultEntry) -> VaultEntry) {82 saveJob?.cancel()83 saveJob = viewModelScope.launch {84 delay(800)85 commit(patch)86 }87 }8889 private fun commit(patch: (VaultEntry) -> VaultEntry) {90 val current = entry.value ?: return91 viewModelScope.launch {92 runCatching { vault.updateEntry(patch(current)) }93 .onSuccess { _savedPulse.value = System.currentTimeMillis() }94 }95 }96}