diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/CalendarHost.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/CalendarHost.kt index 25cda63..2c938f7 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/CalendarHost.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/CalendarHost.kt @@ -172,9 +172,15 @@ fun CalendarHost( // picker (many). A plain conditional overlay (no slide) — it's transient. var importUri by remember { mutableStateOf(null) } var importForm by remember { mutableStateOf(null) } + // A restore (in-app "Restore from .ics" button) always runs the full import + // flow — picker + summary — even for a single-event file, because the intent + // is "restore a backup", not "add this one event". An externally opened .ics + // keeps routing a single event straight into the prefilled create form. + var importForceMany by remember { mutableStateOf(false) } LaunchedEffect(requestedImportUri) { if (requestedImportUri != null) { importUri = requestedImportUri + importForceMany = false onImportConsumed() } } @@ -414,7 +420,7 @@ fun CalendarHost( ) { CalendarsScreen( onBack = { showCalendars = false }, - onImport = { importUri = it }, + onImport = { importUri = it; importForceMany = true }, ) } @@ -423,6 +429,7 @@ fun CalendarHost( importUri?.let { uri -> ImportScreen( uri = uri, + forceMany = importForceMany, onClose = { importUri = null }, onOpenSingle = { form -> importUri = null diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportScreen.kt index eb072af..71d67b1 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportScreen.kt @@ -64,7 +64,9 @@ import de.jeanlucmakiola.calendula.ui.common.predictiveBack * Handles an opened/received `.ics` file. A single event is handed straight to * the prefilled create form via [onOpenSingle]; several events show a target- * calendar picker and import in bulk (dedup by UID), then a result summary. - * Empty/failed files show a short message and close. + * Empty/failed files show a short message and close. [forceMany] keeps a + * single-event file on the bulk path — used by the in-app restore, whose intent + * is "restore a backup" rather than "add this one event". */ @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -72,9 +74,10 @@ fun ImportScreen( uri: Uri, onClose: () -> Unit, onOpenSingle: (EventForm) -> Unit, + forceMany: Boolean = false, viewModel: ImportViewModel = hiltViewModel(), ) { - LaunchedEffect(uri) { viewModel.load(uri) } + LaunchedEffect(uri) { viewModel.load(uri, forceMany) } val state by viewModel.state.collectAsStateWithLifecycle() // A single event isn't shown here — it opens the create form for review. diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportViewModel.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportViewModel.kt index 248d656..8ba9084 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportViewModel.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/imports/ImportViewModel.kt @@ -66,8 +66,13 @@ class ImportViewModel @Inject constructor( val state: StateFlow = _state.asStateFlow() private var started = false - /** Read + parse [uri] once; subsequent calls (recomposition) are ignored. */ - fun load(uri: Uri) { + /** + * Read + parse [uri] once; subsequent calls (recomposition) are ignored. + * When [forceMany] is set (an in-app restore), a single-event file still goes + * through the bulk picker + summary rather than the prefilled create form — + * a restore is "bring back a backup", not "add this one event". + */ + fun load(uri: Uri, forceMany: Boolean = false) { if (started) return started = true viewModelScope.launch { @@ -77,7 +82,7 @@ class ImportViewModel @Inject constructor( _state.value = when { parsed == null -> ImportUiState.Failed parsed.events.isEmpty() -> ImportUiState.Empty - parsed.events.size == 1 -> ImportUiState.Single( + parsed.events.size == 1 && !forceMany -> ImportUiState.Single( form = parsed.events.single().toEventForm(TimeZone.currentSystemDefault()), warnings = parsed.warnings, )