Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
984da3c61c | ||
|
|
d562cf85f2 |
No files matched your search
@@ -7,6 +7,12 @@ All notable changes to this project are documented here. The format follows
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
- With 3-button navigation, the navigation bar no longer covers the last home
|
||||
search results, and in landscape it no longer covers the home screen, the
|
||||
task list or the home top bar's buttons. The task details and editor no
|
||||
longer leave an empty gap between the open keyboard and the text (#152).
|
||||
|
||||
## [1.3.1] - 2026-11-09
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package de.jeanlucmakiola.agendula.ui.common
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Pads by the start/end of a scaffold's [inner] padding and consumes it, so a
|
||||
* side navigation bar or cutout (3-button nav in landscape) is cleared once.
|
||||
*/
|
||||
@Composable
|
||||
fun Modifier.sideInsetsPadding(inner: PaddingValues): Modifier {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val sides = PaddingValues(
|
||||
start = inner.calculateStartPadding(layoutDirection),
|
||||
top = 0.dp,
|
||||
end = inner.calculateEndPadding(layoutDirection),
|
||||
bottom = 0.dp,
|
||||
)
|
||||
return this.padding(sides).consumeWindowInsets(sides)
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -268,6 +269,9 @@ private fun DetailBody(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(inner)
|
||||
// Consume the bar insets so imePadding adds only what the keyboard
|
||||
// covers beyond them.
|
||||
.consumeWindowInsets(inner)
|
||||
// Shrink the scroll viewport by the keyboard so the focused add-subtask
|
||||
// field scrolls into view above the IME instead of being hidden.
|
||||
.imePadding()
|
||||
|
||||
@@ -57,6 +57,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
@@ -219,7 +220,9 @@ fun TaskEditScreen(
|
||||
viewModel = viewModel,
|
||||
scroll = scroll,
|
||||
onTitleBottom = { titleBottom = it },
|
||||
modifier = Modifier.padding(inner),
|
||||
// Consumed so EditContent's imePadding adds only what the keyboard
|
||||
// covers beyond the bars.
|
||||
modifier = Modifier.padding(inner).consumeWindowInsets(inner),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,16 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.displayCutout
|
||||
import androidx.compose.foundation.layout.ime
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.union
|
||||
import androidx.compose.foundation.layout.windowInsetsBottomHeight
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
@@ -99,6 +108,7 @@ import de.jeanlucmakiola.agendula.ui.common.LocalUse24HourFormat
|
||||
import de.jeanlucmakiola.agendula.ui.common.ShapedActionButton
|
||||
import de.jeanlucmakiola.agendula.ui.common.SyncPullBox
|
||||
import de.jeanlucmakiola.agendula.ui.common.priorityAccent
|
||||
import de.jeanlucmakiola.agendula.ui.common.sideInsetsPadding
|
||||
import de.jeanlucmakiola.agendula.ui.tasklist.priorityLabel
|
||||
import de.jeanlucmakiola.floret.components.positionOf
|
||||
import de.jeanlucmakiola.floret.time.formatDateTimeCompact
|
||||
@@ -180,7 +190,10 @@ fun ListsScreen(
|
||||
available = syncAvailable && !searchActive,
|
||||
syncing = syncing,
|
||||
onSync = viewModel::syncAll,
|
||||
modifier = Modifier.fillMaxSize().padding(top = inner.calculateTopPadding()),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = inner.calculateTopPadding())
|
||||
.sideInsetsPadding(inner),
|
||||
) {
|
||||
when (val s = state) {
|
||||
ListsUiState.Loading -> Unit // brief; avoids a flash before first emission
|
||||
@@ -513,7 +526,10 @@ private fun HomeTopBar(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.statusBarsPadding()
|
||||
.windowInsetsPadding(
|
||||
WindowInsets.systemBars.union(WindowInsets.displayCutout)
|
||||
.only(WindowInsetsSides.Top + WindowInsetsSides.Horizontal),
|
||||
)
|
||||
.height(72.dp)
|
||||
.padding(horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@@ -672,10 +688,14 @@ private fun SearchResults(
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// The last result scrolls clear of the navigation bar and the keyboard.
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
items(results, key = { it.occurrenceKey }) { task ->
|
||||
UpcomingRow(task = task, onClick = { onOpenTask(task) })
|
||||
}
|
||||
item(key = "bottom-inset") {
|
||||
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars.union(WindowInsets.ime)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ import de.jeanlucmakiola.agendula.ui.common.LocalUse24HourFormat
|
||||
import de.jeanlucmakiola.agendula.ui.common.SyncPullBox
|
||||
import de.jeanlucmakiola.agendula.ui.common.ignoringEdgeSwipes
|
||||
import de.jeanlucmakiola.agendula.ui.common.priorityAccent
|
||||
import de.jeanlucmakiola.agendula.ui.common.sideInsetsPadding
|
||||
import de.jeanlucmakiola.agendula.ui.lists.ListEditorSheet
|
||||
import de.jeanlucmakiola.agendula.ui.lists.listWriteFailureMessage
|
||||
import de.jeanlucmakiola.agendula.ui.lists.ListWriteFailure
|
||||
@@ -250,7 +251,7 @@ fun TaskListScreen(
|
||||
}
|
||||
},
|
||||
) { inner ->
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Box(modifier = Modifier.fillMaxSize().sideInsetsPadding(inner)) {
|
||||
SyncPullBox(
|
||||
available = syncAvailable,
|
||||
syncing = syncing,
|
||||
@@ -260,7 +261,10 @@ fun TaskListScreen(
|
||||
) {
|
||||
when (val s = state) {
|
||||
TaskListUiState.Loading -> Unit // brief; avoids a flash before first emission
|
||||
TaskListUiState.Failure -> CenteredMessage(stringResource(R.string.task_list_failure), inner)
|
||||
TaskListUiState.Failure -> CenteredMessage(
|
||||
stringResource(R.string.task_list_failure),
|
||||
PaddingValues(top = inner.calculateTopPadding(), bottom = inner.calculateBottomPadding()),
|
||||
)
|
||||
is TaskListUiState.Content -> TaskListBody(
|
||||
s, filter, inner, onOpenTask, onRequestDelete, viewModel,
|
||||
onClearCompleted = if (listId != null && list?.isReadOnly != true) ({ confirmClear = true }) else null,
|
||||
|
||||
Reference in new issue
Block a user