Commit graph

19637 commits

Author SHA1 Message Date
Johannes Millan
271db4fab5 feat: improve initial render
- fix(ui): delay material icons until font is ready
- fix(side-nav): wire up tree readiness gate and clean up dead code
- fix(ui): hide icon ligature fallback text
- fix(side-nav): defer data-driven startup content
- fix(side-nav): stabilize magic nav initial render
2026-03-26 17:43:04 +01:00
Johannes Millan
5d37b98986 fix(note): use neutral close button in fullscreen editor 2026-03-26 17:43:04 +01:00
Johannes Millan
215cb6823c fix(layout): improve add task bar task reveal timing 2026-03-26 17:43:04 +01:00
Johannes Millan
9472e8986f fix(mobile): prevent scroll-to-top when closing add-task bar on touch devices 2026-03-26 17:43:04 +01:00
Johannes Millan
38a822140c fix(tasks): hide hover controls on touch-only devices 2026-03-26 17:43:04 +01:00
Johannes Millan
256104d856 fix(tasks): save task title on mobile when tapping outside bottom panel
Force-blur active input on backdrop click so pending edits are saved
before the bottom sheet dismisses and destroys the component tree.
2026-03-26 17:43:04 +01:00
Johannes Millan
26c884935f fix(onboarding): suppress persistence snack during initial preset selection
isOnboardingInProgress() only covered the phase after preset selection.
Fresh users on the preset selection screen still saw the snack because
ONBOARDING_PRESET_DONE was not yet set. Extend the check to also return
true when neither preset nor skip-tour flags are set.
2026-03-26 17:43:04 +01:00
Johannes Millan
25051d2899 fix(plugins): use loopback redirect and system browser for Google OAuth
Google's Desktop OAuth client requires loopback redirect URIs
(http://127.0.0.1:<port>) and blocks embedded webviews. This replaces
the custom URI scheme + BrowserWindow approach with a temporary loopback
HTTP server and shell.openExternal for the system browser.

- Add PLUGIN_OAUTH_PREPARE IPC to start loopback server and return port
- Open auth URL in system browser instead of Electron BrowserWindow
- Make getRedirectUri() async to support IPC port retrieval
- Validate OAuth config before starting loopback server to prevent leaks
- Force 200 status on OPTIONS preflight responses in CORS bypass
2026-03-26 17:43:04 +01:00
Johannes Millan
d328e80ab8 fix(build): add dotenv as explicit devDependency for Docker builds
tools/load-env.js requires dotenv directly but it was only available as
a transitive dependency of @dotenv-run/cli. This caused the Docker image
publish to fail when npm ci couldn't resolve it. Also regenerates
package-lock.json to fix stale lock file entries.
2026-03-26 17:43:04 +01:00
Johannes Millan
b30b3e04b7 fix(validation): relax stale-reference validation on archived tasks (#6270)
Stale references (projectId/tagId/repeatCfgId pointing to deleted
entities) in archived tasks are now treated as harmless historical
records instead of validation failures.

- Validation: logs stale archive refs as info, does not fail
- Repair: no longer mutates stale refs in archives (structural fixes
  like missing projectId→INBOX and TODAY_TAG stripping are kept)
- Restore: normalizeRestoredTask() cleans stale refs when restoring
  archived tasks to active state (INBOX reassignment, tag stripping,
  TODAY_TAG removal, repeatCfgId clearing)
2026-03-26 17:43:04 +01:00
Johannes Millan
a33ffa35a2 feat(tasks): dynamic strikethrough gesture for mobile swipe-right
Add swipe-right-to-done gesture with animated strikethrough line that
follows the finger, checkmark scale-up on trigger, and smooth visual
bridging so the gesture visuals persist until the CSS isDone class
takes effect.
2026-03-26 17:43:04 +01:00
Johannes Millan
4e6bf73859 fix(sync): prevent false IN_SYNC status when sync errors occur (#6571)
Multiple error paths in the sync pipeline silently swallowed errors,
allowing sync to report IN_SYNC while clients had diverged state.
This caused permanent data loss — tasks missing on one device but
present on another, with no indication anything was wrong.

Fixes:

1. Propagate download failure: when OperationLogDownloadService
   returns success=false, throw instead of treating as "no new ops".
   Prevents lastServerSeq from advancing past failed downloads.

2. Throw on LWW conflict apply failure: autoResolveConflictsLWW
   now throws when applyOperations fails, matching the behavior of
   applyNonConflictingOps. Prevents lastServerSeq from advancing
   past failed conflict resolutions.

3. Propagate rejected ops handler errors: rethrow instead of
   swallowing in the uploadPendingOps catch block, so the
   sync-wrapper can set ERROR status.

4. Surface validation failure: validateAfterSync now checks the
   return value from validateAndRepairCurrentState and shows an
   error snackbar when validation fails.

5. Set ERROR status in sync-wrapper catch-all: the generic error
   handler now calls setSyncStatus('ERROR') so the sync icon shows
   the red error state.

Fixes #6571
2026-03-26 17:43:04 +01:00
Johannes Millan
98c41a8234 style(sidenav): improve light theme milkglass with background image
Remove saturate(180%) from light theme milkglass to prevent
over-darkening. Use solid background on mobile for readability.
2026-03-26 17:43:04 +01:00
Johannes Millan
142107b12e build: update capacitor and package-lock.json 2026-03-26 17:43:04 +01:00
Johannes Millan
a4bea36520 feat(tasks): dynamic strikethrough gesture for mobile swipe-right
Replace the accent-colored block + checkmark icon on swipe-right with
a dynamic strikethrough line that follows the touch position. The line
extends from left to right tracking the finger, transitions at the
trigger threshold, and snaps to full width on completion.

For undo (swiping on done tasks), the native text-decoration
line-through fades out via text-decoration-color animation, task
opacity increases from dimmed to full, and the checkmark unchecks.

Key implementation details:
- Strikethrough Y position adapts to task title center, with
  even-line-count offset for multi-line titles
- Undo uses text-decoration-color animation on .display-value
- showUndoneAnimation input on done-toggle removes is-done class
- Left swipe (context menu) behavior is unchanged
- Zero performance impact on desktop (IS_TOUCH_PRIMARY guard)
2026-03-26 17:43:03 +01:00
Johannes Millan
1e49f7d1ce test(e2e): add reproduction test and diagnostic logging for #6230
Add e2e test verifying the day-change trigger correctly creates new
repeat task instances when midnight passes. Uses Playwright clock
manipulation (setFixedTime) to control Date.now() while keeping real
timers running.

Document a known intra-day gap in TaskDueEffects: once addAllDueToday()
fires for today (via distinctUntilChanged on todayDateStr$), there is no
retry mechanism within the same day. Investigation verified day-change
trigger, sync buffering, and data loading guards all work correctly in
isolation — the exact real-world trigger remains unidentified.

Add diagnostic logging in addAllDueToday() to help users reproduce and
identify the failure point (repeat config count + IDs, sync window state).
2026-03-26 17:43:03 +01:00
Johannes Millan
cd12556d49 feat(color): replace native color input with swatch picker
Replace the browser's native <input type="color"> with a custom color
picker component showing a 5x4 grid of preset swatches and a custom
color button that opens the native picker.

- New standalone InputColorPickerComponent with overlay panel
- 19 preset colors in rainbow hue order + 1 custom color button
- Formly ColorInputComponent wraps the new picker
- dialog-create-tag uses the new picker directly
- Escape key and backdrop click to close overlay
- Fixed positioning to avoid dialog overflow clipping
2026-03-26 17:43:03 +01:00
Johannes Millan
061acf4124 perf(daily-summary): improve perceived performance of daily summary page
Today's tasks from the NgRx store now render immediately without waiting
for the archive IndexedDB read. Archive tasks are appended progressively
when they arrive.

Changes:
- Use combineLatest with startWith([]) on archive stream so today tasks
  emit instantly while archive loads in the background
- Add isArchiveLoaded signal with subtle opacity indicator on summary
  cards while archive data is loading
- Defer confetti animation until first non-empty task emission + 300ms
  paint buffer, instead of a fixed setTimeout
- Show spinner only when tasks are empty and archive hasn't loaded yet
2026-03-26 17:43:03 +01:00
Johannes Millan
3fe9da6021 build: update package-lock.json 2026-03-26 17:43:03 +01:00
Johannes Millan
f885336aa3 feat(plugins): enable google-calendar-provider bundled plugin 2026-03-26 17:43:03 +01:00
dependabot[bot]
c519092ab2
chore(deps): bump the npm_and_yarn group across 6 directories with 1 update (#6962)
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/ai-productivity-prompts directory: [picomatch](https://github.com/micromatch/picomatch).
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/automations directory: [picomatch](https://github.com/micromatch/picomatch).
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/boilerplate-solid-js directory: [picomatch](https://github.com/micromatch/picomatch).
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/clickup-issue-provider directory: [picomatch](https://github.com/micromatch/picomatch).
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/google-calendar-provider directory: [picomatch](https://github.com/micromatch/picomatch).
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/procrastination-buster directory: [picomatch](https://github.com/micromatch/picomatch).


Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-26 15:19:41 +01:00
dependabot[bot]
111d096496
chore(deps-dev): bump picomatch (#6961)
Bumps the npm_and_yarn group with 1 update in the /packages/plugin-dev/sync-md directory: [picomatch](https://github.com/micromatch/picomatch).


Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 23:51:38 +01:00
Johannes Millan
1a103989f4
fix(oauth): use system browser for Google OAuth on mobile (#6952)
Google blocks OAuth authorization in embedded WebViews (Error 400:
invalid_request). Use @capacitor/browser to open the system browser
on mobile instead of window.open() in the WebView.

https://claude.ai/code/session_01QWSy4NhhNQNMD2GJwqoYTc

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-24 23:50:36 +01:00
Johannes Millan
982723bc4e Merge branch 'feat/how-do-my-releases-for-parallel-code-bdf8dc'
* feat/how-do-my-releases-for-parallel-code-bdf8dc:
  ci(release): auto-generate release notes from PRs
2026-03-24 21:21:51 +01:00
Johannes Millan
76e2cdd6d8 ci(release): auto-generate release notes from PRs 2026-03-24 21:21:43 +01:00
Johannes Millan
fe0edaacd0 18.0.0-rc.0 2026-03-24 21:04:33 +01:00
Johannes Millan
96a4122dd6 style(test): fix trailing whitespace in inline-markdown spec 2026-03-24 20:42:40 +01:00
Johannes Millan
36dd00f730 style(tasks): make subtask toggle button more subtle 2026-03-24 20:41:38 +01:00
Johannes Millan
54b1095008 fix(zen): prevent selected task border from leaking into subtasks 2026-03-24 20:33:22 +01:00
Johannes Millan
2f1680a892 style(zen): make dialogs and context menus slightly lighter in dark mode 2026-03-24 20:09:02 +01:00
Johannes Millan
83432fb0f4 fix(e2e): add settle time after done-toggle to prevent sync race condition
The stale client reconnection test was flaky because syncAndWait()
was called immediately after clicking done-toggle, racing with the
200ms animation delay before isDone is dispatched to the store.
Use markTaskDone helper and wait for state to persist before syncing.
2026-03-24 20:09:02 +01:00
Johannes Millan
3d937e228d fix(context-menu): make backdrop tappable on mobile and remove task title header
Set pointer-events: none on the bounding box and overlay pane so taps
pass through to the CDK backdrop, and re-enable pointer-events on the
menu panel itself. Also remove the task title header from the top of the
context menu on touch devices.
2026-03-24 20:09:02 +01:00
Johannes Millan
5a9d501bc6 fix(theme): use dark backdrop color for light theme
--c-light-60 (white at 60% opacity) does not create a visible scrim on
a light background. Switch to --c-dark-60 (black at 60% opacity) to
match the Material Design M2 default.
2026-03-24 20:09:02 +01:00
Johannes Millan
86da1bc9d5 style(zen): use white for elevated surfaces and transparent for task-like elements
- Add task bar, dialogs, menus, and cards use #fff in light mode instead
  of off-white (#f8f8f7)
- Schedule events and repeat task cards are transparent
- Override --schedule-event-bg-in-side-panel for upcoming panel
2026-03-24 20:09:02 +01:00
Johannes Millan
ea4e4a45a7 feat(dialog): disable autofocus on touch-primary devices via global MAT_DIALOG_DEFAULT_OPTIONS
Add a global MAT_DIALOG_DEFAULT_OPTIONS provider that sets autoFocus: false
on touch-primary devices, preventing virtual keyboard popup when dialogs open.
Remove redundant per-dialog autoFocus overrides that are now handled globally.
2026-03-24 20:09:02 +01:00
Trang Le
c3f443589f
feat: Shortcut for Making Text in Task Comments Bold and Italic (#6712)
* insert ** and _  when pressing Ctrl+B and Ctrl+I respectively

* add test for shortcuts for bold and italic text

* change `fit` to `it`

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* support bold/italic shortcuts in macOS

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* change fit to it

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix unclosed curly braces

* fix redundant test

* don't set this_model directly

* place check for Ctrl+b and Ctrl+i before handleListKeydown

* add blank line between  block

* fix typos in test suite

* fix typo

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-24 19:59:11 +01:00
Johannes Millan
8b2705941d style: fix prettier multiline string formatting errors 2026-03-24 18:22:31 +01:00
Johannes Millan
c8ac3feda2 fix(lint): resolve prettier formatting and lint errors from CI run 2026-03-24 18:08:30 +01:00
Johannes Millan
3d45f26b56 - style(zen): refine schedule, header, and form field styling
- style(zen): flatten backgrounds across panels, dialogs, notes, and schedule
- style(zen): remove border from repeat config preview blocks
- style(zen): remove separator line between tasks
2026-03-24 17:52:21 +01:00
Johannes Millan
dc27787ba8 chore(deps): upgrade Angular-related dependencies to latest versions 2026-03-24 17:50:47 +01:00
Johannes Millan
857f2e3731 feat(task-repeat): improve repeat config dialog UX
- Wrap heatmap in collapsible "Activity" section, collapsed by default
- Lazy-load heatmap only when expanded to avoid loading full archive
- Disable autoFocus at all dialog call sites to prevent keyboard popup
- Icon-only action buttons on small screens with aria-labels
- Rename "Remove for" to "Skip for" with consistent confirmation dialog
- Save button raised, Remove button warn color
2026-03-24 17:26:07 +01:00
Johannes Millan
dbeca43876 test(e2e): fix done-toggle selector to use element instead of class
The done-toggle was refactored from an inline SVG with class="done-toggle"
into a standalone Angular component <done-toggle>. Update all e2e selectors
from '.done-toggle' (class) to 'done-toggle' (element) to match.
2026-03-24 16:25:42 +01:00
Johannes Millan
bbf3c741a7 feat(tasks): lock drag-and-drop Y-axis on small screens and throttle tree drag
Lock cdkDragLockAxis to Y on small screens (<600px) for task-list and
planner components, matching the breakpoint where planner switches to
single-column and bottom nav appears. Nav menu tree always locks Y.
Uses reactive LayoutService.isXs() so orientation changes work correctly.

Throttle tree-dnd onDragMoved with requestAnimationFrame to reduce
layout thrashing from getBoundingClientRect/elementFromPoint calls.
2026-03-24 16:25:42 +01:00
Johannes Millan
f20ebea583 fix(android): prevent ForegroundServiceDidNotStartInTimeException and bridge NPE
Add safeStopSelf() to TrackingForegroundService and FocusModeForegroundService
that calls startForeground() before stopSelf() in fallback branches (missing
task ID, stop when not running, null/unknown action). Android requires
startForeground() within 10s of startForegroundService().

Replace ambiguous NullPointerException in CapacitorMainActivity.onCreate with
a descriptive IllegalStateException when Capacitor bridge fails to initialize.
Add safe-call operators in onSaveInstanceState/onRestoreInstanceState.
2026-03-24 16:25:42 +01:00
Johannes Millan
d316a684bb fix(sync): improve move operation reliability during sync
- moveItemAfterAnchor: preserve current position when anchor is
  concurrently deleted instead of appending to end (which corrupted
  ordering on remote clients). For cross-list moves, append to end
  as fallback to prevent data loss.
- Prevent double-write of deferred actions: track buffered actions in
  a WeakSet and filter them in the effect so they are only written
  once by processDeferredActions().
- Propagate skipDequeue through handleQuotaExceeded retry path to
  prevent queue desync when deferred actions hit storage quota.
- Add e2e tests for concurrent delete + reorder sync scenarios.
2026-03-24 16:25:42 +01:00
Johannes Millan
0242978e49 fix(tasks): prevent focus border from leaking into subtask boxes
Angular emulated ViewEncapsulation shares the same _ngcontent attribute
across all instances of the same component type. The :host:focus
.inner-wrapper > .box selector therefore matches subtask .box elements
when the parent task is focused. Override with a more specific selector
that includes .sub-tasks to reset border-color back to defaults.
2026-03-24 16:25:42 +01:00
Johannes Millan
1e599113ac feat(tasks): allow drag-and-drop from task title on desktop
Switch task-title edit-mode trigger from mousedown to click so that
mousedown propagates freely to CDK drag. CDK's built-in 5px threshold
distinguishes drag from click naturally.
2026-03-24 16:25:42 +01:00
Johannes Millan
70ee45b16b fix(reminder): add sound to iOS local notifications
Without an explicit sound property, Capacitor's LocalNotifications plugin
sets content.sound = nil on iOS, causing silent notifications. Adding
sound: 'default' triggers the system default notification sound via iOS's
file-not-found fallback path.

Closes #6951
2026-03-24 16:25:42 +01:00
Johannes Millan
0bd214bca3 style(done-toggle): reduce circle size, per-element opacity, accent play indicator, bigger checkmark 2026-03-24 16:25:42 +01:00
Johannes Millan
5f9c9c2abd fix(planner): improve calendar handle visibility on light theme 2026-03-24 16:25:42 +01:00