Realtime sync UI preferences between tabs
This commit is contained in:
@@ -108,22 +108,21 @@ export default class AuthStore extends Store<Team> {
|
||||
// signin/signout events in other tabs and follow suite.
|
||||
window.addEventListener("storage", (event) => {
|
||||
if (event.key === AUTH_STORE && event.newValue) {
|
||||
const data: PersistedData | null | undefined = JSON.parse(
|
||||
event.newValue
|
||||
);
|
||||
const newData: PersistedData | null = JSON.parse(event.newValue);
|
||||
|
||||
// data may be null if key is deleted in localStorage
|
||||
if (!data) {
|
||||
if (!newData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're not signed in then hydrate from the received data, otherwise if
|
||||
// we are signed in and the received data contains no user then sign out
|
||||
if (this.authenticated) {
|
||||
if (data.user === null) {
|
||||
if (newData.user === null) {
|
||||
void this.logout(false, false);
|
||||
}
|
||||
} else {
|
||||
this.rehydrate(data);
|
||||
this.rehydrate(newData);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -20,6 +20,16 @@ export enum SystemTheme {
|
||||
Dark = "dark",
|
||||
}
|
||||
|
||||
type PersistedData = {
|
||||
languagePromptDismissed: boolean | undefined;
|
||||
theme: Theme;
|
||||
sidebarCollapsed: boolean;
|
||||
sidebarWidth: number;
|
||||
sidebarRightWidth: number;
|
||||
tocVisible: boolean;
|
||||
commentsExpanded: string[];
|
||||
};
|
||||
|
||||
class UiStore {
|
||||
// has the user seen the prompt to change the UI language and actioned it
|
||||
@observable
|
||||
@@ -74,7 +84,15 @@ class UiStore {
|
||||
|
||||
constructor() {
|
||||
// Rehydrate
|
||||
const data: Partial<UiStore> = Storage.get(UI_STORE) || {};
|
||||
const data: PersistedData = Storage.get(UI_STORE) || {};
|
||||
this.languagePromptDismissed = data.languagePromptDismissed;
|
||||
this.sidebarCollapsed = !!data.sidebarCollapsed;
|
||||
this.sidebarWidth = data.sidebarWidth || defaultTheme.sidebarWidth;
|
||||
this.sidebarRightWidth =
|
||||
data.sidebarRightWidth || defaultTheme.sidebarRightWidth;
|
||||
this.tocVisible = !!data.tocVisible;
|
||||
this.commentsExpanded = data.commentsExpanded || [];
|
||||
this.theme = data.theme || Theme.System;
|
||||
|
||||
// system theme listeners
|
||||
if (window.matchMedia) {
|
||||
@@ -93,15 +111,22 @@ class UiStore {
|
||||
}
|
||||
}
|
||||
|
||||
// persisted keys
|
||||
this.languagePromptDismissed = data.languagePromptDismissed;
|
||||
this.sidebarCollapsed = !!data.sidebarCollapsed;
|
||||
this.sidebarWidth = data.sidebarWidth || defaultTheme.sidebarWidth;
|
||||
this.sidebarRightWidth =
|
||||
data.sidebarRightWidth || defaultTheme.sidebarRightWidth;
|
||||
this.tocVisible = !!data.tocVisible;
|
||||
this.commentsExpanded = data.commentsExpanded || [];
|
||||
this.theme = data.theme || Theme.System;
|
||||
window.addEventListener("storage", (event) => {
|
||||
if (event.key === UI_STORE && event.newValue) {
|
||||
const newData: PersistedData | null = JSON.parse(event.newValue);
|
||||
|
||||
// data may be null if key is deleted in localStorage
|
||||
if (!newData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: we do not sync all properties here, sidebar widths cause fighting between windows
|
||||
this.theme = newData.theme;
|
||||
this.languagePromptDismissed = newData.languagePromptDismissed;
|
||||
this.sidebarCollapsed = !!newData.sidebarCollapsed;
|
||||
this.tocVisible = !!newData.tocVisible;
|
||||
}
|
||||
});
|
||||
|
||||
autorun(() => {
|
||||
Storage.set(UI_STORE, this.asJson);
|
||||
@@ -265,7 +290,7 @@ class UiStore {
|
||||
}
|
||||
|
||||
@computed
|
||||
get asJson() {
|
||||
get asJson(): PersistedData {
|
||||
return {
|
||||
tocVisible: this.tocVisible,
|
||||
sidebarCollapsed: this.sidebarCollapsed,
|
||||
|
||||
Reference in New Issue
Block a user