Skip to content

fix(sync): propagate connection group membership changes to other devices#1477

Merged
datlechin merged 2 commits into
mainfrom
fix/group-membership-sync
May 29, 2026
Merged

fix(sync): propagate connection group membership changes to other devices#1477
datlechin merged 2 commits into
mainfrom
fix/group-membership-sync

Conversation

@datlechin
Copy link
Copy Markdown
Member

Problem

On one Mac, connections are organized into groups and iCloud sync is on. On a second Mac with sync enabled, the groups and connections both arrive, but the connections show up flat (ungrouped) and the groups report a count of 0. The group membership is lost across devices.

Root cause

Group membership lives in connection.groupId. Three paths that change it persisted via the low-level ConnectionStorage.saveConnections(_:), which writes the file but does not mark connections dirty for sync (unlike addConnection / updateConnection / updateConnections and the form-save and reorder paths):

  • WelcomeViewModel.moveConnections(_:toGroup:)
  • WelcomeViewModel.removeFromGroup(_:)
  • GroupStorage.deleteGroup(_:)

So a groupId change saved locally but never re-pushed. The connection record in iCloud kept its last-pushed groupId (usually nil). Groups themselves synced fine (GroupStorage.saveGroups marks groups dirty), so the second device pulled correct groups but stale connections, leaving them ungrouped with empty group counts.

This reproduces when grouping happens while sync is already on. When grouping happens before enabling sync, enableSync() marks all data dirty and pushes everything correctly, which is why it sometimes works.

Fix

Route the three membership mutations through the existing updateConnections(_:) API, which persists once and marks each changed connection dirty (and skips localOnly / sample connections). This keeps saveConnections as a pure write primitive, which the sync-apply path and load-time migration rely on.

Tests

  • New testDeleteGroupClearsMembershipAndMarksConnectionDirtyForSync in GroupStorageTests asserts that deleting a group clears groupId on its connections and marks them dirty for sync.
  • The WelcomeViewModel paths are covered transitively: updateConnections' dirty-marking is already tested in ConnectionStoragePersistenceTests.

Recovering already-affected devices

On the device that owns the correct grouping, toggle iCloud sync off then on. enableSync() re-marks all local data dirty and re-pushes every connection with its current groupId, which the other device then pulls.

@datlechin datlechin merged commit b9764dd into main May 29, 2026
1 check passed
@datlechin datlechin deleted the fix/group-membership-sync branch May 29, 2026 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant