Commit graph

12717 commits

Author SHA1 Message Date
novikov1337danil
b350141c5d
fix(schedule-week): adjust sizes (#6350) 2026-02-04 12:44:51 +01:00
Johannes Millan
80007dbc19 fix(tasks): clear remindAt when rescheduling task via planner (#6342)
planTaskForDay set dueDay and cleared dueWithTime but left remindAt
untouched. The reminder worker kept firing for the past remindAt value,
causing the reminder popup to reopen in a loop after "Reschedule for
tomorrow".
2026-02-03 16:55:25 +01:00
Johannes Millan
0df56878e1 fix(tasks): reset devError state in orphan ID detection test
The devError module has shared mutable state (isShowAlert flag) that
caused flaky test failures in America/Los_Angeles timezone. Add a
test-only reset function and call it before the affected test.
2026-02-03 15:54:52 +01:00
Johannes Millan
47cc5d1514 refactor(sync): extract shared native HTTP retry utility with locale-proof error detection
- Extract executeNativeRequestWithRetry and isTransientNetworkError into
  shared native-http-retry.ts for reuse by Dropbox and SuperSync
- Add locale-proof error.code checks: iOS NSURLErrorDomain, Android
  SocketTimeoutException/UnknownHostException/ConnectException
- Keep English string matching as fallback for web/Electron
- Wrap Dropbox token refresh in retry logic
- Split timeouts: 30s for auth endpoints, 120s for data transfer
- Apply retry wrapper to SuperSync _fetchApiNative and _fetchApiCompressedNative
2026-02-03 15:45:27 +01:00
Johannes Millan
e69108b14e fix(tasks): filter orphan IDs in removeTasksFromTodayTag reducer (#6327)
The reducer unconditionally prepended payload taskIds into state.ids
without checking entity existence. During op-log replay or concurrent
effects, deleted task IDs could be re-injected as orphans, causing
TypeErrors on properties like dueWithTime and dueDay.
2026-02-03 15:33:28 +01:00
Johannes Millan
39eaef79dd fix(sync): add retry logic for transient iOS network errors in Dropbox sync
iOS CapacitorHttp uses URLSession.dataTask which does not auto-retry POST
requests. Large sync payloads crossing the WKWebView bridge are vulnerable
to TCP connection drops (NSURLErrorNetworkConnectionLost / -1005).

- Add _executeNativeRequestWithRetry() with max 2 retries and linear backoff
- Add _isTransientNetworkError() classifier for iOS NSError descriptions
- Increase readTimeout from 60s to 120s for all native CapacitorHttp calls
- Add comprehensive unit tests for error classification and edge cases

Closes #6333
2026-02-03 14:38:05 +01:00
Johannes Millan
f78f6f4e39 refactor: replace PFLog with SyncLog/OpLog and remove obsolete migration scripts
PFLog was named after "Pfapi" which is no longer used. Replace with
SyncLog in sync provider files and OpLog in op-log infrastructure files.
Delete unused migration scripts.
2026-02-03 14:38:05 +01:00
Johannes Millan
f6c9714433 fix(sync): prevent task duplication during file-based sync snapshot hydration
When a fresh client first syncs with a file-based provider (WebDAV,
Dropbox, LocalFile), it receives both a snapshotState and recentOps.
The snapshot was hydrated correctly, but recentOps were not recorded,
causing duplication through two paths:

1. Download path: On the next sync cycle, recentOps bypassed the
   appliedOpIds filter (not in IndexedDB) and were re-applied.
2. Piggyback path: The adapter's isForceFromZero guard skipped marking
   ops as processed, so they were returned as piggybacked during upload.

Fix by writing recentOps to IndexedDB after snapshot hydration and
always marking downloaded ops as processed for piggyback tracking.
2026-02-03 14:38:05 +01:00
Johannes Millan
a5c6337ff5 fix(main-header): remove unnecessary right padding on macOS Electron
The WCO padding-right rule matched on macOS where window controls are
on the left side, causing header icons to be pushed ~140px inward.
Restrict the rule to non-Mac Electron using the isNoMac body class.

Closes #6337
2026-02-03 14:38:05 +01:00
Johannes Millan
2a491010af fix(main-header): restore inline simple counter buttons on desktop
Counter buttons were always behind a dropdown toggle after the habits
management page change. Restore inline rendering on desktop and restrict
the timer-icon dropdown to mobile viewports only.
2026-02-03 14:38:05 +01:00
Stone Widder
204ae7b6c6
Fix long break condition calculation (#6259)
* Fix long break condition calculation

Adjust calculation for long break condition to account for cycle update.

* Undo Previous Change to getBreakDuration

* Move fix To Focus-Mode.effects

Adjust break duration calculation to account for cycle increment.

* Fix formatting of getBreakDuration calculation

* fix Test(pomodoro-bug-6044): Change test cases to be correct

* fix(Focus-Mode-Session-done): Subtract 1 from cycle to get last cycle

* Fix Test(focus-mode-effect.spec): Verify decrement of cycle

* Fix(focus-mode.effect.ts): Make comments clearer

* Fix(Pormodoro-Bug-6044.spec): Update tests names

* fix(focus-mode-effects.ts): Fix Missed tests

* Add(fpcis-mode-session-done): add || 1 Guard

* Fix Linting and formatting

* fix(focus-mode.effects.spec.ts): update cycle number for manual break duration calculation
2026-02-03 13:55:56 +01:00
Andrii Hrushetskyi
b9fde5fb53
feat: add Czech, Slovak, and Ukrainian calendar locale support and correct Czech language code from 'cz' to 'cs'. (#6329) 2026-02-03 13:02:59 +01:00
Gitoffthelawn
29ed466122
Further improve English i18n (#6336)
In this update, I focused on improving UI consistency and adhering to UI standards.
2026-02-03 12:24:44 +01:00
Johannes Millan
b66b680e30
fix: address code review findings across sync, tasks, and UI (#6339)
- fix(tasks): preserve selectAllTasks memoization by only filtering when
  undefined entities exist, avoiding new array allocation on every call
- fix(sync): replace mutable ARGON2_PARAMS export with getter/setter to
  prevent test pollution across spec files
- fix(sync): convert tag-task-page from async pipe to toSignal pattern
  to fix OnPush change detection after bulk sync state updates
- fix(sync): remove E2E navigation workarounds that masked the rendering
  bug now fixed by the toSignal conversion
- fix(sync): add clarifying comments for archive-wins sibling conflict
  resolution and waitForSyncWindow switchMap concurrency semantics
- fix(ios): add hex preview of first 16 bytes to WebDAV UTF-8 decode
  error for easier debugging
- docs: add JSDoc to getDiffInWeeks noting negative diff behavior

https://claude.ai/code/session_01Y51QDFEdvrJ9VVgp9XfWLJ

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-03 12:13:57 +01:00
Johannes Millan
c6701ba2d8 fix(test): add missing skipConflictDetection arg in forceDownloadRemoteState test 2026-02-02 21:41:10 +01:00
Johannes Millan
9ff4d5e7cb fix(sync): address code review findings for E2E tests and sync services
Remove unused _counterTitle parameter from counter helpers, replace
hardcoded waitForTimeout with visibility check, unify timeout strategy
to test.slow(), fix waitForSyncToComplete API call, add
skipConflictDetection for forceDownloadRemoteState, and clean up
package-lock.json.
2026-02-02 21:28:36 +01:00
Johannes Millan
741d7b61e7 fix(habit-tracker): remove unused MsToStringPipe import 2026-02-02 21:10:48 +01:00
Johannes Millan
0b14ba83ae fix(sync): address code review findings for archive-wins and entity frontier
- Use toEntityKey() utility instead of inline template strings
- Fix stale mock in remote-ops-processing.service.spec.ts to match
  new _buildEntityFrontier logic (appliedFrontier !== undefined)
- Fix transient entity resurrection: non-archive conflicts for
  locally-archived entities now resolve as local-wins (no localWinOp)
  instead of remote-wins, preventing addOne() from resurrecting entities
- Add unit test for multi-conflict pre-scan scenario
- Add TODO comments for Angular reactivity navigation workarounds
2026-02-02 21:06:19 +01:00
Johannes Millan
0dd49c1894 fix(sync): archive-wins pre-scan and entity frontier for new clients
Fix two sync bugs causing E2E test failures:

1. Archive-wins pre-scan: When an entity has multiple conflicts (e.g.,
   field updates + archive), the archive op was only checked per-conflict.
   Non-archive conflicts resolved via LWW, creating local-win update ops
   that resurrected archived entities. Now pre-scans ALL conflicts to
   build entity-level sets, so all conflicts for an archived entity
   resolve as archive-wins.

2. Entity frontier for new entities: When snapshotEntityKeys was undefined
   (old format), _buildEntityFrontier used the snapshot vector clock for
   ALL entities, inflating the frontier for genuinely new entities never
   seen locally. Remote ops for these entities were incorrectly discarded
   as superseded. Now only uses snapshot clock when appliedFrontier exists
   for the entity.

Also improves E2E tests with navigation-based component refresh and
Playwright auto-retry assertions (toHaveCount with timeout).
2026-02-02 20:32:32 +01:00
Johannes Millan
5e0453203c fix(tasks): filter undefined entities in selectAllTasks to prevent crashes 2026-02-02 18:23:57 +01:00
Johannes Millan
ef480810a9 perf(test): speed up slow encryption and large batch sync tests
Extract Argon2 params into mutable exported constant so tests can use
minimal KDF settings (8 KiB memory, 1 iteration) instead of production
values (64 MB, 3 iterations). Add batch operation creation helper and
configurable download limit to SimulatedClient, reducing test op counts
from 500-1000 to 50-100 while still exercising pagination.
2026-02-02 18:19:48 +01:00
Johannes Millan
b6db912665 fix(tasks): filter undefined subtasks in mapSubTasksToTask (#6325)
Prevent "Cannot read properties of undefined" crash when subtask
entities are transiently missing during sync import or recurring
task replay.
2026-02-02 17:15:13 +01:00
Johannes Millan
9810c320b1 fix(tasks): prevent recurring tasks from failing to repeat (#6192)
Use immutable `created` timestamp instead of mutable `dueDay` for
duplicate detection in task-repeat-cfg.service.ts. The old check
used dueDay which gets mutated by planTasksForToday when users
reschedule overdue tasks, causing false-positive duplicate matches.

Replace filter-and-drop with waitForSyncWindow operator in all three
TaskDueEffects so day-change emissions during hydration/sync are
deferred rather than permanently lost.

Add waitForSyncWindow reusable RxJS operator and expose isInSyncWindow
as a computed signal + observable on HydrationStateService.
2026-02-02 17:15:13 +01:00
Johannes Millan
d74ab299d9 fix(main-header): center sync icon glyph to eliminate spin wobble
Use inline-flex centering on the mat-icon to align the font glyph
to the geometric center of its bounding box, and promote the spinning
element to a GPU compositing layer via translateZ(0) to prevent
sub-pixel anti-aliasing shifts during rotation.

Closes #6318
2026-02-02 17:15:13 +01:00
Johannes Millan
e6930390d0 fix(inline-markdown): preserve unsaved content when adding checklist item
Save current textarea value before toggling checklist mode to prevent
content loss when mousedown.preventDefault() blocks the blur event.
2026-02-02 17:15:13 +01:00
Johannes Millan
68309b731d fix(focus-mode): stop time tracking when exiting break to planning
exitBreakToPlanning resets focus session state but had no effect to stop
tracking, leaving it running orphaned. Add effect to dispatch
unsetCurrentTask() when isSyncSessionWithTracking is enabled.
2026-02-02 17:15:13 +01:00
Johannes Millan
9002157a6b test(util): add coverage for extract-first-emoji edge cases
Add tests for plain #/digit false-positive guards, null/undefined/non-string
inputs, and isSingleEmoji with variation selector emoji (❤️).
2026-02-02 17:15:13 +01:00
Johannes Millan
3154dbbb8c fix(tasks): handle compound emojis in icon input using Intl.Segmenter
Replace manual Unicode code-point iteration with Intl.Segmenter for
correct handling of ZWJ sequences, flag emojis, and keycap emojis.
Fixes #6256.
2026-02-02 17:15:13 +01:00
Johannes Millan
875341f04a fix(tasks): correct biweekly recurring task week boundary calculation (#6298)
getDiffInWeeks used Math.round(ms / weekMs) which rounded Friday (day 4
of 7) into the next week. Switch to day-first calculation with
Math.floor(days / 7) to respect week boundaries while preserving DST
safety via Math.round on the day count.
2026-02-02 17:15:13 +01:00
Johannes Millan
fcedc4ed05 fix(sync): add native iOS WebDAV plugin to fix broken read on iPhone
iOS WebDAV sync could write but not read data due to Capacitor's native
bridge auto-parsing responses as JSON and replacing data with error strings.
Add a native URLSession-based plugin (matching the existing Android one)
that bypasses CapacitorHttp entirely.

Fixes #6317
2026-02-02 17:15:13 +01:00
Johannes Millan
cd2ae61ae0 Revert "feat(sync): add rolling JWT token refresh on sync requests"
This reverts commit eca323505d1923fcfc470d78fc8984251e825382.
2026-02-02 17:15:13 +01:00
Johannes Millan
6a2b7e3b9b fix(sync): handle concurrent ops for archived/deleted entities
Make checkOpForConflicts async to check current entity state when
a CONCURRENT remote op targets an entity with no pending local ops.
If the entity no longer exists in state (archived/deleted), treat
concurrent updates as superseded to prevent ghost resurrections.
2026-02-02 17:15:13 +01:00
Johannes Millan
717e4ba84d feat(sync): add rolling JWT token refresh on sync requests
On each successful sync request, the server now returns a fresh 14-day
JWT via X-Refreshed-Token response header. The client reads and stores
it automatically, preventing token expiry during active usage.

Server: export JWT_EXPIRY/getJwtSecret from auth, add createRefreshedToken(),
add onSend hook scoped to sync routes, expose header via CORS.
Client: store refreshed token in all 4 fetch methods, fix _getServerSeqKey
to hash only baseUrl (prevents full re-download on token change).
2026-02-02 17:15:13 +01:00
Johannes Millan
2a6de0e41f fix(sync): remove dead code, add defensive checks, and clean up vector clock logic
- Remove redundant subset condition in compareVectorClocks
- Add clarifying comment for conservative return in hasVectorClockChanges
- Batch per-key verbose logs into single summary log
- Add defensive warning for negative startingSeq in file-based sync
- Extract magic timeout constant in E2E test
- Update stale doc date
2026-02-02 17:15:13 +01:00
Andrii Hrushetskyi
224ee200dd
Extending Ukrainian and Czech translations (#6292)
* feat: Extended ukrainian translation

Added the properties that do exist in en.json, but didn't exist in uk.json.

BUT, PLEASE PAY ATTENTION, Most of that new properties that I added, were translated using LLM, I didn't review each of them, so they still need human review

* feat: Extended czech translation

Added the properties that do exist in en.json, but didn't exist in cz.json.

BUT, PLEASE PAY ATTENTION, Most of that new properties that I added, were translated using LLM, I didn't review each of them, so they still need human review

* fix: Fixes after claude PR review

https://github.com/super-productivity/super-productivity/pull/6292#discussion_r2749397256
2026-02-02 14:28:41 +01:00
Lisontowind
6bc810f209
Add a management page for habits (#6265)
* feat: introduce habit tracking page and enhance simple counters with streak tracking and comprehensive configuration options.

* feat: add habit tracker for simple counters with navigation and internationalization.

* feat: Introduce habit tracker component and tests for simple counter streak duration calculation.

* Fix the dialog style that appears in the Habit interface

* bug fix

* Fixed translation and time zone issues

* habit icon

* app features

* Add a Settings button to the Habits page; clicking it opens the Settings interface and automatically expands the corresponding configuration section.
Clicking a habit icon allows you to configure that habit. To add a new habit, click the “Add” button.

* If a habit does not have a custom icon, its first character can be displayed inside a circular placeholder instead.

* The dialog box appears only after you release the button following a long press.

* Add the functionality to display names; clicking the button shows the habitual name. This can be persisted

* bug修复:Date adjustment (left/right) in shrink mode is not functioning as expected.

* Set Text Icon

* Fix abnormal icon size

* These development artifacts should not be committed to the repository.

* Lost Chinese translations

* Flaky Date-Dependent Tests

* Logic error in streak calculation

* Fix the icon issue

* Translation file violation
Use of any type

---------

Co-authored-by: Xinjie <xinjie_zhou@163.com>
2026-02-02 14:24:00 +01:00
Peter
e1f01de5f3
fix: undefined redmine ticket (#6279)
* fix: undefined redmine ticket

* feat: post time tracking to Redmine

* feat: add ENG translation

* chore: remove debug log
2026-02-02 14:19:54 +01:00
Jehandad Kamal
78699d278e
fix(backup): support importing pre-v17 backups (v10-v15 tested, v16 partial) (#6271)
* fix(backup): support importing legacy v10-v13 backups into v17

When v17 rewrote the sync architecture (PFAPI → operation-log), all
cross-model migrations (2 through 4.5) were dropped. This means backups
created by v10-v13 cannot be imported — they fail Typia validation
because the data shape is incompatible and archived tasks are silently
lost.

Add `migrateLegacyBackup()` which consolidates the essential v16
cross-model migrations into a single pass that runs before validation:

- Migration 2: Split flat `taskArchive` → `archiveYoung`/`archiveOld`,
  extract `timeTracking` from project/tag properties
- Migration 3: Planner→dueDay, INBOX project, legacy tag cleanup
- Migration 4: `plannedAt`→`dueWithTime`, strip TODAY_TAG from tagIds
- Migration 4.1-4.2: Task repeat config cleanup
- Migration 4.3-4.5: menuTree, localization, appFeatures, lowercase

The detection (`isLegacyBackupData`) only triggers on definitive legacy
markers (`taskArchive`, `improvement`, `obstruction` keys) so modern
backups are unaffected.

Tested against a real v10-era backup (253 tasks, 155 archived, 19
projects) — all data preserved after migration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(backup): replace large fixture with minimal v10 scaffold

Replace the 17k-line migrated backup dump with a small hand-crafted
fixture (~160 lines) that exercises every legacy edge case: flat
taskArchive, workStart/workEnd on projects, _showSubTasksMode, numeric
issueId, null timeEstimate/created, plannedAt, TODAY_TAG in repeat
configs, and lang config section.

Add 12 fixture-based tests that verify each of these conversions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(backup): resolve lint issues in legacy migration code

- Cast legacy project/tag to `any` (v17 types lack workStart/workEnd)
- Remove unused TaskState import
- Rename functions to camelCase (eslint naming-convention)
- Add eslint-disable for prefer-arrow-functions and naming-convention
- Replace require() with ES import for test fixture
- Fix prettier formatting in backup.service.ts import

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(backup): preserve archiveYoung for v13-v15 backups in migration 2

Migration 2's skip condition checked timeTracking.project length, which
is 0 for users who never used project-level work tracking. For v13-v15
backups (already archive-split but detected via improvement/obstruction),
this caused archiveYoung to be overwritten with empty data since
taskArchive is undefined.

Fix: skip migration 2 when archiveYoung already has tasks, or when
archiveYoung + archiveOld + timeTracking all exist without taskArchive
(meaning migration 2 already ran in v13+).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(backup): use nullish coalescing for numeric task fields in migration

Use ?? instead of || for issueAttachmentNr and issuePoints to preserve
valid 0 values during legacy backup migration. Add tests for this case.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 14:17:04 +01:00
Dastan
ea61d6a89f
feat(theme): add Cybr. New THEME (#6314)
* feat(theme): add Cybr. New THEME

* fix(theme): update font family and adjust scanline effect for improved aesthetics
2026-02-02 14:14:09 +01:00
Diego
15e87be577
Update es.json (#6315)
* Update es.json

Modified typos found while using the app, also gave better structure to some phrases on the UI that weren't clear due to lack of context.

Will check further whenever I am able to.

* Update src/assets/i18n/es.json

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

---------

Co-authored-by: Johannes Millan <johannesjo@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-02 13:20:56 +01:00
Andrii Hrushetskyi
4179a0f6ef
fix(inline-markdown): update placeholder and modelCopy to use empty string instead of undefined string (#6281) 2026-01-31 01:42:28 +01:00
Johannes Millan
e97d530d2a 17.0.12 2026-01-30 21:13:40 +01:00
Johannes Millan
29d211a5e4 fix(sync): add warning for preserved IDs exceeding MAX_VECTOR_CLOCK_SIZE in vector clock pruning 2026-01-30 21:13:07 +01:00
Johannes Millan
6d72472681 fix(sync): use syncVersion instead of ops count for upload latestSeq
After upload, latestSeq was set to mergedOps.length (total ops count)
instead of finalSyncVersion. This caused false "Server sequence
decreased" warnings when ops count exceeded syncVersion, and could
trigger unnecessary re-downloads. Aligns upload with download behavior
which already correctly uses syncVersion.
2026-01-30 20:31:48 +01:00
Johannes Millan
192ec62d4a fix(sync): harden vector clock comparison and fix docs
- Replace fragile VectorClockComparison[result] enum lookup with safe cast
- Return CONCURRENT instead of EQUAL when only one side has non-shared
  keys in pruning-aware mode (safe direction: triggers LWW instead of
  silent skip)
- Fix docs claiming clocks "reset" at MAX_SAFE_INTEGER (they throw)
2026-01-30 20:05:48 +01:00
Johannes Millan
c5409bbd25 fix(sync): add server pruning log, harden test coverage for vector clocks
- Add Logger.warn() in ValidationService when oversized vector clocks
  are pruned server-side, improving observability for buggy clients
- Add tests for hasVectorClockChanges (previously zero coverage)
- Add symmetric LESS_THAN test for pruning-aware comparison mode
- Export MAX_LWW_REUPLOAD_RETRIES constant to eliminate magic number
  coupling between sync-wrapper service and its test
- Add test verifying uploading client ID is preserved during server-side
  clock pruning
- Add test for limitVectorClockSize when preserveClientIds exceeds MAX
2026-01-30 19:50:30 +01:00
Johannes Millan
495f0fe0d3 fix(sync): improve vector clock pruning awareness and harden tests
Make hasVectorClockChanges pruning-aware by checking clock size before
logging missing keys — downgrade to verbose when pruning is likely,
warn when corruption is likely. Add return value assertion to LWW retry
exhaustion test, asymmetric pruning test cases, server-side pruning
tradeoff documentation, and fix stale "max 50" in docs.
2026-01-30 19:35:51 +01:00
Johannes Millan
b113a2d7dd fix(sync): return CONCURRENT instead of EQUAL when pruned clocks have non-shared keys
When both vector clocks are at MAX size (pruning-aware mode) and shared
keys compare as equal, non-shared keys on both sides indicate genuinely
different causal histories. Returning EQUAL caused silent data loss by
skipping operations as duplicates. Returning CONCURRENT safely triggers
LWW conflict resolution instead.

Also fixes server snapshot pruning to preserve the requesting client's
ID and the snapshot author's client ID when limiting vector clock size.
2026-01-30 19:21:45 +01:00
Johannes Millan
002c37e054 fix(sync): guard empty intersection in vector clock comparison and fix LWW return value
Return CONCURRENT instead of EQUAL when two max-size clocks share no
keys (independent client populations). Fix misleading SyncStatus.InSync
return when LWW retry exhaustion leaves pending ops. Document known
limitation of size-based pruning heuristic. Add missing edge case tests.
2026-01-30 19:17:02 +01:00
Johannes Millan
fd3d06c5ff test(sync): add tests for vector clock pruning and LWW retry loop fix
Cover all 4 changes from cb36c09538: shared-schema vector clock tests
(22 Vitest), sync wrapper LWW retry loop limit tests (4 Jasmine),
client vector clock pruning-aware comparison tests (3 Jasmine), and
E2E tests for heavy LWW conflict, TAG:TODAY convergence, and
multi-client vector clock consistency (3 Playwright).
2026-01-30 19:04:44 +01:00