The SHORT_SYNTAX_URL_REG_EX greedily matched the closing ')' from
markdown link syntax like [Website](https://example.com/), producing
malformed URLs and broken titles in extract mode. Fix by detecting
markdown links first, extracting their URLs correctly, then running
the plain URL regex on the remainder.
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.
Set localStorage flags (onboarding preset, hints, tour, example tasks)
via addInitScript before app boots, preventing onboarding overlays and
example tasks from interfering with e2e tests. Also switch archive
import/subtask specs to use the shared test fixture for proper isolation.
- Replace drag handle with SVG done-toggle circle with checkmark draw-on animation
- Improve mobile UX: cdkDragStartDelay for touch, bottom-sheet context menu
- Move issue/repeat indicators from drag handle to tag-list as chips
- Add isFinishDayEnabled config toggle
- Reorder context menu: add sub task before duplicate, deadline as own entry
- Fix context menu not opening on swipe left
- Fix race condition in done toggle animation timeout
Remove the full welcome tour (Welcome, AddTask, DeleteTask, Projects,
Sync, IssueProviders, ProductivityHelper, FinalCongrats, StartTourAgain)
and keep only the KeyboardNav tour, triggered from the Help menu.
- Delete ShepherdComponent (auto-start on load)
- Strip shepherd-steps.const.ts to KeyboardNav steps only
- Simplify ShepherdService with _initPromise guard and fresh tour on re-open
- Remove 3 tour menu items from Help menu, keep keyboard tour
- Remove waitForEl/waitForElObs$ helpers (unused by KeyboardNav)
- Delete e2e/utils/tour-helpers.ts and all tour dismissal calls
- Clean up stale tour comments across e2e tests
- Fix pre-existing build error: add isFinishDayEnabled to AppFeaturesConfig
type, defaults, form toggle, component signal, and translations
Planning mode added unnecessary UI complexity — the global add-task-bar
provides the same functionality and is always accessible via the header
button, keyboard shortcut, or mobile FAB.
- Remove PlanningModeService entirely
- Always show status bar and finish-day button
- 'Add more' button now opens the global add-task-bar
- Relocate 'add scheduled for tomorrow' button into empty state
- Remove E2E workarounds for planning mode exit
- Remove orphaned translation keys from t.const.ts and en.json
- Fix decorative image alt text for screen readers
When importing a backup file locally, archive data (archiveYoung and
archiveOld) was not being persisted to IndexedDB. This caused archived
tasks to be lost after page reload.
Root cause: ArchiveOperationHandler._handleLoadAllData() returns early
for local imports (isRemote=false), expecting the archive to be written
by the backup import flow - but this code never existed.
Fix: Add _writeArchivesToIndexedDB() to BackupService.importCompleteBackup()
that explicitly writes archive data to IndexedDB after dispatching the
loadAllData action.
- Add ArchiveDbAdapter injection to BackupService
- Add _writeArchivesToIndexedDB() private method
- Update misleading comment in ArchiveOperationHandler
- Add unit tests for archive persistence (7 tests)
- Add E2E tests for archive import persistence (3 tests)
- Add test fixture with archive data
The tests were failing because:
1. The backup file has tasks with dueDay in the past (2024-12-01)
2. TODAY tag is a "virtual tag" where membership is determined by
task.dueDay === today, not by taskIds
3. When all tasks are done, planning mode activates and hides the
Finish Day button
Fix by:
- Navigate to INBOX project to view and mark tasks as done
- Navigate to TODAY tag to access the Finish Day button
- Exit planning mode by clicking "Ready to work!" if visible
- Then proceed with Finish Day flow
The PfapiStoreDelegateService was reading archive data from NgRx store,
but archives are stored in ModelCtrl (pf database), not NgRx. The NgRx
archive state is only populated on loadAllData (import) and is never
updated when ArchiveService writes to ModelCtrl during finish day.
This caused exports to contain empty/stale archiveYoung data after
archiving tasks via "Finish Day", resulting in lost subtasks.
The fix reads archiveYoung and archiveOld from ModelCtrl (via
pfapiService.m.archiveYoung.load()) instead of NgRx selectors, since
that's where the actual archive data lives.
Includes E2E test to verify subtasks are preserved in archive after
legacy data import and finish day flow.
Add E2E and integration tests documenting a bug where tasks with
subtasks are lost when:
1. Importing legacy data (pre-operation logs)
2. Archiving via "Finish Day"
3. Exporting again
The archiveYoung ends up empty in the export. Tests will pass
once the bug is fixed.
Files added:
- e2e/fixtures/legacy-archive-subtasks-backup.json
- e2e/tests/import-export/legacy-archive-subtasks.spec.ts
- integration/legacy-archive-subtasks.integration.spec.ts