The E2E tests were failing because dismissTourIfVisible only handled
the Shepherd tour steps, not the Welcome intro mat-dialog that appears
first. This dialog blocks UI interactions causing test timeouts.
Updated tour-helpers.ts to:
- Add dismissWelcomeDialog() for the intro dialog
- Add dismissShepherdTour() for the tour steps
- Update dismissTourIfVisible() to handle both in sequence
The test was failing because task deletion now shows a confirmation
dialog by default (isConfirmBeforeTaskDelete=true). Added handling
to click the confirm button before expecting the task count to change.
docker-compose.e2e.yaml was failing when used standalone because the
supersync service only had a port override without a base definition.
Split into separate files so e2e:docker:webdav works without errors.
- Apply runtime default for isConfirmBeforeTaskDelete to ensure existing users get confirmation dialog
- Add takeUntil cleanup for dialog subscription in context menu
- Move _isTaskDeleteTriggered flag before delete call to prevent race condition
- Replace alert() with PFLog.warn() for non-blocking notification
- Change any to unknown type for better type safety
- Localize month names using DateAdapter instead of hardcoded English strings
- Remove duplicate monthNames array declaration (DRY)
Extract reusable heatmap component from activity-heatmap and add
a new repeat-task-heatmap that shows time spent history for
repeatable task instances in the configuration dialog.
Add handlers to autoFixTypiaErrors to fix validation errors for deprecated
fields that will be removed in future:
- metric.entities[*].obstructions, improvements, improvementsTomorrow
- improvement.hiddenImprovementBannerItems
These fields are now auto-fixed to empty arrays when missing/undefined,
allowing import of older backups without validation failures.
Apply GitHub's OR pattern to fix timing bug while preserving filterUsername.
Refactor getFreshDataForIssueTasks to call getFreshDataForIssueTask (DRY).
Fixes inconsistency from #5944 where only one method was updated.
When the app is backgrounded on Android, the focus mode countdown timer
now triggers a high-priority notification with alarm sound and vibration
when it completes. Previously, only the silent foreground service
notification was shown, causing users to miss timer completion.
Changes:
- Add completion notification channel with IMPORTANCE_HIGH
- Detect timer completion in FocusModeForegroundService
- Broadcast completion event to activity via LocalBroadcastManager
- Forward event to Angular via onFocusModeTimerComplete$ subject
- Handle native completion in effects to sync app state
Fixes#5923
Fixes#5921: When a task was rescheduled by removing the time and
changing only the date, the native Android alarm would still fire at
the original time. This was because removeTaskReminderSideEffects$
only removed the reminder from ReminderService but did not cancel
the native Android alarm.
Added explicit native Android alarm cancellation following the same
pattern used in clearRemindersOnDelete$, unscheduleDoneTask$, and
other similar effects.
Add service-level deduplication to prevent the same reminder from
triggering multiple notifications when the worker's 10-second polling
interval races with state updates.
The fix tracks recently processed reminder IDs and filters them out
before emitting. IDs are cleared when snoozing (to allow re-trigger at
new time) and auto-cleaned after 60 seconds to prevent memory leaks.
Closes#5925
Add isFocusWindow setting to reminder config, defaulting to false.
This prevents the app from stealing focus when reminders fire, which
was interrupting users working in other applications.
Closes#5922
Display weekday alongside date when tasks are grouped by scheduled date
(e.g., "Wed 1/15" instead of "2025-01-15"), making it easier to identify
weekends at a glance.
Closes#5941
Add optional setting to show confirmation dialog when deleting tasks
via keyboard shortcut (Backspace) or context menu. This prevents
accidental cascading deletions when users press Backspace expecting
browser-like "go back" behavior.
- Add isConfirmBeforeTaskDelete setting (defaults to true)
- Add confirmation dialog to TaskComponent.deleteTask()
- Add confirmation dialog to context menu deleteTask()
- Add setting checkbox in Settings > Misc
- Add unit and E2E tests for the feature
Closes#5942
supersync-models.spec.ts:
- Replace fragile inline tag deletion with robust retry-wrapped implementation
- Use toPass() with increasing intervals for automatic retries
- Properly expand Tags section before finding target tag
- Wait for tag to disappear as final verification
supersync-server-migration.spec.ts:
- Remove unnecessary waitForTimeout(500) before sync
- Existing waitForTask() calls handle synchronization properly
Add comprehensive E2E test that verifies legacy data (pre-operation-log
format) migrates correctly when the app starts. The test:
- Seeds legacy 'pf' IndexedDB database with test data before app loads
- Verifies backup file is downloaded during migration
- Validates all data migrates correctly including:
- Tasks with subtasks (parent-child relationships)
- Projects and tags
- Sync provider settings (WebDAV/SuperSync configs)
- Archive data (archiveYoung and archiveOld)
- Time tracking data and notes
Includes comprehensive fixture file with realistic legacy state format.
Verifies the core sync filtering mechanism that all 27 effects depend on:
- LOCAL_ACTIONS filters out actions with meta.isRemote: true
- LOCAL_ACTIONS passes through local actions (no meta or isRemote: false)
- ALL_ACTIONS receives both remote and local actions
This single test validates the filtering mechanism that prevents effects
from running during remote sync operations.
Replace sequential hasOp() + append() calls with batch operations:
- Use filterNewOps() to batch-check for duplicate ops
- Use appendBatch() to write multiple ops in a single transaction
- Reduces O(n) database calls to O(2) for each operation category
This optimization applies to:
- Remote-wins conflict ops
- Local-wins remote ops (stored then rejected)
- Non-conflicting piggybacked ops
Updated tests to expect appendBatch calls instead of append.
Adds E2E test for the scenario where an already-syncing client detects
that another client has uploaded a snapshot replacement:
1. Client A sets up sync, uploads initial data
2. Client B connects (no local data), downloads A's data
3. Client B creates a local task (not yet synced)
4. Client C connects with local data, resolves conflict with USE_LOCAL
5. Client B syncs and should detect the gap/snapshot replacement
This tests the fix for snapshot replacement detection in
file-based-sync-adapter.service.ts, which uses clientId comparison
when available and falls back to syncVersion comparison otherwise.
- auto-fix-typia-errors.ts: use unknown with type guards in path utilities
- data-repair.ts: add type-safe helper for entity state reset
- is-data-repair-possible.util.ts: use 'in' operator for property checks
- is-related-model-data-valid.ts: use MenuTreeTreeNode type instead of any[]
- sync.types.ts: use recursive Serializable type for SerializableObject
- sync-errors.ts: use IValidation<unknown> for validation result types
- dropbox-api.ts: use string | Record<string, unknown> for upload data
- persistent-action.interface.ts: add eslint-disable comment for justified any
When detecting snapshot replacement during op download, use a dual-strategy:
- If excludeClient is provided: use clientId comparison (more accurate)
- If excludeClient is undefined: fall back to syncVersion comparison
This fixes gap detection when another client uploads a fresh snapshot
that replaces all ops but keeps syncVersion at 1.
The ternary handles both scenarios:
- Unit tests: pass excludeClient, use clientId check
- Download service: passes undefined, uses syncVersion check
Add unit tests for LWWOperationFactory and StateSnapshotService to
improve test coverage. Optimize remote ops processing by replacing
sequential append calls with a single appendBatch call, reducing
N database transactions to 1.
Playwright throws ENOENT errors when finalizing trace artifacts for
manually-created browser contexts. This is a known issue when using
trace: 'retain-on-failure' with contexts created via browser.newContext().
The fix extends error handling to catch and log these cleanup errors
instead of failing the test after assertions have already passed.
The initial fix returned correct serverSeq after snapshot upload,
but snapshotReplacement gap detection still triggered incorrectly.
When sinceSeq equals syncVersion, we're in sync (our own upload),
not detecting another client's snapshot replacement.
Added E2E regression test for WebDAV sync to verify no repeated
conflict dialog after USE_LOCAL resolution.
Update test fixtures to use correct NgRx entity format (task, project,
tag, globalConfig) instead of invalid plural keys (tasks, projects).
This aligns tests with the payload validation added in 2d26228ca.
Rather than comparing the issues last update timestamp with the last comment timestamp, it now compares the issue last update timestamp with the task `issueLastUpdated` property. This avoids the latency between an update and the update being logged in the comments.
Fixes#5518