Commit graph

18115 commits

Author SHA1 Message Date
Johannes Millan
fb6041c0b6 fix(focus-mode): get latest isResumingBreak value in effect (#5995)
Move selectIsResumingBreak from outer combineLatest to inner
withLatestFrom to ensure we check the current flag value at
execution time, not a stale value from the outer closure.
2026-01-20 17:07:24 +01:00
Johannes Millan
b7139036f7 fix(focus-mode): prevent break skip when resuming from pause (#5995)
Replace time-based flag with store-based _isResumingBreak flag to
reliably distinguish break resume from manual tracking start.
This eliminates race conditions that caused breaks to be skipped.
2026-01-20 17:07:24 +01:00
Johannes Millan
2b5bf17027 fix(data-repair): preserve archiveOld separately during repair
The dataRepair function was merging archiveOld into archiveYoung,
contradicting the dual-archive architecture where both archives
should remain separate for proper age-based archiving.

Changes:
- Removed archive merging logic from dataRepair (lines 80-97)
- Updated 11 repair functions to handle both archiveYoung and archiveOld:
  * _fixEntityStates
  * _removeNonExistentTagsFromTasks
  * _removeNonExistentProjectIdsFromTasks
  * _addInboxProjectIdIfNecessary
  * _removeDuplicatesFromArchive
  * _removeMissingTasksFromListsOrRestoreFromArchive
  * _moveArchivedSubTasksToUnarchivedParents
  * _moveUnArchivedSubTasksToArchivedParents
  * _removeNonExistentRepeatCfgIdsFromTasks
  * _cleanupOrphanedSubTasks
  * _setTaskProjectIdAccordingToParent
- Added debug logging to BackupService for validation failures

Tests:
- All 40 data-repair unit tests pass
- All 189 archive-related unit/integration tests pass
- All 6 archive import/export E2E tests pass

Fixes E2E test: "should persist both archive types after import"
2026-01-20 17:07:24 +01:00
Johannes Millan
be4b8ba241 fix(migrations): ensure unique IDs and prevent data loss in split operations
When splitting one operation into misc and tasks operations:
- Both operations now get unique ID suffixes (_misc and _tasks)
- Skip logic verifies both conditions before skipping:
  1. tasks config has migrated field (isConfirmBeforeDelete)
  2. misc config has NO migrated fields remaining

This prevents:
- Potential operation ID conflicts in the sync log
- Data loss in partial migration scenarios

Adds test cases for partial migration and correct skip scenarios.
2026-01-20 17:07:23 +01:00
Johannes Millan
c42d5ace43 chore(focus-mode): remove debug console logs for bug #5995
Removes temporary debug logging added during bug #5995 investigation:
- Remove console.warn from syncSessionPauseToTracking$ effect
- Remove console.warn from _handlePlayPauseToggle method
- Remove console.warn from pauseBreak() in focus-mode-break component
- Remove console.log from resumeBreak()

No functional changes.
2026-01-20 17:07:23 +01:00
Johannes Millan
0c853549cf fix(focus-mode): align manual break cycle calculation with auto-start behavior
Fixes inconsistency introduced in bug #6044 fix where auto-start breaks use
cycle directly but manual-start breaks still used cycle-1 adjustment.

After session 4, both auto and manual breaks now correctly trigger long break.

- Remove obsolete cycle-1 adjustment from _handleStartAfterSessionComplete
- Update test to expect cycle=4 instead of cycle=5 for long break
- Update comment to reference bug #6044 fix
- Fix TypeScript type errors in test file (as any assertions)
2026-01-20 17:07:23 +01:00
Johannes Millan
9ebf98ff3c fix(metric): add validation for logFocusSession operation payload
Adds explicit validation for the {day, duration} payload structure used by
logFocusSession action. This prevents the false positive warning about
"unusual structure" while maintaining correct validation for all other
METRIC operations. The specialized payload format is intentional for
append-only focus session logging.
2026-01-20 17:07:23 +01:00
Johannes Millan
c4a9a05055 fix(tags): respect menu tree order in tag selection menu
Tags in the selection menu (shown when adding/editing tasks) now
respect the custom order defined in the left panel navigation instead
of being sorted alphabetically.

The component now uses MenuTreeService.buildTagViewTree() to maintain
user-defined ordering, including tags within folders. This provides
consistent UX between the navigation panel and tag selection dialogs.

Fixes #6046
2026-01-20 17:07:23 +01:00
Johannes Millan
96576a7ff1 test(focus-mode): add E2E tests for Pomodoro break timing
Relates to #6044

Added comprehensive E2E tests to verify the correct Pomodoro break pattern:
- Sessions 1-3 should trigger short breaks
- Session 4 should trigger a LONG break (critical test for bug #6044)
- Session 5 should trigger a short break (not long)
- Session 8 should trigger a LONG break (second cycle)

**Test Coverage:**
- Individual test for long break after 4th session
- Individual test for short break after 5th session
- Individual test for long break after 8th session
- Full pattern verification: S S S L S S S L

**Test Structure:**
The tests follow the existing E2E test patterns and include:
- Helper functions for common operations (openFocusModeWithTask, startFocusSession, etc.)
- Break type detection to verify short vs long breaks
- Screenshot capture for visual verification
- Console logging for debugging and verification

**Additional Changes:**
- Added screenshots/ directory for test artifacts
- Updated e2e/.gitignore to exclude generated screenshots

These E2E tests complement the 131 passing unit tests to ensure the bug fix works correctly in the actual application.
2026-01-20 17:07:23 +01:00
Johannes Millan
cfc3437fd0 fix(focus-mode): long break now occurs after 4th session, not 5th
Fixes #6044

**Root Cause:**
Race condition in NgRx effects. When completeFocusSession was dispatched:
1. incrementCycleOnSessionComplete$ dispatched incrementCycle action
2. autoStartBreakOnSessionComplete$ ran simultaneously and read OLD cycle value
3. The "-1 adjustment" tried to compensate but couldn't fix the race condition

Session 4 completed → cycle became 5, but effect read 4 → (4-1)=3 → 3%4≠0 → short break 
Session 5 completed → cycle became 6, but effect read 5 → (5-1)=4 → 4%4=0 → LONG break 

**Fix:**
Changed autoStartBreakOnSessionComplete$ to listen to incrementCycle instead of
completeFocusSession. This ensures:
1. Cycle is incremented FIRST (reducer runs)
2. THEN break calculation reads the UPDATED cycle value
3. No adjustment needed - cycle value is already correct

Session 4 completes → cycle=4 → incrementCycle → effect fires → 4%4=0 → LONG break ✓
Session 5 completes → cycle=5 → incrementCycle → effect fires → 5%4≠0 → short break ✓

**Changes:**
- Changed effect trigger from completeFocusSession to incrementCycle
- Removed incorrect "cycle - 1" adjustment
- Added explicit Pomodoro mode filter to effect
- Updated all related tests to dispatch incrementCycle
- Added specific tests for 4th (long break) and 5th (short break) sessions

**Test Coverage:**
- All 131 focus-mode.effects tests pass
- All 458 focus-mode feature tests pass
- PomodoroStrategy tests confirm correct break duration logic
2026-01-20 17:07:23 +01:00
Johannes Millan
9f2d2b9a6e fix(focus-mode): prevent tray indicator jumping during focus sessions
The tray icon was jumping between showing task time and focus session time
when focus mode was active with a task being tracked. This occurred because
the tray display logic didn't know which focus mode was active.

Changes:
- Send focus mode type (Countdown/Pomodoro/Flowtime) from frontend to Electron
- Update IPC handler to receive and pass focus mode type to tray message creation
- Implement three-mode priority logic in createIndicatorMessage():
  1. Countdown/Pomodoro modes: Show focus session countdown timer
  2. Flowtime mode: Show task estimate or title (no timer)
  3. No focus mode: Show normal task time (existing behavior)
- Update TypeScript type definitions for updateCurrentTask()
- Update unit tests to mock the new mode() signal

This ensures the tray displays the correct timer without jumping based on
the active focus mode, matching the behavior of the overlay indicator.

Fixes jumping tray indicator during focus mode + tracking
2026-01-20 17:07:23 +01:00
Johannes Millan
b77f18f681 fix(focus-mode): prevent taskbar progress bar filling every second
Converts setTaskBarProgress$ effect from selector-based to action-based
with 500ms throttling to prevent excessive IPC calls. The selector-based
effect was firing on every timer tick (1s), causing the Windows taskbar
progress bar to fill completely every second instead of gradually over
the session duration.

Fixes #6061
2026-01-20 17:07:23 +01:00
Johannes Millan
955a3e13c5 docs: add plan 2026-01-20 17:07:23 +01:00
Johannes Millan
fa8bad6292 fix(electron): restore hidden window on taskbar click
Fixes #6042 where app wouldn't launch from taskbar when minimize to tray
was enabled. The second-instance handler now uses showOrFocus() which
properly handles both hidden and minimized windows, matching the behavior
of the tray icon click handler.
2026-01-20 17:07:23 +01:00
Johannes Millan
e3b78c9c0c
Merge pull request #5990 from steindvart/domina-mode-rename-#5989
Rename "Domina mode" to a "Voice Reminder"
2026-01-20 13:26:09 +01:00
Johannes Millan
68a28fae0a
Merge pull request #6069 from steindvart/scheduling-modal-buttons-redesing
Improve design of action buttons in the scheduling task modal
2026-01-20 11:42:38 +01:00
Ivan Kalashnikov
d0572ac14c fix: increase minimum height of dialog content to improve layout 2026-01-20 14:03:04 +07:00
Ivan Kalashnikov
45ec227da7 refactor: adjust alignment and styling of schedule actions buttons in dialog 2026-01-20 13:50:47 +07:00
Ivan Kalashnikov
25c0c2764a refactor: update dialog actions layout and styling in schedule task dialog 2026-01-20 13:40:17 +07:00
Ivan Kalashnikov
376675d209 feat: add cancel button to schedule task dialog actions 2026-01-20 13:17:14 +07:00
Ivan Kalashnikov
6ba28a5a33 refactor: enhance dialog actions layout and styling in schedule task dialog 2026-01-20 13:12:04 +07:00
Ivan Kalashnikov
e6dada42e9 refactor: align dialog actions to the start in schedule task dialog 2026-01-20 12:49:57 +07:00
Ivan Kalashnikov
9b3b65183d refactor: remove cancel button from schedule task dialog actions 2026-01-20 12:47:32 +07:00
Johannes Millan
c29a05fa1c
Modify humanitarian aid link and support text
Updated link and description for humanitarian aid.
2026-01-19 20:07:13 +01:00
Johannes Millan
12d7cb80c4
update readme 2026-01-19 19:58:18 +01:00
Johannes Millan
8ba130ad58
Merge pull request #6063 from steindvart/tasks-settings-inline-label
Tasks tab - provide changes from #6058
2026-01-19 19:23:55 +01:00
Ivan Kalashnikov
7f61c638c3 fix: enhance Tasks tab with tooltip and section title 2026-01-20 00:47:55 +07:00
Johannes Millan
8734b7ef4c
Merge pull request #6053 from steindvart/task-settings
Move task-related settings to a dedicated Tasks Settings tab and fix technical issues
2026-01-19 16:46:44 +01:00
Johannes Millan
83bc88d686
Merge pull request #6062 from steindvart/restore-issue-templates
Hotfix: remove conditionals from bug and feature issue templates
2026-01-19 16:44:04 +01:00
Johannes Millan
98e94b5663
Merge pull request #6049 from Kuntal6002/fix/manual-break-overtime
Fix/manual break overtime
2026-01-19 16:43:33 +01:00
Johannes Millan
7ba9ca015b
Merge pull request #6043 from Nejvis/patch-1
Update pl.json
2026-01-19 16:20:59 +01:00
Johannes Millan
27f07e418a
Merge pull request #6058 from steindvart/tabs-style-small-devices
Improve settings tabs navigation on small screens
2026-01-19 16:20:25 +01:00
Johannes Millan
6426f59804
Merge pull request #6060 from mycochang/fix/restore-force-upload-ui
Fix/restore force upload UI
2026-01-19 16:19:40 +01:00
Ivan Kalashnikov
21579be27d fix(issue-templates): remove conditional from bug report and feature request templates 2026-01-19 22:17:12 +07:00
Johannes Millan
1a455e294d
Merge pull request #6048 from steindvart/update-bug-issue-template
Improve issue templates
2026-01-19 16:08:54 +01:00
Michael Chang
a54e5f7fe8 style(sync): use proper button label for force upload 2026-01-19 14:56:05 +01:00
Johannes Millan
f8a9347681 feat(focus-mode): add end focus session button to completion banner
Adds a secondary "End Focus Session" button to the focus banner when a session completes, allowing users to completely exit focus mode and dismiss the banner instead of only being able to start a break or next session.
2026-01-19 14:48:56 +01:00
Johannes Millan
9e7a9ccdc9 fix(ci): grant write permissions for fork PRs in Claude Code review
Change trigger from pull_request to pull_request_target to allow the
workflow to run with write permissions even for external contributors.
This fixes the "Actor has insufficient permissions" error.

Also add condition to skip draft PRs to reduce API usage.
2026-01-19 14:43:26 +01:00
Ivan Kalashnikov
86be6872bf feat(config-page): add section titles to each tab in settings 2026-01-19 20:24:48 +07:00
Ivan Kalashnikov
d1f5045646 feat(config-page): hide tabs labes in 'md' size screens 2026-01-19 20:21:05 +07:00
Michael Chang
c1f5a1ab15 chore: remove accidental directory 2026-01-19 14:11:11 +01:00
Michael Chang
222b3474b8 fix(sync): restore missing force upload button in new config UI 2026-01-19 13:58:23 +01:00
Ivan Kalashnikov
5ceb5fdb03 fix: ensure default tasks configuration is used when tasks are undefined 2026-01-19 19:35:18 +07:00
Johannes Millan
cf317036de fix(e2e): wait for dialog close animation in deleteTask helper
The deleteTask() helper was clicking the confirmation dialog Delete
button but not waiting for the dialog to actually close. This caused
a race condition where tests would immediately check for the undo
snackbar before it could appear, leading to timeouts.

The fix adds a proper wait for the dialog container to be hidden
after clicking Delete, ensuring the close animation completes and
NgRx effects have time to dispatch the snackbar action.

Fixes CI E2E workflow failure in "Undo task delete syncs restored
task to other client" test.
2026-01-19 12:09:50 +01:00
Johannes Millan
7dcf0b77df fix(config): handle undefined state in config selectors
Fixes #6052

Add null-safety checks to all 15 config selectors to handle
undefined state during app initialization. Prevents crash when
selector-based effects fire before loadAllData completes.

Changes:
- Add nullish coalescing operator to all selectors
- Return DEFAULT_GLOBAL_CONFIG values when state is undefined
- Add 26 unit tests for undefined state handling

All tests pass (41/41). No breaking changes to API or behavior.
2026-01-19 11:44:56 +01:00
Ivan Kalashnikov
b602993864 fix: update incompatible version logic to use CURRENT_SCHEMA_VERSION 2026-01-19 14:56:37 +07:00
Ivan Kalashnikov
1987292433 refactor: streamline migration logic and enhance field mapping for settings 2026-01-19 14:38:42 +07:00
Ivan Kalashnikov
800ba30f4f refactor: rename misc to tasks settings migration file and object. 2026-01-19 14:30:42 +07:00
Ivan Kalashnikov
356278fc87 feat: enhance migration tests for settings and operations handling 2026-01-19 14:21:09 +07:00
Ivan Kalashnikov
218e74f882 feat: implement migration of settings from misc to tasks with operation handling 2026-01-19 14:19:31 +07:00