Использования менеджера Tasks
This commit is contained in:
@@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
@@ -92,8 +93,12 @@ class LocalVaultViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun printStorageInfoToLog(storage: IStorageInfo) {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Dump storage to log",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
storageFileManagementUseCase.setStorage(storage)
|
||||
viewModelScope.launch {
|
||||
ctx.log(TaskLogLevel.Info, "Enumerating files and directories…")
|
||||
val files: List<IFile>
|
||||
val dirs: List<IDirectory>
|
||||
val time = measureTimeMillis {
|
||||
@@ -108,7 +113,12 @@ class LocalVaultViewModel @Inject constructor(
|
||||
}
|
||||
logger.debug("Time", "Time: $time ms")
|
||||
logger.debug("Storage", storage.toPrintable())
|
||||
}
|
||||
ctx.log(
|
||||
TaskLogLevel.Info,
|
||||
"Done: ${files.size} files, ${dirs.size} dirs in ${time}ms (see app log for lines)",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun createStorage() {
|
||||
@@ -123,71 +133,105 @@ class LocalVaultViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private val runningStorages = mutableSetOf<java.util.UUID>()
|
||||
private val storageOpMutex = Any()
|
||||
private val runningStorages = mutableSetOf<UUID>()
|
||||
|
||||
fun enableEncryption(storage: IStorageInfo, password: String, encryptPath: Boolean) {
|
||||
val id = storage.uuid
|
||||
if (runningStorages.contains(id))
|
||||
return
|
||||
tasksCount++
|
||||
synchronized(storageOpMutex) {
|
||||
if (runningStorages.contains(id)) return
|
||||
runningStorages.add(id)
|
||||
tasksCount++
|
||||
}
|
||||
val key = EncryptKey(password)
|
||||
viewModelScope.launch {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Enable encryption",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Checking storage…")
|
||||
when (manageStoragesEncryptionUseCase.canEncrypt(storage)) {
|
||||
ManageStoragesEncryptionUseCase.CanEncryptResult.Allowed -> {
|
||||
ctx.log(TaskLogLevel.Info, "Encrypting…")
|
||||
manageStoragesEncryptionUseCase.enableEncryption(storage, key, encryptPath)
|
||||
manageStoragesEncryptionUseCase.openStorage(storage, key, true)
|
||||
ctx.log(TaskLogLevel.Info, "Encryption enabled")
|
||||
_messages.emit("Encryption enabled")
|
||||
}
|
||||
ManageStoragesEncryptionUseCase.CanEncryptResult.AlreadyEncrypted -> {
|
||||
ctx.log(TaskLogLevel.Info, "Storage is already encrypted")
|
||||
_messages.emit("Storage is already encrypted")
|
||||
}
|
||||
ManageStoragesEncryptionUseCase.CanEncryptResult.StorageIsNotEmpty -> {
|
||||
ctx.log(TaskLogLevel.Info, "Storage is not empty")
|
||||
_messages.emit("Storage is not empty")
|
||||
}
|
||||
ManageStoragesEncryptionUseCase.CanEncryptResult.StorageStateUnknown -> {
|
||||
ctx.log(TaskLogLevel.Info, "Cannot determine whether storage is empty")
|
||||
_messages.emit("Cannot determine whether storage is empty")
|
||||
}
|
||||
ManageStoragesEncryptionUseCase.CanEncryptResult.UnsupportedStorageType -> {
|
||||
ctx.log(TaskLogLevel.Info, "Unsupported storage type")
|
||||
_messages.emit("Unsupported storage type")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Failed to enable encryption")
|
||||
_messages.emit(e.message ?: "Failed to enable encryption")
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
synchronized(storageOpMutex) {
|
||||
runningStorages.remove(id)
|
||||
tasksCount--
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun openEncryptedStorage(storage: IStorageInfo, password: String, rememberPassword: Boolean) {
|
||||
val id = storage.uuid
|
||||
synchronized(storageOpMutex) {
|
||||
if (runningStorages.contains(id)) return
|
||||
tasksCount++
|
||||
runningStorages.add(id)
|
||||
tasksCount++
|
||||
}
|
||||
val key = EncryptKey(password)
|
||||
viewModelScope.launch {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Open encrypted storage",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Opening storage…")
|
||||
manageStoragesEncryptionUseCase.openStorage(storage, key, rememberPassword)
|
||||
ctx.log(TaskLogLevel.Info, "Storage opened")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Failed to open encrypted storage")
|
||||
_messages.emit(e.message ?: "Failed to open encrypted storage")
|
||||
} finally {
|
||||
synchronized(storageOpMutex) {
|
||||
runningStorages.remove(id)
|
||||
tasksCount--
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun closeEncryptedStorage(storage: IStorageInfo) {
|
||||
viewModelScope.launch {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Close encrypted storage",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Closing storage…")
|
||||
manageStoragesEncryptionUseCase.closeStorage(storage)
|
||||
ctx.log(TaskLogLevel.Info, "Storage closed")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Failed to close encrypted storage")
|
||||
_messages.emit(e.message ?: "Failed to close encrypted storage")
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun disableEncryption(storage: IStorageInfo) {
|
||||
@@ -211,9 +255,19 @@ class LocalVaultViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun rename(storage: IStorageInfo, newName: String) {
|
||||
viewModelScope.launch {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Rename storage",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Renaming…")
|
||||
renameStorageUseCase.rename(storage, newName)
|
||||
ctx.log(TaskLogLevel.Info, "Renamed")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Rename failed")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun remove(storage: IStorageInfo) {
|
||||
|
||||
@@ -4,18 +4,22 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.github.nullptroma.wallenc.domain.auth.RemoteYandexSignInLauncher
|
||||
import com.github.nullptroma.wallenc.domain.interfaces.IYandexVault
|
||||
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
|
||||
import com.github.nullptroma.wallenc.domain.tasks.ITaskOrchestrator
|
||||
import com.github.nullptroma.wallenc.domain.tasks.TaskLogLevel
|
||||
import com.github.nullptroma.wallenc.presentation.ViewModelBase
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class RemoteVaultsViewModel @Inject constructor(
|
||||
private val vaultsManager: IVaultsManager,
|
||||
val yandexSignIn: RemoteYandexSignInLauncher,
|
||||
private val taskOrchestrator: ITaskOrchestrator,
|
||||
) : ViewModelBase<RemoteVaultsScreenState>(RemoteVaultsScreenState()) {
|
||||
|
||||
val uiState = combine(
|
||||
@@ -50,15 +54,25 @@ class RemoteVaultsViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun onYandexAuthSuccess(accessToken: String) {
|
||||
viewModelScope.launch {
|
||||
setBusy(true)
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Add Yandex vault",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Adding vault…")
|
||||
vaultsManager.addYandexVault(accessToken)
|
||||
ctx.log(TaskLogLevel.Info, "Vault added")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Failed to add vault")
|
||||
} finally {
|
||||
withContext(Dispatchers.Main.immediate) {
|
||||
setBusy(false)
|
||||
setAddChoiceVisible(false)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun requestDeleteVault(item: RemoteVaultListItem) {
|
||||
@@ -71,14 +85,25 @@ class RemoteVaultsViewModel @Inject constructor(
|
||||
|
||||
fun confirmDeleteVault() {
|
||||
val pending = state.value.vaultPendingDelete ?: return
|
||||
viewModelScope.launch {
|
||||
val uuid = pending.uuid
|
||||
setBusy(true)
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Remove remote vault",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
vaultsManager.removeRemoteVault(pending.uuid)
|
||||
ctx.log(TaskLogLevel.Info, "Removing remote vault…")
|
||||
vaultsManager.removeRemoteVault(uuid)
|
||||
ctx.log(TaskLogLevel.Info, "Remote vault removed")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Failed to remove vault")
|
||||
} finally {
|
||||
withContext(Dispatchers.Main.immediate) {
|
||||
setBusy(false)
|
||||
dismissDeleteVault()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user