From b742783577eb7fbe593a55d1f406b0b0fd447ec3 Mon Sep 17 00:00:00 2001 From: David Sheldrick Date: Thu, 25 May 2023 16:36:29 +0100 Subject: [PATCH] send user prefs data in broadcast msg (#1466) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #1464 The user preference changes were not broadcasting correctly in firefox because it has a race condition wherein the broadcast message was being received by a peer tab before the localStorage data was ready to be consumed in that tab. ### Change Type - [x] `patch` — Bug Fix - [ ] `minor` — New Feature - [ ] `major` — Breaking Change - [ ] `dependencies` — Dependency Update (publishes a `patch` release, for devDependencies use `internal`) - [ ] `documentation` — Changes to the documentation only (will not publish a new version) - [ ] `tests` — Changes to any testing-related code only (will not publish a new version) - [ ] `internal` — Any other changes that don't affect the published package (will not publish a new version) ### Test Plan 1. in firefox, have two tabs open in the same user context. 2. toggle dark mode. 3. the change should propagate to the other tab --- .../src/lib/config/TLUserPreferences.ts | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/packages/editor/src/lib/config/TLUserPreferences.ts b/packages/editor/src/lib/config/TLUserPreferences.ts index c6f0f34de..629330733 100644 --- a/packages/editor/src/lib/config/TLUserPreferences.ts +++ b/packages/editor/src/lib/config/TLUserPreferences.ts @@ -27,18 +27,16 @@ interface UserDataSnapshot { interface UserChangeBroadcastMessage { type: typeof broadcastEventKey origin: string + data: UserDataSnapshot } -const userTypeValidator: T.Validator = T.model( - 'user', - T.object({ - id: T.string, - name: T.string, - locale: T.string, - color: T.string, - isDarkMode: T.boolean, - }) -) +const userTypeValidator: T.Validator = T.object({ + id: T.string, + name: T.string, + locale: T.string, + color: T.string, + isDarkMode: T.boolean, +}) const userTypeMigrations = defineMigrations({}) @@ -72,18 +70,12 @@ function getFreshUserPreferences(): TLUserPreferences { isDarkMode: false, } } - -function loadUserPreferences(): TLUserPreferences { - const userData = - typeof window === 'undefined' - ? null - : ((JSON.parse(window?.localStorage?.getItem(USER_DATA_KEY) || 'null') ?? - null) as null | UserDataSnapshot) - if (userData === null) { +function migrateUserPreferences(userData: unknown) { + if (userData === null || typeof userData !== 'object') { return getFreshUserPreferences() } - if (!('version' in userData) || !('user' in userData)) { + if (!('version' in userData) || !('user' in userData) || typeof userData.version !== 'number') { return getFreshUserPreferences() } @@ -107,6 +99,16 @@ function loadUserPreferences(): TLUserPreferences { return migrationResult.value } +function loadUserPreferences(): TLUserPreferences { + const userData = + typeof window === 'undefined' + ? null + : ((JSON.parse(window?.localStorage?.getItem(USER_DATA_KEY) || 'null') ?? + null) as null | UserDataSnapshot) + + return migrateUserPreferences(userData) +} + const globalUserPreferences = atom('globalUserData', loadUserPreferences()) function storeUserPreferences() { @@ -138,7 +140,7 @@ const channel = channel?.addEventListener('message', (e) => { const data = e.data as undefined | UserChangeBroadcastMessage if (data?.type === broadcastEventKey && data?.origin !== broadcastOrigin) { - globalUserPreferences.set(loadUserPreferences()) + globalUserPreferences.set(migrateUserPreferences(data.data)) } }) @@ -149,6 +151,10 @@ function broadcastUserPreferencesChange() { channel?.postMessage({ type: broadcastEventKey, origin: broadcastOrigin, + data: { + user: globalUserPreferences.value, + version: userTypeMigrations.currentVersion, + }, } satisfies UserChangeBroadcastMessage) }