feat(sync): добавлен механизм снятия блокировки синхронизации для хранилищ
This commit is contained in:
@@ -29,6 +29,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ripple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -63,6 +64,8 @@ fun StorageTree(
|
||||
onDisableEncryption: (Tree<IStorageInfo>) -> Unit,
|
||||
getStatusText: (Tree<IStorageInfo>) -> String,
|
||||
isEncryptionOpened: (Tree<IStorageInfo>) -> Boolean,
|
||||
isStorageSyncLockHeld: suspend (IStorageInfo) -> Boolean,
|
||||
onClearStorageSyncLock: (IStorageInfo) -> Unit,
|
||||
) {
|
||||
val cur = tree.value
|
||||
val available by cur.isAvailable.collectAsStateWithLifecycle()
|
||||
@@ -125,6 +128,15 @@ fun StorageTree(
|
||||
horizontalAlignment = Alignment.End
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
var syncLockHeld by remember { mutableStateOf<Boolean?>(null) }
|
||||
LaunchedEffect(expanded, cur.uuid) {
|
||||
if (expanded) {
|
||||
syncLockHeld = null
|
||||
syncLockHeld = isStorageSyncLockHeld(cur)
|
||||
} else {
|
||||
syncLockHeld = null
|
||||
}
|
||||
}
|
||||
var showRenameDialog by remember { mutableStateOf(false) }
|
||||
var showRemoveConfirmDialog by remember { mutableStateOf(false) }
|
||||
var showLockDialog by remember { mutableStateOf(false) }
|
||||
@@ -166,6 +178,25 @@ fun StorageTree(
|
||||
text = { Text(stringResource(R.string.encrypt)) }
|
||||
)
|
||||
}
|
||||
HorizontalDivider()
|
||||
DropdownMenuItem(
|
||||
enabled = syncLockHeld == true,
|
||||
onClick = {
|
||||
expanded = false
|
||||
if (syncLockHeld == true) {
|
||||
onClearStorageSyncLock(cur)
|
||||
}
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
when (syncLockHeld) {
|
||||
null -> stringResource(R.string.storage_sync_lock_checking)
|
||||
true -> stringResource(R.string.storage_sync_unlock_action)
|
||||
false -> stringResource(R.string.storage_sync_not_locked)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (showRenameDialog) {
|
||||
@@ -295,7 +326,9 @@ fun StorageTree(
|
||||
onCloseEncrypted,
|
||||
onDisableEncryption,
|
||||
getStatusText,
|
||||
isEncryptionOpened
|
||||
isEncryptionOpened,
|
||||
isStorageSyncLockHeld,
|
||||
onClearStorageSyncLock,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,4 +328,37 @@ abstract class AbstractVaultBrowserViewModel(
|
||||
val openedMap = getOpenedStoragesUseCase.openedStorages.value
|
||||
return openedMap.containsKey(storage.uuid)
|
||||
}
|
||||
|
||||
suspend fun isStorageSyncLockHeld(storage: IStorageInfo): Boolean {
|
||||
val s = storage as? IStorage ?: return false
|
||||
return try {
|
||||
s.accessor.readSyncLock() != null
|
||||
} catch (_: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun clearStorageSyncLock(storage: IStorageInfo) {
|
||||
taskOrchestrator.enqueue(
|
||||
title = "Снятие блокировки синхронизации",
|
||||
dispatcher = Dispatchers.IO,
|
||||
work = { ctx ->
|
||||
try {
|
||||
val s = storage as? IStorage
|
||||
if (s == null) {
|
||||
ctx.log(TaskLogLevel.Error, "Некорректное хранилище")
|
||||
_messages.emit("Некорректное хранилище")
|
||||
return@enqueue
|
||||
}
|
||||
ctx.log(TaskLogLevel.Info, "Снимаю блокировку синхронизации…")
|
||||
s.accessor.forceClearSyncLock()
|
||||
ctx.log(TaskLogLevel.Info, "Блокировка синхронизации снята")
|
||||
_messages.emit("Блокировка синхронизации снята")
|
||||
} catch (e: Exception) {
|
||||
ctx.log(TaskLogLevel.Error, e.message ?: "Не удалось снять блокировку")
|
||||
_messages.emit(e.message ?: "Не удалось снять блокировку синхронизации")
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,8 @@ fun VaultBrowserScreen(
|
||||
onDisableEncryption = { tree -> viewModel.disableEncryption(tree.value) },
|
||||
getStatusText = { tree -> viewModel.getStorageStatus(tree.value) },
|
||||
isEncryptionOpened = { tree -> viewModel.isEncryptionSessionOpen(tree.value) },
|
||||
isStorageSyncLockHeld = { info -> viewModel.isStorageSyncLockHeld(info) },
|
||||
onClearStorageSyncLock = { info -> viewModel.clearStorageSyncLock(info) },
|
||||
)
|
||||
}
|
||||
item { Spacer(modifier = Modifier.height(8.dp)) }
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<string name="new_name_title">New name</string>
|
||||
<string name="remove_confirmation_dialog">Delete storage "%1$s"?</string>
|
||||
<string name="storage_lock_actions">Storage encryption actions</string>
|
||||
<string name="storage_sync_lock_checking">Проверка блокировки…</string>
|
||||
<string name="storage_sync_unlock_action">Снять блокировку синхронизации</string>
|
||||
<string name="storage_sync_not_locked">Синхронизация не заблокирована</string>
|
||||
|
||||
<string name="task_pipeline_title">Task pipeline</string>
|
||||
<string name="task_pipeline_jobs">Jobs</string>
|
||||
|
||||
Reference in New Issue
Block a user