v1.0.15: ON_CHANGE file watching, browser fix, rich notifications

- Add FileWatchService for real-time ON_CHANGE sync (FileObserver for
  direct paths, ContentObserver for SAF content:// URIs), 5s debounce
- Fix remote browser stuck spinner: cancel in-flight jobs on navigation,
  reset entries immediately, add Retry button on error
- Fix browser reuse bug: LaunchedEffect key now includes initialPath
- Fix WebDavProvider: rethrow XML parse errors (no more silent Empty
  folder) and URL-decode file names from href
- Notifications now use BigTextStyle showing per-file-type counts
  (Uploaded/Downloaded/Deleted) matching Autosync notification style
- Wire FileWatchService into BootReceiver and HomeViewModel toggle
- Register FileWatchService in AndroidManifest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 02:55:19 +00:00
parent e22db9bced
commit f751b26a9e
10 changed files with 318 additions and 94 deletions
@@ -27,7 +27,7 @@ fun RemoteBrowserDialog(
onDismiss: () -> Unit,
vm: RemoteBrowserViewModel = hiltViewModel(),
) {
LaunchedEffect(accountId) { vm.init(accountId, initialPath) }
LaunchedEffect(accountId, initialPath) { vm.init(accountId, initialPath) }
val state by vm.state.collectAsState()
@@ -81,6 +81,7 @@ fun RemoteBrowserDialog(
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Default.ErrorOutline, null, Modifier.size(48.dp), tint = MaterialTheme.colorScheme.error)
Text(state.error!!, color = MaterialTheme.colorScheme.error)
FilledTonalButton(onClick = { vm.retry() }) { Text("Retry") }
}
}
state.entries.isEmpty() -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {