v1.0.26: fix multi-selection reactivity, redesign icon, security review

Fix multi-selection: selectedKeys exposed as StateFlow, collected in
FilesScreen so checkboxes and highlights update correctly on every tap.
fileKey() made public so UI can check membership without ViewModel calls.

Icon: white cloud body with two cyan/teal circular sync arcs (AutoSync
style), deep blue-to-teal gradient background.

Security review clean: no hardcoded credentials, cleartext blocked by
network_security_config, allowBackup=false, path traversal guards in
place on both server responses and local resolution.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 02:45:43 +00:00
parent 8fdd22bc98
commit 742f634084
5 changed files with 86 additions and 39 deletions
@@ -39,8 +39,9 @@ fun FilesScreen(
val selectedPair by vm.selectedPair.collectAsState()
val files by vm.files.collectAsState()
val isDownloading by vm.isDownloading.collectAsState()
val isSelectionMode by vm.isSelectionMode.collectAsState()
val selectedCount by vm.selectedCount.collectAsState()
val selectedKeys by vm.selectedKeys.collectAsState()
val isSelectionMode = selectedKeys.isNotEmpty()
val selectedCount = selectedKeys.size
val context = LocalContext.current
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
@@ -252,12 +253,11 @@ fun FilesScreen(
}
}
items(dirFiles, key = { "${it.syncPairId}_${it.relativePath}" }) { file ->
val selected = vm.isSelected(file)
FileRow(
file = file,
isInSubDir = dir.isNotEmpty() && !isSelectionMode,
isSelectionMode = isSelectionMode,
isSelected = selected,
isSelected = vm.fileKey(file) in selectedKeys,
vm = vm,
)
HorizontalDivider(