Skip to content

feat: sync settings across devices via Matrix account data#409

Closed
Just-Insane wants to merge 1 commit intodevfrom
feat/settings-sync
Closed

feat: sync settings across devices via Matrix account data#409
Just-Insane wants to merge 1 commit intodevfrom
feat/settings-sync

Conversation

@Just-Insane
Copy link
Contributor

@Just-Insane Just-Insane commented Mar 20, 2026

Closes #402

What

Adds opt-in settings synchronisation across devices using Matrix account data (moe.sable.app.settings), plus a JSON export/import fallback for users who prefer manual control.

How it works

  • Sync toggle (off by default) in General settings enables live sync
  • On toggle-on, settings are loaded from account data immediately
  • Local changes are debounced 2 s then uploaded to account data
  • Echo-token loop prevention: each upload embeds a random token; when the homeserver echoes the event back the hook recognises it and skips re-applying (avoiding a feedback loop)
  • Events arriving from other devices are applied and merge over local state
  • Non-syncable keys are always taken from local state and never uploaded: usePushNotifications, useInAppNotifications, useSystemNotifications, pageZoom, isPeopleDrawer, isWidgetDrawer, memberSortFilterIndex, developerTools, settingsSyncEnabled

JSON export / import

Available regardless of whether sync is enabled. Export triggers a browser download; import opens a file picker and merges the selected file into current settings (same schema validation as the sync path).

Files changed

File Purpose
src/types/matrix/accountData.ts SableSettings = 'moe.sable.app.settings' enum value
src/app/state/settings.ts settingsSyncEnabled: boolean (default false)
src/app/utils/settingsSync.ts serialize / deserialize / export / import helpers
src/app/hooks/useSettingsSync.ts side-effect hook + status atoms
src/app/pages/client/ClientNonUIFeatures.tsx wire SettingsSyncFeature for session lifetime
src/app/features/settings/general/General.tsx SettingsSyncSection UI
src/app/utils/settingsSync.test.ts 26 tests for pure utility functions
src/app/hooks/useSettingsSync.test.tsx 13 tests for hook behaviour (mount load, debounce, echo-token, remote updates)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

AI assistance level

  • None — No AI tools were used
  • Research only — AI used for research, brainstorming, or understanding existing code; no generated code included
  • AI-assisted — AI suggested code or logic that I reviewed, tested, and understand fully; I can explain every change
  • Primarily AI-generated — The majority of code was AI-generated; I have thoroughly reviewed it, verified correctness, and made it my own

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

- Add SableSettings account data event type (moe.sable.app.settings)
- Add settingsSyncEnabled setting (default off, device-local)
- serializeForSync/deserializeFromSync utilities with versioned schema
- Echo-token loop prevention: own uploads don't re-apply on echo
- Debounced (2 s) upload on settings change
- JSON export (browser download) and import (file picker)
- SettingsSyncSection in General settings with sync toggle, status, and export/import buttons
- 39 new tests covering utilities and hook behaviour
@github-actions
Copy link
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

Status Preview URL Commit Alias Updated (UTC)
✅ Deployment successful! https://pr-409-sable.raspy-dream-bb1d.workers.dev 1e07701 pr-409 Fri, 20 Mar 2026 03:26:32 GMT

@Just-Insane
Copy link
Contributor Author

Tests well, can change settings and see them syncing to account data, uploading and downloading the files also works and overwrites settings as expected.

An example settings export file is below:
sable-settings-1773977439924.json

@Just-Insane Just-Insane marked this pull request as ready for review March 20, 2026 03:39
@Just-Insane Just-Insane requested review from 7w1 and hazre as code owners March 20, 2026 03:39
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.

Sync app settings across devices

1 participant