release: v2.13.0 — special dates, custom fonts, quick-switch, es/it translations #58

Merged
makiolaj merged 65 commits from release/v2.13.0 into main 2026-07-03 14:47:43 +00:00
2 changed files with 52 additions and 23 deletions
Showing only changes of commit 0a89ff9d0e - Show all commits

View File

@@ -28,6 +28,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -57,10 +58,16 @@ fun positionOf(index: Int, count: Int): Position = when {
} }
/** /**
* The app's standard full-screen list scaffold: a collapsing [LargeTopAppBar] * The app's standard full-screen list scaffold. By default a collapsing
* whose title shrinks into the bar (next to the back button) as the content * [LargeTopAppBar] whose title shrinks into the bar (next to the back button) as
* scrolls. Content is a scrollable column that feeds the toolbar via nested * the content scrolls — used by Settings and the calendar manager, where the
* scroll. Used by Settings and the calendar manager so they share one shell. * large header sets the page. Content is a scrollable column that feeds the
* toolbar via nested scroll.
*
* Set [largeTopBar] to false for a pinned, single-line [TopAppBar] instead: the
* title sits in the bar from the start, with no expanded header to scroll past.
* Preferred for selection pickers, where the tall header is just wasted space
* above the options.
*/ */
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -68,12 +75,16 @@ fun CollapsingScaffold(
title: String, title: String,
onBack: () -> Unit, onBack: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
largeTopBar: Boolean = true,
snackbarHost: @Composable () -> Unit = {}, snackbarHost: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
content: @Composable ColumnScope.() -> Unit, content: @Composable ColumnScope.() -> Unit,
) { ) {
val scrollBehavior = val scrollBehavior = if (largeTopBar) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()) TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
} else {
TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
}
Scaffold( Scaffold(
modifier = modifier modifier = modifier
.predictiveBack(onBack = onBack) .predictiveBack(onBack = onBack)
@@ -81,22 +92,34 @@ fun CollapsingScaffold(
.background(MaterialTheme.colorScheme.surface) .background(MaterialTheme.colorScheme.surface)
.nestedScroll(scrollBehavior.nestedScrollConnection), .nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
LargeTopAppBar( val navigationIcon = @Composable {
title = { Text(title) }, IconButton(onClick = onBack) {
navigationIcon = { Icon(
IconButton(onClick = onBack) { Icons.AutoMirrored.Filled.ArrowBack,
Icon( contentDescription = stringResource(R.string.settings_back),
Icons.AutoMirrored.Filled.ArrowBack, )
contentDescription = stringResource(R.string.settings_back), }
) }
} val colors = TopAppBarDefaults.topAppBarColors(
}, scrolledContainerColor = MaterialTheme.colorScheme.surface,
actions = actions,
scrollBehavior = scrollBehavior,
colors = TopAppBarDefaults.topAppBarColors(
scrolledContainerColor = MaterialTheme.colorScheme.surface,
),
) )
if (largeTopBar) {
LargeTopAppBar(
title = { Text(title) },
navigationIcon = navigationIcon,
actions = actions,
scrollBehavior = scrollBehavior,
colors = colors,
)
} else {
TopAppBar(
title = { Text(title) },
navigationIcon = navigationIcon,
actions = actions,
scrollBehavior = scrollBehavior,
colors = colors,
)
}
}, },
snackbarHost = snackbarHost, snackbarHost = snackbarHost,
) { innerPadding -> ) { innerPadding ->

View File

@@ -43,8 +43,9 @@ import de.jeanlucmakiola.calendula.ui.agenda.AgendaRange
/** /**
* Shared full-screen scaffold for selection pickers: a full-bleed [Dialog] that * Shared full-screen scaffold for selection pickers: a full-bleed [Dialog] that
* reuses the app's [CollapsingScaffold] (collapsing title + back button), so a * reuses the app's [CollapsingScaffold] (back button + full width), but with a
* picker is visually identical to a Settings sub-page and uses the full width. * pinned single-line title rather than the large collapsing header — a picker is
* a short list, so the tall header would only be empty space to scroll past.
* [content] places the connected grouped rows; selecting one calls [onDismiss]. * [content] places the connected grouped rows; selecting one calls [onDismiss].
*/ */
@Composable @Composable
@@ -69,7 +70,12 @@ fun FullScreenPicker(
(view.parent as? DialogWindowProvider)?.window (view.parent as? DialogWindowProvider)?.window
?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) ?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
} }
CollapsingScaffold(title = title, onBack = onDismiss, content = content) CollapsingScaffold(
title = title,
onBack = onDismiss,
largeTopBar = false,
content = content,
)
} }
} }