From 069ae38b2c5a8b05e8c429a589658d31e459f1ba Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sun, 28 Jun 2026 13:25:53 +0200 Subject: [PATCH] components batch-2: draw CollapsingScaffold + OptionPicker from floret-kit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agendula now sources the collapsing settings/sub-screen scaffold and the full-screen single-select picker (FullScreenPicker/OptionPicker) from the kit's components module. Deletes the app copies; repoints SettingsScreen imports and adds the FullScreenPicker import in ReminderLeadPicker. Submodule re-pinned. ReminderFormatting stays app-local (needs a label-callback API — separate pass). Clean composite build + tests + lintDebug + debug assemble green. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../agendula/ui/common/CollapsingScaffold.kt | 84 ------------------- .../agendula/ui/common/OptionPicker.kt | 81 ------------------ .../agendula/ui/common/ReminderLeadPicker.kt | 1 + .../agendula/ui/settings/SettingsScreen.kt | 4 +- floret-kit | 2 +- 5 files changed, 4 insertions(+), 168 deletions(-) delete mode 100644 app/src/main/java/de/jeanlucmakiola/agendula/ui/common/CollapsingScaffold.kt delete mode 100644 app/src/main/java/de/jeanlucmakiola/agendula/ui/common/OptionPicker.kt diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/CollapsingScaffold.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/CollapsingScaffold.kt deleted file mode 100644 index 87754c7..0000000 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/CollapsingScaffold.kt +++ /dev/null @@ -1,84 +0,0 @@ -package de.jeanlucmakiola.agendula.ui.common - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.rounded.ArrowBack -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.LargeTopAppBar -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.rememberTopAppBarState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import de.jeanlucmakiola.agendula.R - -/** - * Shared collapsing scaffold for the settings hub, its sub-screens and the - * full-screen pickers: a [LargeTopAppBar] that collapses on scroll, a back - * button, and a vertically scrolling content column. Ported from Calendula so - * the two apps' settings read as one family. The content lays out the connected - * grouped rows. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun CollapsingScaffold( - title: String, - onBack: () -> Unit, - modifier: Modifier = Modifier, - content: @Composable ColumnScope.() -> Unit, -) { - val scrollBehavior = - TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()) - Scaffold( - modifier = modifier - .fillMaxSize() - .background(MaterialTheme.colorScheme.surface) - .nestedScroll(scrollBehavior.nestedScrollConnection), - topBar = { - LargeTopAppBar( - title = { Text(title) }, - navigationIcon = { - IconButton(onClick = onBack) { - Icon( - Icons.AutoMirrored.Rounded.ArrowBack, - contentDescription = stringResource(R.string.back), - ) - } - }, - scrollBehavior = scrollBehavior, - colors = TopAppBarDefaults.largeTopAppBarColors( - scrolledContainerColor = MaterialTheme.colorScheme.surface, - ), - ) - }, - ) { innerPadding -> - Column( - modifier = Modifier - .padding(innerPadding) - // Consume the scaffold's bar insets so imePadding adds only the - // keyboard height beyond them (max, not sum). - .consumeWindowInsets(innerPadding) - .fillMaxSize() - .background(MaterialTheme.colorScheme.surface) - .imePadding() - .verticalScroll(rememberScrollState()) - .padding(top = 8.dp, bottom = 24.dp), - content = content, - ) - } -} diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/OptionPicker.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/OptionPicker.kt deleted file mode 100644 index e4cc7b8..0000000 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/OptionPicker.kt +++ /dev/null @@ -1,81 +0,0 @@ -package de.jeanlucmakiola.agendula.ui.common - -import de.jeanlucmakiola.floret.components.positionOf -import de.jeanlucmakiola.floret.components.GroupedRow -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Check -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties - -/** - * Shared full-screen scaffold for selection pickers: a full-bleed [Dialog] that - * reuses [CollapsingScaffold] (collapsing title + back), so a picker is visually - * identical to a settings sub-page and uses the full width. [content] places the - * connected grouped rows; selecting one calls [onDismiss]. Ported from Calendula. - */ -@Composable -fun FullScreenPicker( - title: String, - onDismiss: () -> Unit, - content: @Composable ColumnScope.() -> Unit, -) { - Dialog( - onDismissRequest = onDismiss, - properties = DialogProperties( - usePlatformDefaultWidth = false, - decorFitsSystemWindows = false, - ), - ) { - CollapsingScaffold(title = title, onBack = onDismiss, content = content) - } -} - -/** - * General single-select picker, full-screen: each option is a connected grouped - * row and the current one carries a check. The drop-in for the family's option - * dialogs (theme, default list, reminder offset, …). - */ -@Composable -fun OptionPicker( - title: String, - options: List, - selected: T, - label: @Composable (T) -> String, - onSelect: (T) -> Unit, - onDismiss: () -> Unit, - leading: (@Composable (T) -> Unit)? = null, -) { - FullScreenPicker(title = title, onDismiss = onDismiss) { - options.forEachIndexed { index, option -> - val isSelected = option == selected - GroupedRow( - title = label(option), - position = positionOf(index, options.size), - selected = isSelected, - leading = leading?.let { { it(option) } }, - trailing = if (isSelected) { - { SelectedCheck() } - } else { - null - }, - onClick = { - onSelect(option) - onDismiss() - }, - ) - } - } -} - -@Composable -private fun SelectedCheck() { - Icon( - imageVector = Icons.Rounded.Check, - contentDescription = null, - tint = MaterialTheme.colorScheme.primary, - ) -} diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/ReminderLeadPicker.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/ReminderLeadPicker.kt index 18f9b6f..e848c17 100644 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/ReminderLeadPicker.kt +++ b/app/src/main/java/de/jeanlucmakiola/agendula/ui/common/ReminderLeadPicker.kt @@ -1,5 +1,6 @@ package de.jeanlucmakiola.agendula.ui.common +import de.jeanlucmakiola.floret.components.FullScreenPicker import de.jeanlucmakiola.floret.components.Position import de.jeanlucmakiola.floret.components.positionOf import de.jeanlucmakiola.floret.components.InlineTextField diff --git a/app/src/main/java/de/jeanlucmakiola/agendula/ui/settings/SettingsScreen.kt b/app/src/main/java/de/jeanlucmakiola/agendula/ui/settings/SettingsScreen.kt index ade7101..598123f 100644 --- a/app/src/main/java/de/jeanlucmakiola/agendula/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/agendula/ui/settings/SettingsScreen.kt @@ -87,9 +87,9 @@ import de.jeanlucmakiola.agendula.R import de.jeanlucmakiola.agendula.data.prefs.ListReminderOverride import de.jeanlucmakiola.agendula.data.prefs.ThemeMode import de.jeanlucmakiola.agendula.domain.TaskFormField -import de.jeanlucmakiola.agendula.ui.common.CollapsingScaffold +import de.jeanlucmakiola.floret.components.CollapsingScaffold import de.jeanlucmakiola.floret.components.GroupedRow -import de.jeanlucmakiola.agendula.ui.common.OptionPicker +import de.jeanlucmakiola.floret.components.OptionPicker import de.jeanlucmakiola.floret.components.Position import de.jeanlucmakiola.agendula.ui.common.ReminderLeadPicker import de.jeanlucmakiola.floret.components.pastelize diff --git a/floret-kit b/floret-kit index 1bd3e03..0db0e38 160000 --- a/floret-kit +++ b/floret-kit @@ -1 +1 @@ -Subproject commit 1bd3e03ad582f15f22938cec171a7786afaff9ff +Subproject commit 0db0e3883f03390b3d8938ad05df7aa253dcfa30