diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/EditorChrome.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/EditorChrome.kt
index 4a57648..ec7b8b5 100644
--- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/EditorChrome.kt
+++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/EditorChrome.kt
@@ -157,48 +157,70 @@ fun EditorTopBar(
}
/**
- * When the note was last written, in the bottom corner.
+ * The footer: when the note was last written, and the way out.
*
- * There is no save button. That is right — a note is saved continuously, so a
- * button offering to do what already happened is a lie with a tap attached — but it
- * leaves nothing on screen saying the work is safe, and "closing this saves it" is
- * not a thing anyone should have to be told twice.
+ * **Where the note stands.** There is no save button, and there should not be — a
+ * note is saved continuously, so a button offering to do what already happened is a
+ * lie with a tap attached. But that left nothing on screen saying the work is safe,
+ * and "closing this keeps it" is not a thing anyone should have to be told twice. So
+ * the state says it, as a fact rather than an instruction: Not saved yet → Saving… →
+ * Edited just now is the whole lifecycle, and someone who watches it once never has
+ * to wonder again.
*
- * So the state says it instead, and it says it as a fact rather than an
- * instruction. Not saved yet → Saving… → Edited just now is the whole lifecycle,
- * visible in the corner, and someone who watches it once never has to wonder again.
+ * **The way out.** Down here because of where hands are. Moving the toolbar to the
+ * top took the back arrow with it, which left the only exit from a full-screen
+ * editor in the top-left corner — the furthest point on the display from a
+ * right-handed thumb, and reached over the whole note to get to. The operator hit
+ * that on the first device pass and was right to. So the exit lives in the bottom
+ * corner, which with the keyboard up sits directly above it.
+ *
+ * The top-left arrow stays as well. Two affordances for one action is usually
+ * clutter, but this is the case that earns it: the arrow is what habit, the system
+ * back gesture and TalkBack all expect of a full-screen surface, and removing it
+ * would strand the reflex to strike a duplicate that costs one icon slot.
+ *
+ * A WORD rather than a checkmark, like the overflow menu below and for the same
+ * reason. A tick in a notes app is a checklist item to anyone who has used one, and
+ * "Done" cannot be misread — including aloud.
*
* [DateUtils] rather than a hand-rolled formatter: it is localised, it already
* knows the difference between minutes, hours and yesterday, and getting plurals
* right in every language is not this app's problem to solve twice.
*/
@Composable
-fun EditorSavedLine(
+fun EditorFooter(
updatedAt: String?,
saving: Boolean,
+ onClose: () -> Unit,
modifier: Modifier = Modifier,
) {
Row(
modifier =
modifier
.fillMaxWidth()
- // Rides above the keyboard, like the bar it replaced. The content
- // Column deliberately does not also inset for the IME: Scaffold
- // measures this at its lifted height and passes the inset down.
+ // Rides above the keyboard, like the bar that used to be here. The
+ // content Column deliberately does not also inset for the IME:
+ // Scaffold measures this row at its lifted height and passes the
+ // inset down.
.imePadding()
.navigationBarsPadding()
- .padding(horizontal = 16.dp, vertical = 8.dp),
+ // Asymmetric: the button brings its own padding, the text does not.
+ .padding(start = 16.dp, end = 4.dp),
horizontalArrangement = Arrangement.End,
+ verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = savedLabel(updatedAt, saving),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
+ TextButton(onClick = onClose) {
+ Text(stringResource(R.string.editor_done))
+ }
}
}
-/** The three things [EditorSavedLine] can be saying, in the order it says them. */
+/** The three things the footer can be saying, in the order it says them. */
@Composable
private fun savedLabel(
updatedAt: String?,
diff --git a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt
index d2d6289..1bb2f21 100644
--- a/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt
+++ b/android/app/src/main/java/com/fabledsword/thoughtsync/ui/NoteEditorScreen.kt
@@ -53,8 +53,9 @@ import kotlinx.coroutines.delay
* opening a note reads as the same object growing to fill the display.
*
* No save button, deliberately. Writes are continuous, so a button offering to do
- * what already happened would be a lie with a tap attached; [EditorSavedLine] in the
- * bottom corner says the same thing as a fact instead.
+ * what already happened would be a lie with a tap attached; [EditorFooter] in the
+ * bottom corner says the same thing as a fact instead, beside the Done that
+ * leaves.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@@ -182,16 +183,23 @@ fun NoteEditorScreen(
onAction = onAction,
)
},
- // Where the action bar used to be. A note is saved as it is written,
- // so what belongs at the bottom of the screen is not a control but
- // the answer to "did that land" — see [EditorSavedLine].
- bottomBar = { EditorSavedLine(updatedAt = note.updatedAt, saving = saving) },
+ // Where the action bar used to be, carrying the two things that
+ // belong within reach of a thumb: whether the note is safe, and the
+ // way out. See [EditorFooter] for why the exit is down here and not
+ // only in the top-left corner.
+ bottomBar = {
+ EditorFooter(
+ updatedAt = note.updatedAt,
+ saving = saving,
+ onClose = leave,
+ )
+ },
) { padding ->
Column(
modifier =
Modifier
.fillMaxSize()
- // No imePadding here: EditorSavedLine carries it, so
+ // No imePadding here: EditorFooter carries it, so
// Scaffold measures that row at its keyboard-lifted
// height and the inset already reaches this Column
// through `padding`. Adding it again would inset for the
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 0316b69..b8dd342 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -45,6 +45,7 @@
Not saved yet
Edited %1$s
just now
+ Done
Pin
Unpin
Labels…