Yandex штуки
This commit is contained in:
@@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.UUID
|
||||
import kotlin.system.measureTimeMillis
|
||||
@@ -32,7 +33,7 @@ import kotlin.system.measureTimeMillis
|
||||
*/
|
||||
abstract class AbstractVaultBrowserViewModel(
|
||||
storagesFlow: Flow<List<IStorage>>,
|
||||
private val canAddStorage: Boolean,
|
||||
private val vaultAvailabilityFlow: Flow<Boolean>,
|
||||
private val resolveCreateVaultUuid: () -> UUID?,
|
||||
private val removeStorageUseCase: RemoveStorageUseCase,
|
||||
private val getOpenedStoragesUseCase: GetOpenedStoragesUseCase,
|
||||
@@ -43,7 +44,7 @@ abstract class AbstractVaultBrowserViewModel(
|
||||
private val taskOrchestrator: ITaskOrchestrator,
|
||||
private val logger: ILogger,
|
||||
) : ViewModelBase<VaultBrowserScreenState>(
|
||||
VaultBrowserScreenState(storagesList = emptyList(), isLoading = true, canAddStorage = canAddStorage),
|
||||
VaultBrowserScreenState(storagesList = emptyList(), isLoading = true, addStorageFabEnabled = false),
|
||||
) {
|
||||
|
||||
private val _messages = MutableSharedFlow<String>()
|
||||
@@ -63,6 +64,14 @@ abstract class AbstractVaultBrowserViewModel(
|
||||
|
||||
init {
|
||||
collectFlows(storagesFlow)
|
||||
viewModelScope.launch {
|
||||
vaultAvailabilityFlow
|
||||
.distinctUntilChanged()
|
||||
.collect { available ->
|
||||
updateState(state.value.copy(addStorageFabEnabled = available))
|
||||
logger.debug(TAG, "vault availability → add FAB enabled=$available")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateStateLoading() {
|
||||
@@ -125,20 +134,36 @@ abstract class AbstractVaultBrowserViewModel(
|
||||
}
|
||||
|
||||
fun createStorage() {
|
||||
if (!state.value.canAddStorage) return
|
||||
if (!state.value.addStorageFabEnabled) {
|
||||
logger.debug(TAG, "createStorage ignored (vault unavailable or FAB disabled)")
|
||||
return
|
||||
}
|
||||
logger.debug(TAG, "createStorage: enqueue task")
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Create storage",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
ctx.log(TaskLogLevel.Info, "Creating storage…")
|
||||
val uuid = resolveCreateVaultUuid()
|
||||
?: throw IllegalStateException("Vault is not available")
|
||||
manageVaultUseCase.createStorage(uuid)
|
||||
ctx.log(TaskLogLevel.Info, "Storage created")
|
||||
try {
|
||||
ctx.log(TaskLogLevel.Info, "Creating storage…")
|
||||
val uuid = resolveCreateVaultUuid()
|
||||
?: throw IllegalStateException("Vault is not available")
|
||||
logger.debug(TAG, "createStorage: vaultUuid=$uuid")
|
||||
val storage = manageVaultUseCase.createStorage(uuid)
|
||||
ctx.log(TaskLogLevel.Info, "Storage created")
|
||||
logger.debug(TAG, "createStorage: done storageUuid=${storage.uuid}")
|
||||
} catch (e: Exception) {
|
||||
logger.debug(TAG, "createStorage failed: ${e.stackTraceToString()}")
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: e.toString())
|
||||
throw e
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val TAG = "VaultBrowser"
|
||||
}
|
||||
|
||||
private val storageOpMutex = Any()
|
||||
private val runningStorages = mutableSetOf<UUID>()
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ class LocalVaultViewModel @Inject constructor(
|
||||
storagesFlow = vaultsManager.vaults
|
||||
.map { vaults -> vaults.described().locals.firstOrNull() }
|
||||
.flatMapLatest { v -> v?.storages ?: flowOf(emptyList()) },
|
||||
canAddStorage = true,
|
||||
vaultAvailabilityFlow = vaultsManager.vaults
|
||||
.map { vaults -> vaults.described().locals.firstOrNull() }
|
||||
.flatMapLatest { v -> v?.isAvailable ?: flowOf(false) },
|
||||
resolveCreateVaultUuid = { vaultsManager.vaults.value.described().locals.firstOrNull()?.uuid },
|
||||
removeStorageUseCase = removeStorageUseCase,
|
||||
getOpenedStoragesUseCase = getOpenedStoragesUseCase,
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.github.nullptroma.wallenc.domain.usecases.RenameStorageUseCase
|
||||
import com.github.nullptroma.wallenc.domain.usecases.StorageFileManagementUseCase
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -28,8 +30,9 @@ class RemoteVaultViewModel @Inject constructor(
|
||||
logger: ILogger,
|
||||
) : AbstractVaultBrowserViewModel(
|
||||
storagesFlow = manageVaultUseCase.storagesOf(savedStateHandle.requireVaultUuid()),
|
||||
canAddStorage = false,
|
||||
resolveCreateVaultUuid = { null },
|
||||
vaultAvailabilityFlow = manageVaultUseCase.observe(savedStateHandle.requireVaultUuid())
|
||||
.flatMapLatest { v -> v?.isAvailable ?: flowOf(false) },
|
||||
resolveCreateVaultUuid = { savedStateHandle.requireVaultUuid() },
|
||||
removeStorageUseCase = removeStorageUseCase,
|
||||
getOpenedStoragesUseCase = getOpenedStoragesUseCase,
|
||||
storageFileManagementUseCase = storageFileManagementUseCase,
|
||||
|
||||
@@ -50,12 +50,21 @@ fun VaultBrowserScreen(
|
||||
modifier = modifier,
|
||||
contentWindowInsets = WindowInsets(0.dp),
|
||||
floatingActionButton = {
|
||||
if (uiState.canAddStorage) {
|
||||
FloatingActionButton(
|
||||
onClick = { viewModel.createStorage() },
|
||||
) {
|
||||
Icon(Icons.Filled.Add, contentDescription = null)
|
||||
}
|
||||
val fabEnabled = uiState.addStorageFabEnabled
|
||||
FloatingActionButton(
|
||||
onClick = { if (fabEnabled) viewModel.createStorage() },
|
||||
containerColor = if (fabEnabled) {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceVariant
|
||||
},
|
||||
contentColor = if (fabEnabled) {
|
||||
MaterialTheme.colorScheme.onPrimaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.55f)
|
||||
},
|
||||
) {
|
||||
Icon(Icons.Filled.Add, contentDescription = null)
|
||||
}
|
||||
},
|
||||
) { innerPadding ->
|
||||
|
||||
@@ -6,5 +6,6 @@ import com.github.nullptroma.wallenc.domain.interfaces.IStorageInfo
|
||||
data class VaultBrowserScreenState(
|
||||
val storagesList: List<Tree<IStorageInfo>>,
|
||||
val isLoading: Boolean,
|
||||
val canAddStorage: Boolean = false,
|
||||
/** FAB «добавить storage»: активна только когда vault доступен (сеть/API/путь). */
|
||||
val addStorageFabEnabled: Boolean = false,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user