mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
* feat(sync): show banner when LWW discards a user content edit Auto-resolved LWW conflicts were only surfaced as a generic "N local/ remote wins" count snack, so a field-level edit silently dropped by last-write-wins (e.g. a title edit lost to a concurrent notes edit) was invisible to the user (#8694). Split the resolution outcome: routine self-healing (reschedule/repeat/ archive/done churn) keeps the quiet count snack, while a resolution that discarded a genuine content edit (task title/notes/subtasks/attachments) shows a dismissible banner naming the affected task(s). - New pure summarizeLwwResolutions() classifier in @sp/sync-core (inspects the losing side's changed fields; UPDATE only, so create/delete/move and scheduling churn stay routine). - Titles are HTML-escaped before the innerHTML banner (they come from synced remote data) and never logged. * fix(sync): correct + simplify LWW content-conflict notice (multi-review) Address multi-agent review of the previous commit: - CRITICAL: the classifier's multi-entity branch made the feature a no-op in production. Captured ops are always wrapped as { actionPayload, entityChanges: [] } and task edits never populate entityChanges (only time-tracking does), so a real title/notes edit was read as having no changed fields → classified routine → banner never fired. Fixed by dropping the branch and relying on extractUpdateChanges (which unwraps actionPayload), gated to UPDATE ops. Spec now uses the real wrapped payload shape so this can't regress. - Move the classifier out of the framework-agnostic @sp/sync-core package into the app (findLwwContentConflicts); it held app-specific TASK field names and was exported but unused. TASK-only, no generics/callback. - De-duplicate content conflicts per task (one task can yield several concurrent conflicts) so the banner never lists a title twice. - Direction-neutral wording ("Older edits may have been discarded") since the discarded side depends on which client won. - Use the banner's built-in dismiss button instead of a no-op action. - Consolidate escapeHtml: escapeHtmlAttr now re-exports the shared util. - Guard against a non-string title before trim(). * fix(sync): drop dead 'attachments' from LWW content fields (review) Second-review WARNING: attachments are edited via dedicated [TaskAttachment] actions with payload { taskId, taskAttachment }, never updateTask({ task: { changes: { attachments } } }), so extractUpdateChanges never surfaces an 'attachments' key — the entry could never match and falsely claimed coverage. Removed it (title/notes/subTaskIds are live) and added a guard test asserting a real attachment-action-shaped op is not flagged, so it isn't naively re-added. |
||
|---|---|---|
| .. | ||
| long-term-plans | ||
| plans | ||
| promotion | ||
| research | ||
| screens | ||
| sync-and-op-log | ||
| wiki | ||
| add-new-integration.md | ||
| android-edge-to-edge-keyboard.md | ||
| apple-release-automation.md | ||
| build-and-publish-notes.md | ||
| documentation-guide.md | ||
| ENV_SETUP.md | ||
| github-access-token-instructions.md | ||
| gitlab-access-token-instructions.md | ||
| how-to-rate.md | ||
| howto-refresh-snap-credentials.md | ||
| i18n-script-usage.md | ||
| legacy-webview-analysis.md | ||
| mac-app-store-code-signing-guide.md | ||
| performance-project-tag-report.md | ||
| plainspace-api-extension-plan.md | ||
| plainspace-integration-plan.md | ||
| plugin-development.md | ||
| styling-guide.md | ||
| theming-contract.md | ||
| TRANSLATING.md | ||
| unused-translations-analysis.md | ||
| update-android-app.md | ||
| update-mac-certificates.md | ||