| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| checksums-macos.txt | 2026-03-30 | 96 Bytes | |
| Mini-Diarium-0.4.14-macos.dmg | 2026-03-30 | 20.1 MB | |
| checksums-windows.txt | 2026-03-30 | 196 Bytes | |
| Mini-Diarium-0.4.14-windows.exe | 2026-03-30 | 8.6 MB | |
| Mini-Diarium-0.4.14-windows.msi | 2026-03-30 | 10.4 MB | |
| checksums-linux.txt | 2026-03-30 | 197 Bytes | |
| Mini-Diarium-0.4.14-linux.AppImage | 2026-03-30 | 83.6 MB | |
| Mini-Diarium-0.4.14-linux.deb | 2026-03-30 | 11.1 MB | |
| 0.4.14 source code.tar.gz | 2026-03-29 | 10.3 MB | |
| 0.4.14 source code.zip | 2026-03-29 | 10.5 MB | |
| README.md | 2026-03-29 | 6.8 kB | |
| Totals: 11 Items | 154.5 MB | 12 | |
What's Changed
v0.4.14 delivers full internationalisation (i18n) with Spanish translation and live native-menu locale switching, Markdown file import into the active entry, a benchmarking infrastructure for Rust and frontend, and Flatpak/Flathub distribution. Three editor correctness fixes address word-count HTML-awareness, an entry-not-saved race on fresh dates, and an auto-delete race on newly created entries.
Added
- Benchmarking infrastructure: Rust criterion benchmarks for AES-256-GCM cipher operations, encrypted SQLite queries, and word-count; frontend Vitest bench for Markdown parsing; CI benchmark workflow tracks trends on each merge to master;
benchmarks/CLAUDE.mddomain guide. - Markdown file import into current entry: A new "Import Markdown file" button in the advanced formatting toolbar (next to Insert Image) allows importing a
.mdfile from disk into the active editor. When the current entry is empty the imported content replaces it; when the entry already has content the Markdown is appended after a horizontal-rule separator.marked(GFM mode) handles Markdown-to-HTML conversion on the frontend;DOMPurifysanitizes the output via thepostprocesshook before it reaches TipTap. File size is capped at 1 MB; import errors surface as a dismissible banner in the editor footer. - i18n / Translation support: All ~220 hardcoded English UI strings are extracted into a typed locale file (
src/i18n/locales/en.ts) using@solid-primitives/i18n. The system is designed for community-contributed translations — add a JSON file tosrc/i18n/locales/and runbun run validate:localesto check completeness. Seedocs/TRANSLATIONS.mdfor the full translator guide covering interpolation syntax, plural key pairs, and PR instructions.- Language selector in Preferences: A Language dropdown is now available in Preferences → General. The locale is stored in user preferences and applied reactively at runtime (no restart needed).
- Spanish (Español) translation: full translation of all UI strings into Spanish (
src/i18n/locales/es.json). Select "Español" in Preferences → General → Language. - Native OS menu i18n: The native app menu (Navigation, Diary, and all items within) now updates to the selected language in real time without an app restart. A new
update_menu_localeTauri command stores all translatableMenuItemandSubmenuhandles in aTranslatableMenuItemsmanaged-state struct and callsset_text()on each. Adding a new community locale requires adding its ~15 menu strings to the match block insrc-tauri/src/commands/menu.rsalongside the JSON locale file.
- Flatpak / Flathub distribution: The release process is extended to automatically publish Mini Diarium to Flathub on each release. A new
flathub-publish.ymlworkflow generates offline-vendored Cargo and Node source lists, patches the Flatpak manifest with the release tag and commit SHA, and opens a PR against the Flathub repository. The Flatpak manifest (flatpak/com.minidiarium.yml) builds vianpm ci --offline→npm run build→cargo build --release, bypassing the Tauri CLI so Bun is not required in the sandbox. Desktop entry, AppStream metainfo, and icon installs are all included. One-time manual setup (screenshots, local manifest test, initial Flathub submission PR) is documented indocs/RELEASING.md.
Changed
- Benchmarks revised to cover actual hot paths: added
db_update_entry(the real auto-save path replacingdb_insert_entryas primary write bench),db_get_all_entry_datesat 100 and 500 entries,auth_argon2group for Argon2id wrap/unwrap (the unlock path,sample_size(10)); scaleddb_get_allcorpus to 500 entries alongside 100; replaced synthetic word-count input with realistic TipTap HTML; added context comments tocipher_bench.
Fixed
- Word count live updates and HTML-awareness: two bugs corrected. (1) The word counter now updates on every keystroke —
handleContentUpdatecallssetWordCount(countWordsFromText(editor.getText()))on each TipTap transaction so the counter reflects the current document without requiring a save. (2) Load-time word count calculations previously split raw HTML with a whitespace regex, inflating the count to thousands of "words" for entries containing embedded base64 images. All four calculation sites inEditorPanel.tsxnow use a newcountWordsInHtmlhelper (src/lib/wordcount.ts) that strips all HTML tags (including<img src="data:…">in full) before splitting — consistent with the backendcount_words/strip_html_tagsimplementation.editor.getText()(TipTap's own plain-text extractor) is used for the live path;countWordsInHtmlis used as a fallback and for all load-time sites. - Entry-not-saved race on fresh date: typing on a date with no prior entries and locking the journal before the
createEntryIPC call returned would leave the entry blank after unlock. Two windows existed: (1)pendingEntryIdwas stillnullwhen the cleanup callback fired so the normal save path was skipped entirely; (2)createEntryreturned andsetPendingEntryIdwas set but the 500 ms debounce hadn't fired beforedebouncedSave.cancel()was called. Fixed by extracting a sharedstartEntryCreationhelper that stores the in-flight Promise in apendingCreationPromiseref, and updating theregisterCleanupCallbackto await that Promise and callsaveEntrydirectly — with the DB still open — before returning. Ghost entries created during the race with no real content are cleaned up viadeleteEntryIfEmpty. - Auto-delete race on newly created blank entry: clicking "+" and typing within 500 ms could delete the just-created entry before the first keystroke was saved. The race:
addEntry()cancels the old debounce synchronously, but DiaryEditor'screateEffect(which callsonSetContent(isEmpty=true)) runs as a SolidJS microtask at the followingawait getAllEntryDates()— aftercancel()has already returned.onSetContentthen re-queued a fresh 500 ms debounce that was never cancelled, racing against the user's first input. Fixed with ajustCreatedEntryIdmutable ref set inaddEntry()after the new entry's ID is known; theonSetContentcallback skips queuing the auto-delete debounce when the active entry ID matches. The ref is cleared on first real user input (handleContentUpdateorhandleTitleInput). Blank entries loaded from the DB (e.g. on navigation or date switch-back) are unaffected —justCreatedEntryIdis null for those paths and the auto-delete debounce fires normally.