Tags: fjrevoredo/mini-diarium
Tags
0.4.8 ### Changed - **Vite 8 upgrade**: bumped `vite` from 7.3.1 → 8.0.0 and `jsdom` from 28.1.0 → 29.0.0. Converted `manualChunks` in `vite.config.ts` from object to function form, as required by Vite 8's rolldown bundler. Vendor chunk output (`vendor-solid`, `vendor-tiptap`, `vendor-ui`) is unchanged. - **Image alignment**: alignment controls now apply to images as well as text blocks, using a container model that makes future block types (tables, etc.) trivially alignable without per-node workarounds. Each image is wrapped in a `<figure class="image-container">` element; `TextAlign` sets `text-align` on the container and the inner `<img>` responds as `display: inline-block`. Existing bare `<img>` entries load correctly via a parse fallback (no migration needed).
0.4.7 ### Added - **Editor alignment controls**: paragraphs and headings can now be aligned **left**, **center**, **right**, or **justified** using four new toolbar buttons. The controls live in the advanced toolbar (requires **Preferences → Writing → Show advanced formatting toolbar**). Alignment is stored as an inline `style="text-align: …"` attribute on the block element so it round-trips cleanly through save/load. Existing entries with no alignment metadata continue to render exactly as before. JSON export preserves the stored HTML unchanged; Markdown export degrades alignment gracefully without dropping content. Closes [#54](#54). - **Entry timestamps**: the editor can now show the `date_created` and `date_updated` timestamps for the current entry below the title, formatted using the OS locale. Opt-in via **Preferences → Writing → Show entry timestamps** (disabled by default). The updated timestamp is only shown when it differs from the created timestamp. Both timestamps are hidden when "Hide Titles" is enabled. - **Theme overrides (advanced)**: advanced users can now override individual theme color tokens. Open **Preferences → General → Theme Overrides**, enter a JSON object with `light` and/or `dark` keys mapping CSS variable names (`--bg-primary`, `--text-primary`, etc.) to values, then click **Apply Overrides**. Overrides persist in `localStorage` and are layered on top of the active built-in theme automatically at startup. The documented token contract (`--bg-*`, `--text-*`, `--border-*`, `--interactive-*`, `--btn-*`, `--editor-*`, `--status-*`, `--spinner-color`, `--overlay-bg`, `--shadow-*`) is supported; unknown tokens are silently ignored. **Reset to Default** removes all overrides immediately. `auto` theme resolution continues to work correctly with overrides applied on top of the resolved light/dark theme. ### Fixed - **Dark mode editor body text too dark**: two layered issues caused editor body text to appear dark-on-dark in dark mode. (1) `--editor-body-text` in the `.dark` token set was hardcoded to `#e5e7eb` (gray-200) instead of `var(--text-primary)` (`#f9fafb`); the token now follows `--text-primary` consistently in both themes. (2) The `color` rule was declared on `.ProseMirror` (single-class specificity), which lost to `@tailwindcss/typography`'s `.prose` rule injected later in the stylesheet. The `color` declaration has been moved to `.ProseMirror.journal-editor-content` (double-class specificity), exactly as was already done for `font-size` for the same reason. - **Heading-style dropdown focus ring in editor toolbar**: the text-style `<select>` was using the raw palette class `focus:ring-blue-500` instead of the semantic `focus:ring-[var(--border-focus)]` token introduced during theme hardening. ### Changed - **Theme system hardening**: all raw palette classes (`bg-blue-600`, `bg-red-600`, `border-blue-600`, `text-blue-500`, `text-red-500`, etc.) have been replaced with semantic CSS variable tokens and utility classes across 13 component files and `src/styles/editor.css`. New tokens added to `src/index.css`: `--btn-primary-*`, `--btn-destructive-*`, `--btn-active-*`, `--spinner-color` (button/spinner family), and `--editor-*` (editor content family). New utility classes: `.interactive-primary`, `.interactive-destructive`, `.text-destructive`, `.btn-active`, `.spinner-border`, `.text-interactive`, `.bg-interactive`. `editor.css` now uses only CSS variables with no `.dark`-specific override blocks. This task establishes the stable token contract for future user theme overrides (Task 69).
0.4.6
### Added
- **Automatic WinGet publishing**: every published release now automatically submits a WinGet manifest update to the community repository (`microsoft/winget-pkgs`), opening a pull request for the new version. The workflow triggers on `release.published` events (not drafts), handles the `vX.Y.Z` tag format by stripping the `v` prefix, verifies the Windows asset `Mini-Diarium-{VERSION}-windows.exe` exists, and uses `wingetcreate.exe --submit` to auto-submit the PR. Users can install/upgrade via `winget install fjrevoredo.MiniDiarium` and `winget upgrade fjrevoredo.MiniDiarium`. Requires the `WINGET_TOKEN` repository secret to be configured.
### Fixed
- **Dark theme form-control contrast on Linux**: text inside password fields, plain text inputs, and native `<select>` dropdowns is now always readable in dark mode regardless of the active GTK theme. Added `color-scheme: light` / `color-scheme: dark` to `:root` / `.dark` so WebKit/GTK respects the app's color scheme for native form-control rendering. Added a zero-specificity `:where()` baseline that sets `background-color: var(--bg-primary)` and `color: var(--text-primary)` on all non-checkbox/radio/range/file inputs, selects, and textareas — any UnoCSS utility class (`bg-primary`, `bg-tertiary`, `disabled:bg-tertiary`, etc.) overrides it. Auth-screen password inputs in `PasswordPrompt` and `PasswordCreation` now carry explicit `bg-primary` classes. Fixes [#48](#48).
- **About dialog now accessible from the native menu at any auth state**: the `AboutOverlay` and its `menu-about` listener have been lifted from `MainLayout` (unlocked-only) up to `App` (always mounted). Help → About Mini Diarium now opens correctly from the journal picker, password prompt, and creation screens — not just when the journal is unlocked.
- **E2E: title persistence assertion now waits for async DB load**: replaced `waitForDisplayed` + immediate `getValue` with a `waitUntil` poll, preventing a race between the WebDriver assertion and the async `loadEntriesForDate` round-trip to the backend.
- **Backup rotation limit reduced from 50 to 30**: the `MAX_BACKUPS` constant has been lowered and a new test `test_backup_and_rotate_repeated_unlocks()` verifies that repeated unlock operations never allow the backup count to exceed the configured cap. All test assertions now use the constant instead of hardcoded values.
0.4.5 ### Added - **Advanced tab in Preferences** with a "Generate Debug Dump" button — exports a privacy-safe JSON diagnostic file (app version, OS/platform, schema version, entry counts, auth method types, backup count, plugin count, preferences); no entry content, passwords, or key material is ever included - **Month/year picker in calendar header**: clicking the month/year label in the sidebar calendar now toggles an inline month picker. The calendar body switches to a 3×4 month grid with year-step arrows; selecting a month jumps directly to that month and closes the picker. The currently displayed month is highlighted in the grid. No new dependencies. (#43) - **Delete entry button for multi-entry days**: a "−" button now appears next to the "+" button in the entry navigator when a day has more than one entry. Clicking "−" opens a confirmation dialog ("Delete Entry" — "Are you sure you want to delete this entry?") and, if confirmed, deletes the currently selected entry and navigates to the next available entry for the same day (staying at the same index, clamping to bounds if the last entry was deleted). The button is only visible when the day has multiple entries and is disabled while an entry is being created. (#43) ### Changed - **Unified user-facing terminology to "Journal"**: all UI text, error messages, and documentation now consistently use "Journal" instead of the mixed "diary"/"journal" wording; internal Tauri command names and filesystem identifiers (`diary.db`) are preserved for compatibility (issue #46) - **Auto-select last-used journal on startup**: the app now skips the Journal Picker when a previously used journal is known (`active_journal_id` set in config). `initializeAuth()` calls `refreshAuthState()` directly and transitions to the password prompt (or unlocked state if already unlocked). The Journal Picker is shown only on a fresh install or when no active journal is configured. (#43) - **Reduced password minimum length to 1 character:** the 8-character minimum has been removed. Passwords must be non-empty; a visual strength indicator now guides users with feedback on weak/medium/strong passwords. Very weak passwords show an additional warning banner with recommendations. This aligns with the cryptographic reality that Argon2id protects any password length, while giving users control over their security tradeoffs. (#43) - **Website SEO/GEO follow-up pass (2026-03-06)**: replaced the 4.5 MB hero GIF with compressed MP4/WebM demo media plus a poster image, switched the stylesheet to inline-critical + non-blocking loading, updated title/description metadata for search intent, replaced the social preview SVG with a PNG, changed the hero download CTAs to distinct Windows/macOS/Linux direct installer links with ARIA labels, added apex-canonical redirect/cache parity to the nginx reference config, and documented post-release Search Console/IndexNow/Cloudflare ops in the release guide. ### Fixed - **Window position flash on startup**: the main window no longer flashes at the default position before jumping to the saved position. The window is now created hidden (`"visible": false` in `tauri.conf.json`) and shown explicitly after `tauri-plugin-window-state` has restored the saved bounds. (#43) - **"+" add-entry button**: the button to create an additional entry for the same day now correctly guards against concurrent calls using a reactive signal. The button is disabled while creation is in flight, preventing duplicate entries from rapid clicks. Errors are no longer silently swallowed. (#43) - **"Go to today" calendar button**: clicking the calendar icon in the sidebar now correctly navigates the calendar month view. A `createEffect` in `Calendar.tsx` watches `selectedDate` and syncs `currentMonth` whenever the selected date falls outside the currently displayed month — fixing all month-navigation cases including "go to today", go-to-date overlay, and day/month menu navigation. (#43) - **Clicking adjacent-month days in calendar**: days from the previous or next month shown in the calendar grid are now clickable. The `isCurrentMonth` guard has been removed from `handleDayClick` and the `disabled` attribute; only future dates (when the preference is off) remain disabled. (#43) - **Sidebar header border alignment**: the sidebar title bar and the main header bar now share the same rendered height (64 px). Previously the sidebar's text-only header was 12 px shorter than the main header whose icon buttons set the height, causing the bottom borders to visually misalign. (#43) - **"Go to today" button alignment**: the button in the sidebar was right-aligned (`justify-end`) while the calendar below it is left-aligned. Changed to `justify-start` so the button aligns with the calendar's left edge. (#43) - **Settings tab active state on light theme**: the active tab in Preferences used hardcoded Tailwind classes (`bg-blue-100 text-blue-700`) that could render with low contrast. Replaced with CSS-variable classes (`bg-active text-primary`) that correctly follow the current theme in both light and dark mode. (#43) - **Editor placeholder showing "Loading…"**: TipTap's placeholder extension showed "Loading…" whenever the editor was empty during an async entry load, which could flicker on fast navigations. Placeholders are now always static ("Title (optional)" / "What's on your mind today?"). (#43) - **Calendar month navigation broken by reactive loop**: clicking the previous/next month buttons had no effect because the `createEffect` that syncs `currentMonth` to `selectedDate` was also reading `currentMonth()` as a reactive dependency — causing it to immediately reset the month back. Fixed by using `untrack(currentMonth)` so the effect only re-runs when `selectedDate` changes. - **"+" button creates spurious entry on empty day**: pressing "+" when no content existed would create and immediately delete an empty entry (visible briefly as a dot in the calendar). The button is now disabled unless the current entry has body content. Contextual tooltip text explains why the button is disabled ("Write something first to add another entry for this day") or what it does when enabled ("Add another entry for this day"). - **New entry auto-deleted 500 ms after creation**: after creating a new entry via "+", `setContent('')` caused TipTap to fire `onUpdate` synchronously with empty content, scheduling a debounced save that would delete the blank entry. An explicit `debouncedSave.cancel()` now runs immediately after state is reset to prevent this. - **Multi-entry day counter order**: entries for a day are now displayed in chronological order (oldest = 1/N, newest = N/N). Previously the backend's newest-first ordering made the counter confusingly start at 1 for the most-recent entry. New entries created via "+" always land at position N/N. Opening a multi-entry day now navigates to the newest entry (N/N) instead of the oldest. - **Empty entries persist on lock/switch**: empty entries created with the "+" button now correctly delete themselves when the diary is locked or when switching journals without adding content. Previously, the empty entry would remain in the database until the user navigated to a different entry. The fix implements a pre-lock event pattern that ensures `saveCurrentById()` (which deletes empty entries) is called before the database is locked, covering all lock paths (manual button, OS session lock, and journal switching).
v0.4.4 ## [0.4.4] — 03-03-2026 ### Added - **Text highlight formatting** in the advanced editor toolbar (`Ctrl/Cmd+Shift+H`). Highlighted text is rendered with a yellow background (theme-safe in light and dark mode). HTML `<mark>` tags are preserved in storage and JSON export; Markdown export strips the tags and keeps the text. (#41) - **Embedded images in the editor**: images can now be inserted into diary entries via drag-and-drop, clipboard paste (Ctrl/Cmd+V), or the new "Insert image" button in the advanced toolbar. Images are resized client-side (max 1200 × 1200 px, JPEG 85% quality) before embedding as base64 data URIs in the encrypted entry HTML. Plaintext never touches disk. Note: JSON/Markdown exports will include the full base64 strings and may be large for entries with many images. (#40) - **Configurable editor font size** (12–24 px) in Preferences → Writing (#30)
0.4.3
### Added
- **Expanded rich text toolbar**: heading selector (Normal / H1 / H2 / H3), Underline, Strikethrough, Blockquote, Inline Code, and Horizontal Rule buttons added to the editor toolbar. Markdown export now correctly converts strikethrough (`~~`), blockquotes (`>`), inline code (`` ` ``), and fenced code blocks (` ``` `).
- **Minimal toolbar by default**: a new **Show advanced formatting toolbar** preference (Preferences → Writing) controls whether the extended toolbar controls are visible. The default is off — the toolbar shows only Bold, Italic, Bullet List, and Ordered List. Toggling the setting on reveals the full toolbar (headings, Underline, Strikethrough, Blockquote, Inline Code, Horizontal Rule) immediately without restarting. Rendering of existing content and import/export behavior are unaffected by this setting.
- **Configurable auto-lock timeout**: a new **Auto-Lock** section in Preferences → Security lets you enable automatic locking after a period of inactivity. When enabled, any mouse movement, key press, click, touch, or scroll resets the idle timer; the diary locks automatically once the timeout (1–999 seconds, default 300) expires with no activity. The setting is stored in `localStorage` and takes effect immediately without restarting.
- **Auto-lock on macOS screen lock**: the diary now auto-locks when the display sleeps, the system enters sleep, or the user explicitly locks the screen (Cmd+Ctrl+Q / Apple menu → Lock Screen) on macOS. Uses `NSWorkspaceScreensDidSleepNotification`, `NSWorkspaceWillSleepNotification`, and `com.apple.screenIsLocked` via `NSDistributedNotificationCenter`.
- **Multiple entries per day**: each diary day can now hold any number of independent entries. A `←` / `→` navigation bar appears above the editor when a day has more than one entry, showing the current position (e.g. `2 / 3`). A `+` button on the right side of the bar creates a new blank entry for the same date. Single-entry days look and behave exactly as before — the navigation bar is hidden.
- **Entry identity**: each entry now carries a stable `INTEGER PRIMARY KEY AUTOINCREMENT` id. Saves, deletes, and exports all reference entries by id rather than by date.
### Changed
- **Database schema bumped to v5**: the `entries` table gains an `id INTEGER PRIMARY KEY AUTOINCREMENT` column; the old `date TEXT PRIMARY KEY` unique constraint is replaced by a non-unique `idx_entries_date` index. Existing databases are migrated automatically on first launch (entries are preserved in date-creation order).
- **Import no longer merges same-date entries**: previously, importing a file with entries that matched an existing date would merge the content. Imports now always create a new entry, consistent with the multiple-entries-per-day model. The `entries_merged` field has been removed from the import result.
- **JSON export format changed to an array**: the exported JSON file now contains an `"entries"` array (each object includes an `"id"` field) instead of a date-keyed object. This format can represent multiple entries per day correctly. The `"metadata"` wrapper (`application`, `version`, `exportedAt`) is unchanged.
- **Markdown export groups multiple entries per day**: when a day has more than one entry, each entry appears as a `### Entry N` sub-heading (or `### {title}` if the entry has a title) under the day's `## YYYY-MM-DD` heading.
### Fixed
- **Streak calculation now counts distinct days**: with multiple entries per date, the statistics streak algorithm now deduplicates dates before computing streaks, ensuring one active day is counted once regardless of how many entries it contains.
v0.4.2 ### Added - **Journal Picker as the outermost app layer**: the app now opens to a **Journal Picker** screen before any diary authentication. The picker lists all configured journals and lets you open, rename, or remove any of them without authenticating first. You can also create a new diary (picks a folder, names it, then goes to password creation) or open an existing `diary.db` from any folder — both flows that were previously fragmented across the first-launch screen and Preferences > Journals. On a shared device, each person can select their own diary without having to step through someone else's lock screen. - **"← Back to Journals" link** on both `PasswordCreation` and `PasswordPrompt` screens, letting users navigate back to the journal picker without locking or restarting the app. - **Removing the last journal is now allowed**: the backend no longer blocks removal of the sole remaining journal; the picker simply shows the empty state with the two Add buttons so the user can configure a new one. ### Changed - **Journal management moved to the Journal Picker**: the **Journals** tab has been removed from Preferences. All journal operations (add, rename, remove, open) are available on the pre-auth picker screen. Auth methods, password changes, and data settings remain in their respective Preferences tabs unchanged. - **Auth flow**: `initializeAuth()` now always routes to `'journal-select'` on startup (instead of probing the diary path immediately); `refreshAuthState()` is called only after the user selects a journal. This eliminates the single-user assumption baked into the previous startup sequence. - **Release build profile**: added `[profile.release]` with `opt-level = 3` and `lto = true` to `Cargo.toml` for smaller, faster distribution binaries. - **Website SEO/GEO refresh (2026)**: upgraded metadata and machine-readable signals for search and AI retrieval. Added robots snippet controls, richer Open Graph/Twitter tags (`og:site_name`, `og:locale`, image dimensions, account attribution), expanded JSON-LD graph (`SoftwareApplication` + `Organization` + `WebSite` + `FAQPage` with `softwareVersion`/`dateModified`), added extraction-friendly **Quick facts** + **FAQ** sections, introduced a dedicated **Release status** block with explicit last-updated date, replaced placeholder `href="#"` links, updated sitemap to use `<lastmod>`, and added a lightweight social preview asset (`website/assets/og-cover.svg`). - **Website compatibility and cache hardening (2026-02-26)**: added a broader favicon set (`favicon.ico`, 16/32/128 PNG, `apple-touch-icon`), published `ai-crawlers.txt` and `llms.txt` with footer/README discoverability, and introduced content-hash fingerprinting for website CSS/JS (`website:fingerprint`) so nginx can safely keep `immutable` only for hashed assets while unfingerprinted files use short TTL caching.
PreviousNext