Commit graph

17829 commits

Author SHA1 Message Date
Johannes Millan
05da537e45 fix(docs): correct malformed markdown in extract-translations command
Fix broken markdown formatting where multiple sections were collapsed
into a single malformed block. Properly structure HTML/TypeScript code
examples, key naming conventions, usage examples, and edge cases. #6004
2026-01-15 13:21:58 +01:00
Johannes Millan
9a1e0a2dd8 fix(icon-input): show initial icons on focus for better discoverability #5997
When users click on the icon input field, 50 icons now appear immediately
instead of requiring the user to type first. This makes the icon selection
more intuitive and discoverable.
2026-01-15 13:21:23 +01:00
Johannes Millan
929c474555 fix(simple-counter): add scrolling support for mobile dropdown #5999
Enable vertical scrolling when many counters overflow the viewport on mobile devices.
2026-01-15 13:03:56 +01:00
Johannes Millan
4f2e4b41ce fix(focus-mode): show overlay when no valid task exists for sync #5954
When starting a focus session with "Sync focus sessions with time tracking"
enabled, if no valid (undone) task exists, dispatch showFocusOverlay so the
user can select or create a task instead of running the timer untracked.
2026-01-15 12:59:50 +01:00
Johannes Millan
2f7a00371a fix(supersync): improve GDPR compliance in legal documents
- Remove placeholder address text from privacy policies (DE/EN)
- Expand HTML privacy policy with full GDPR disclosures:
  - Legal bases (Art. 6), data subject rights (Art. 15-22)
  - Supervisory authority, retention periods, DPA info
  - Cookies/tracking and automated decision-making sections
- Align HTML terms with German ToS:
  - Add proper termination notice periods (2 weeks/good cause)
  - Add 6-week notice for ToS amendments
  - Add consumer withdrawal rights (14 days)
  - Add ODR platform link and jurisdiction info
2026-01-15 12:48:18 +01:00
Johannes Millan
00d5dbcdff fix(ui): correct viewChild syntax for visibility menu trigger
The generic type parameter on viewChild() conflicts with the read option.
Remove it to match the pattern used elsewhere in the codebase.

Fixes compilation error introduced in 1bb61fdd4.
2026-01-15 12:42:44 +01:00
Johannes Millan
1bb61fdd4b fix(ui): visibility menu positioning after toggling Inbox #5955
Use visibility:hidden instead of display:none for additional buttons
to keep elements in layout flow. This ensures getBoundingClientRect()
returns correct values for mat-menu positioning.

Also use overflow:clip instead of overflow:hidden to prevent CDK
overlay positioning issues.
2026-01-15 12:37:21 +01:00
Johannes Millan
14e91cc811 fix(focus-mode): require task selection before starting when sync enabled #6009
When "Sync focus sessions with time tracking" is enabled:
- Play button is disabled when no task is selected
- Tooltip shows "Select a task first to start tracking"
- Clicking the button opens the task selector instead of starting

Includes comprehensive unit tests for the new behavior.
2026-01-15 12:33:35 +01:00
Johannes Millan
be0f5f9c7e fix(focus-mode): store pausedTaskId for manual break start regardless of pause setting
Bug #5974: When using Pomodoro with isPauseTrackingDuringBreak=false and
isManualBreakStart=true, pressing the time tracking button to stop tracking
after session ends, then pressing "Start" to begin break, would not resume
tracking.

Root cause: storePausedTaskOnManualBreakSession$ only stored pausedTaskId when
isPauseTrackingDuringBreak=true. Without the stored task ID, the banner button
couldn't resume tracking.

Fix: Store pausedTaskId whenever manual break is enabled, regardless of the
isPauseTrackingDuringBreak setting. This ensures the task ID is available to
resume tracking when the break starts (if user manually stopped tracking).
2026-01-15 12:29:44 +01:00
Johannes Millan
04b5b959a4 fix(icon-input): prevent emoji double-insert on Windows #5929
Add deduplication guard to prevent Windows emoji picker from inserting
emojis twice. The issue occurs due to feedback loop in ngModel/formControl
binding when the picker triggers multiple events.
2026-01-15 12:17:58 +01:00
Johannes Millan
f67bd288bf fix(e2e): configure downloads path to prevent leaking to ~/Downloads
Adds explicit downloadsPath to Playwright config so test downloads
go to .tmp/e2e-test-results/downloads/ instead of the system Downloads
folder.
2026-01-15 12:02:22 +01:00
Johannes Millan
87bd32d22d fix(plugins): provide both 'plugin' and 'PluginAPI' variables for backward compatibility
The automations plugin uses `declare const plugin: PluginAPI` while existing
bundled plugins use `PluginAPI` directly. This fix provides both variable names
pointing to the same API object, ensuring all plugins work correctly.
2026-01-15 11:11:52 +01:00
Johannes Millan
a1d736010c fix(plugins): fix empty side panel for AI Productivity Prompts plugin
The plugin was using a custom vite.config.ts that generated separate
JS/CSS files with broken relative paths. When loaded in a blob URL
iframe, these paths couldn't resolve.

- Switch to @super-productivity/vite-plugin which inlines assets
- Fix title from "Procrastination Buster" to "AI Productivity Prompts"
2026-01-15 11:04:12 +01:00
Johannes Millan
9bfbc06b18 chore: address code review feedback
- Fix misleading comment in sync-wrapper.service.ts safeguard
- Add missing SCSS for pause-resume button in focus mode break
- Remove commented archive store code from feature-stores.module.ts
- Increase touch submenu test buffer from 350ms to 450ms for CI stability
- Remove redundant isEmojiIcon method in tag-toggle-menu-list component
2026-01-15 10:57:43 +01:00
Johannes Millan
305372eb23 fix(e2e): stabilize flaky LWW delete vs update race test
Replace racy :focus selector with explicit visibility wait and focus()
call. The original selector failed intermittently because Angular sets
focus asynchronously via change detection.
2026-01-15 10:54:21 +01:00
Johannes Millan
446a051169 fix(sync): throw error on empty archive overwrite with opType-aware handling
- SYNC_IMPORT: Throws error when empty archive would overwrite non-empty
  (this is always a bug - sync should use getStateSnapshotAsync)
- BACKUP_IMPORT: Shows window.confirm dialog allowing user to choose
  whether to proceed with restoring backup that has empty archives

This prevents silent data loss and state divergence between clients.
2026-01-15 10:53:41 +01:00
Johannes Millan
9809440293 refactor(sync): make opId required in uploadSnapshot
Follow-up to the ID mismatch fix. If the server MUST use the client's
opId (to prevent ID mismatch bugs), then it should be required, not
optional. This makes the type signature match the comment.

- Changed `opId?: string` to `opId: string` in provider.interface.ts
- Updated all callers (SuperSync, FileBasedSyncAdapter, tests)
- Added uuidv7 import to encryption-password-change.service.ts
2026-01-14 22:08:33 +01:00
Johannes Millan
cee12a444a fix(sync): pass op.id to uploadSnapshot to prevent ID mismatch
When uploading BACKUP_IMPORT via uploadSnapshot(), the client's op.id
was not sent to the server. The server would generate its own ID,
causing the client to not recognize the operation when downloaded later.
This led to data loss as the old backup state would be re-applied.

Changes:
- Add opId parameter to uploadSnapshot() interface
- Pass op.id from operation-log-upload.service.ts
- Send opId in SuperSync API request payload
- Server uses client's opId instead of generating new one
- Add E2E test to verify ID matching

The fix is backwards compatible - legacy clients without opId still work
as the server falls back to uuidv7() when opId is not provided.
2026-01-14 21:57:08 +01:00
Johannes Millan
3ef232b785 fix(sync): set SYNCING status to prevent ImmediateUploadService interference
ImmediateUploadService checks isSyncInProgress before uploading, but
SYNCING status was never being set, so uploads could occur during sync
dialog interactions. This caused the CANCEL button on import conflict
dialogs to fail - uploads triggered conflict resolution downloads that
applied remote data before the user could cancel.

Also improved E2E test reliability by verifying dropdown selection was
actually applied before proceeding.
2026-01-14 21:19:00 +01:00
Johannes Millan
07455bd526 feat: adjust styling for schedule dialog to make space for unschedule button 2026-01-14 21:05:32 +01:00
Johannes Millan
23c6691daa 17.0.0-RC.3 2026-01-14 16:26:13 +01:00
Johannes Millan
f31aa0f4a4 fix(test): improve e2e sync test stability
- Add settle delays after bulk task creation for UI/NgRx processing
- Wait for done button visibility before clicking
- Use toPass() retry pattern for CSS class assertions
- Add explicit triggerSync() before expecting conflict dialog
2026-01-14 16:16:08 +01:00
Johannes Millan
ec32146ac0 fix(test): use overrideSelector in taskRepeatCfgs$ test
MockStore setState doesn't work reliably with feature selectors.
Use overrideSelector to match the pattern of other tests in the file.
2026-01-14 16:13:06 +01:00
Johannes Millan
3d7eab0365 fix(focus-mode): add pause/resume and Back to Planning buttons to break screen (#5995)
- Add pause/resume button to break screen for fullscreen break control
- Add "Back to Planning" button to exit break without auto-starting next session
- Add exitBreakToPlanning action to allow returning to preparation state
- Add translation keys for PAUSE_BREAK and RESUME_BREAK

This addresses the two issues reported:
1. Users can now pause breaks from the fullscreen break view
2. Users can click "Back to Planning" to change timer modes during break

Test coverage:
- 48 reducer unit tests (including 4 new for exitBreakToPlanning)
- 14 component unit tests (including pause/resume/exit methods)
- 4 E2E tests for break flow (1 skipped due to NgRx/zone.js E2E limitation)
2026-01-14 16:05:31 +01:00
Johannes Millan
07a5bc7375 fix(focus-mode): stop time tracking when countdown timer ends naturally
When using Countdown timer mode with "Sync focus sessions with time tracking"
and "Pause task tracking breaks" enabled, time tracking now correctly stops
when the timer ends naturally (not just when manually ended).

The issue was that Countdown mode has shouldStartBreakAfterSession=false,
so autoStartBreakOnSessionComplete$ never fired, and stopTrackingOnManualEnd$
only fired for manual completions (isManual=true).

The fix renames stopTrackingOnManualEnd$ to stopTrackingOnSessionEnd$ and
extends the filter to also fire on automatic completions when no break will
auto-start (for Countdown/Flowtime modes or when isManualBreakStart is enabled).

Fixes #5996
2026-01-14 15:31:09 +01:00
Johannes Millan
84e12d25ae fix(planner): fix tomorrow$ timezone bug in daily summary Plan tab
The Plan tab in Daily Summary was showing empty because tomorrow$
returned null due to timezone-related date calculation. The bug was
caused by parsing a date string ("YYYY-MM-DD") as UTC midnight, then
using local timezone operations to add one day.

Fixed by using millisecond arithmetic (same pattern as daysToShow$)
and changed from hardcoded days[1] to days.find() for robustness.

Added 14 comprehensive unit tests covering:
- Basic functionality
- Timezone handling near midnight
- startOfNextDayDiff configuration
- Edge cases: month/year boundaries, leap years
2026-01-14 15:05:57 +01:00
Johannes Millan
e93e0abc89 fix(test): use per-test timeout for large batch sync tests
jasmine.DEFAULT_TIMEOUT_INTERVAL at module level wasn't being applied,
causing 2000ms timeout failures. Pass timeout as third argument to it().
2026-01-14 14:39:48 +01:00
Johannes Millan
aee3b656df 17.0.0-RC.2 2026-01-14 14:26:09 +01:00
Johannes Millan
eedefba254 refactor: update unschedule label and remove unused archive stores to reduce memory bloat 2026-01-14 14:24:39 +01:00
Johannes Millan
df4aa2b56d fix(e2e): reduce task count in tag deletion test to prevent timeout
Reduce tasks from 10 to 5 in the bulk tag deletion sync test.
Creating and syncing 10 tasks was exceeding the 180s test timeout.
5 tasks still validates atomic tag deletion behavior.
2026-01-14 14:22:15 +01:00
Johannes Millan
9d21fa1b6e fix(e2e): stabilize flaky tests with improved waiting strategies
- Increase task creation timeout from 10s to 15s for slow renders
- Use force:true on backdrop click to bypass overlay coverage
- Replace page.evaluate() with Playwright locators in expandSection()
- Add proper condition-based waiting for collapsible panel visibility
2026-01-14 13:45:27 +01:00
Johannes Millan
c6028b980d fix(e2e): stabilize flaky menu-touch-submenu test
Replace arbitrary waitForTimeout calls with condition-based waiting:
- Use specific selector scoped to .mat-mdc-menu-content for tag button
- Wait for tag to appear on task instead of waiting for menu to close
- Keep only the justified 350ms wait for touch protection delay testing
2026-01-14 13:45:27 +01:00
Johannes Millan
78283e7423 test(selectors): add comprehensive tests for optimized selectors
Add unit tests for selectAllTasksWithDueDay and selectAllTasksDueToday
selectors to ensure the performance optimizations work correctly.

Tests cover:
- Filtering tasks by dueDay and dueWithTime
- Sorting by dueDay chronologically
- Handling empty state and missing entities
- Deduplication of tasks from multiple sources
- Edge cases like subtasks with dueDay
2026-01-14 13:45:27 +01:00
Johannes Millan
5cb8720058 perf(planner): optimize selectAllTasksDueToday selector
Consolidate two Object.values() calls into a single iteration over
taskState.ids. This avoids creating two intermediate arrays and
reduces the number of passes over all tasks from 2 to 1.
2026-01-14 13:45:27 +01:00
Johannes Millan
d345bc33ea perf(tasks): optimize selectAllTasksWithDueDay selector
Iterate taskState.ids instead of using Object.values() to avoid
creating an intermediate array. Also simplified the sort comparator
using localeCompare since dueDay is in YYYY-MM-DD format which is
lexicographically sortable.
2026-01-14 13:45:27 +01:00
Johannes Millan
f4b0391209 feat(metric): remove loading placeholder for activity heatmap 2026-01-14 13:45:27 +01:00
Johannes Millan
28bba15e05 fix(tag): correct emoji spacing in tag toggle menu dropdown
Emojis in tag icons were rendered inside <mat-icon> elements, causing
excessive whitespace. Now emojis are detected via isSingleEmoji() and
rendered in a <span> with proper emoji styling.

Fixes #5977
2026-01-14 13:45:27 +01:00
Johannes Millan
b2a807f7db perf(archive): remove unused NgRx archive stores to reduce memory usage
Archives (archiveYoung, archiveOld) were being loaded into NgRx state
at startup but their selectors were never read anywhere in the codebase.
All code that needs archives loads them directly from IndexedDB via
ArchiveDbAdapter (StateSnapshotService, TaskArchiveService, etc).

This change removes the archive store registrations from NgRx, which:
- Reduces memory usage for users with large archives
- Improves startup time (no longer dispatching large archive data to NgRx)
- Reduces GC pressure (fewer large objects in memory)

Archive functionality is unaffected - archives are still stored in
IndexedDB and loaded on-demand when needed for worklog, sync, etc.
2026-01-14 13:45:27 +01:00
Johannes Millan
c5625317bf fix: prevent memory leaks from unmanaged subscriptions and event listeners
- LocalBackupService: add takeUntilDestroyed to backup interval subscription
- GlobalProgressBarService: add takeUntilDestroyed to dirty countdown subscription
- PluginBridgeService: extract window/document listeners to named methods with cleanup
- shepherd-helper: add take(1) to waitForElObs$, add 10s timeout to waitForEl
- plugin.service: add max attempts (100) to plugin loading poll interval
2026-01-14 13:45:27 +01:00
Johannes Millan
a93f6a7ba2 fix(sync): use BackupImport OpType for backup imports to bypass 409
When importing a backup while connected to SuperSync, the server was
rejecting the operation with 409 SYNC_IMPORT_EXISTS error. This happened
because backup imports were using OpType.SyncImport which maps to
reason='initial' on the server.

Fix:
- Change OpType.SyncImport → OpType.BackupImport in backup.service.ts
- OpType.BackupImport maps to reason='recovery' on the server
- Server allows reason='recovery' even when SYNC_IMPORT exists

This enables users to recover data by importing backups when connected
to SuperSync, which is essential for disaster recovery scenarios.

Add unit test verifying OpType.BackupImport is used and E2E test that
validates the full backup recovery flow works when SYNC_IMPORT exists.
2026-01-14 13:45:27 +01:00
Johannes Millan
0fd2618dab fix(sync): preserve archived tasks during server migration and backup
SYNC_IMPORT operations and local backups were losing archived tasks because
they used sync snapshot methods that return empty DEFAULT_ARCHIVE instead of
loading real archive data from IndexedDB.

Changes:
- ServerMigrationService: use getStateSnapshotAsync() to include archives
- LocalBackupService: use getAllSyncModelDataFromStoreAsync() for backups
- ArchiveOperationHandler: add safety guard to prevent overwriting non-empty
  archives with empty ones

Add unit tests for archive preservation and E2E test that triggers actual
server migration by switching sync providers.
2026-01-14 13:45:27 +01:00
Johannes Millan
64ccc99ddb
Merge pull request #5986 from steindvart/time-tracer-position
Made tracking time panel position left of the other elements and remove hiding
2026-01-14 12:51:25 +01:00
Johannes Millan
81ab8d52d0
Merge pull request #5980 from steindvart/fix-readme-links
Fix: links and remove extra symbols in main README
2026-01-14 12:19:33 +01:00
Johannes Millan
b477b0b1fc
Merge pull request #5982 from super-productivity/dependabot/npm_and_yarn/npm_and_yarn-f02db13dca
build(deps): bump the npm_and_yarn group across 1 directory with 2 updates
2026-01-14 12:10:56 +01:00
Ivan Kalashnikov
1fa27662ad Merge remote-tracking branch 'origin/master' into time-tracer-position 2026-01-14 17:40:33 +07:00
Johannes Millan
5a4290eccf
Merge pull request #5988 from steindvart/fix-small-letters
Fix small letters
2026-01-14 11:15:30 +01:00
Ivan Kalashnikov
05c53741af fix: improve capitalization and punctuation in various strings in ru.json 2026-01-14 14:55:24 +07:00
Ivan Kalashnikov
ffceed18b5 fix: update TIME_LOCALE_DESCRIPTION in ru.json for to match the current information in en.json. 2026-01-14 14:51:36 +07:00
Ivan Kalashnikov
0f7000a3ef fix: capitalization and punctuation in START_OF_NEXT_DAY_HINT string. 2026-01-14 14:48:30 +07:00
Ivan Kalashnikov
a9c0b4a590 fix: remove hover effects for current task title and action navigation 2026-01-14 14:17:39 +07:00