Echoes v0.2.0
A big one — new ways to organize and personalize your notes, a much nicer voice note experience, and several real data-integrity fixes found through actual daily use.
✨ New
- Per-note colors — pick a background for any note from seven pastel options (post-it yellow, red, purple, blue, green, orange, white). Text color is never guessed: it's chosen by comparing WCAG contrast ratios against the actual background, so it stays readable in both light and dark app themes. Picking a color triggers a circular reveal animation that sweeps across the whole screen — title bar included.
- Voice notes, reworked — recordings are now inline and positionable in the note body, just like images: write a line, drop in a 25-minute recording, keep writing below it. The recorder panel slides in/out, has a proper red record button, keeps the screen awake while recording, and lets you set a custom timestamp on any recording (long-press it).
- Note search — a search icon in the Home app bar filters the current tab (Notes or Diary) by title, body, or checklist item text.
- Checklist quality-of-life — hide/show completed items, clear all completed items in one tap, and a live "N of M done" counter. Checklists now always open straight into editing — there's nothing to "read" in a working list.
- Contextual formatting toolbar — bold/italic/heading/list/link now appear only when you actually select text, freeing up the space above the body for the voice recorder instead of a permanently-docked ribbon.
- Autosave — edits are saved locally a moment after you stop typing, as a safety net against the back button or the app closing mid-edit.
- List/grid toggle moved to Home, next to search, instead of buried in Settings.
- The note's own title now lives in the app bar — editable in place, no more redundant "Edit note" label with the real title further down.
- Smaller downloads: release APKs are now split per architecture (arm64/armeabi-v7a) alongside the universal one.
Fixed
- Attachments silently failing to reach relays: Primal's Blossom host and nostr.build's NIP-96 host both turned out to actively reject encrypted uploads outright (verified by direct probing) — every image/voice note sent through them was doomed from the start. Swapped the built-in defaults to hosts confirmed to store opaque encrypted blobs correctly.
- A real data-loss race: a background sync cycle uploading an attachment (and deleting the local plaintext) could have its result overwritten by a stale in-memory copy from an open editor's autosave — permanently losing the decryption key while the plaintext was already gone. Fixed at the storage layer (uploaded state can no longer regress to pending), with the in-memory note list and any open editor now kept in sync with what actually lands on disk.
- Voice notes always playing back the first recording when a note had more than one — missing widget identity (
Key) caused Flutter to reuse the wrong player state. - New recordings were stored in a cache directory the OS is allowed to purge at any time — losing not-yet-synced voice notes for good. They now live in persistent app storage.
- Saving a note (✓) now returns you to the note itself instead of kicking you back to the list.