fix(electron): sync settings from localStorage -> atom -> electron (#5020)

- moved `appSettingAtom` to infra since we now have different packages that depends on it. There is no better place to fit in for now
- use atomEffect to sync setting changes to updater related configs to Electron side
- refactored how Electron reacts to updater config changes.
This commit is contained in:
Peng Xiao
2023-12-08 03:20:02 +00:00
parent 453d4db713
commit fcd43033fe
30 changed files with 441 additions and 343 deletions

View File

@@ -0,0 +1,8 @@
import { atom } from 'jotai';
export const loadedPluginNameAtom = atom<string[]>([]);
export * from './layout';
export * from './root-store';
export * from './settings';
export * from './workspace';

View File

@@ -1,34 +1,5 @@
import type { ExpectedLayout } from '@affine/sdk/entry';
import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store';
import { atom, createStore } from 'jotai/vanilla';
import { getBlockSuiteWorkspaceAtom } from './__internal__/workspace';
// global store
let rootStore = createStore();
export function getCurrentStore() {
return rootStore;
}
/**
* @internal do not use this function unless you know what you are doing
*/
export function _setCurrentStore(store: ReturnType<typeof createStore>) {
rootStore = store;
}
export const loadedPluginNameAtom = atom<string[]>([]);
export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceAtom = atom<Promise<Workspace>>(async get => {
const workspaceId = get(currentWorkspaceIdAtom);
assertExists(workspaceId);
const [currentWorkspaceAtom] = getBlockSuiteWorkspaceAtom(workspaceId);
return get(currentWorkspaceAtom);
});
import { atom } from 'jotai';
const contentLayoutBaseAtom = atom<ExpectedLayout>('editor');

View File

@@ -0,0 +1,15 @@
import { createStore } from 'jotai';
// global store
let rootStore = createStore();
export function getCurrentStore() {
return rootStore;
}
/**
* @internal do not use this function unless you know what you are doing
*/
export function _setCurrentStore(store: ReturnType<typeof createStore>) {
rootStore = store;
}

View File

@@ -0,0 +1,101 @@
import { setupGlobal } from '@affine/env/global';
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
import { atomEffect } from 'jotai-effect';
setupGlobal();
export type DateFormats =
| 'MM/dd/YYYY'
| 'dd/MM/YYYY'
| 'YYYY-MM-dd'
| 'YYYY.MM.dd'
| 'YYYY/MM/dd'
| 'dd-MMM-YYYY'
| 'dd MMMM YYYY';
export type AppSetting = {
clientBorder: boolean;
fullWidthLayout: boolean;
windowFrameStyle: 'frameless' | 'NativeTitleBar';
fontStyle: FontFamily;
dateFormat: DateFormats;
startWeekOnMonday: boolean;
enableBlurBackground: boolean;
enableNoisyBackground: boolean;
autoCheckUpdate: boolean;
autoDownloadUpdate: boolean;
};
export const windowFrameStyleOptions: AppSetting['windowFrameStyle'][] = [
'frameless',
'NativeTitleBar',
];
export const dateFormatOptions: DateFormats[] = [
'MM/dd/YYYY',
'dd/MM/YYYY',
'YYYY-MM-dd',
'YYYY.MM.dd',
'YYYY/MM/dd',
'dd-MMM-YYYY',
'dd MMMM YYYY',
];
export type FontFamily = 'Sans' | 'Serif' | 'Mono';
export const fontStyleOptions = [
{ key: 'Sans', value: 'var(--affine-font-sans-family)' },
{ key: 'Serif', value: 'var(--affine-font-serif-family)' },
{ key: 'Mono', value: 'var(--affine-font-mono-family)' },
] satisfies {
key: FontFamily;
value: string;
}[];
const appSettingBaseAtom = atomWithStorage<AppSetting>('affine-settings', {
clientBorder: environment.isDesktop && !environment.isWindows,
fullWidthLayout: false,
windowFrameStyle: 'frameless',
fontStyle: 'Sans',
dateFormat: dateFormatOptions[0],
startWeekOnMonday: false,
enableBlurBackground: true,
enableNoisyBackground: true,
autoCheckUpdate: true,
autoDownloadUpdate: true,
});
type SetStateAction<Value> = Value | ((prev: Value) => Value);
const appSettingEffect = atomEffect(get => {
const settings = get(appSettingBaseAtom);
// some values in settings should be synced into electron side
if (environment.isDesktop) {
console.log('set config', settings);
window.apis?.updater
.setConfig({
autoCheckUpdate: settings.autoCheckUpdate,
autoDownloadUpdate: settings.autoDownloadUpdate,
})
.catch(err => {
console.error(err);
});
}
});
export const appSettingAtom = atom<
AppSetting,
[SetStateAction<Partial<AppSetting>>],
void
>(
get => {
get(appSettingEffect);
return get(appSettingBaseAtom);
},
(_get, set, apply) => {
set(appSettingBaseAtom, prev => {
const next = typeof apply === 'function' ? apply(prev) : apply;
return { ...prev, ...next };
});
}
);

View File

@@ -0,0 +1,14 @@
import { assertExists } from '@blocksuite/global/utils';
import type { Workspace } from '@blocksuite/store';
import { atom } from 'jotai';
import { getBlockSuiteWorkspaceAtom } from '../__internal__/workspace';
export const currentWorkspaceIdAtom = atom<string | null>(null);
export const currentPageIdAtom = atom<string | null>(null);
export const currentWorkspaceAtom = atom<Promise<Workspace>>(async get => {
const workspaceId = get(currentWorkspaceIdAtom);
assertExists(workspaceId);
const [currentWorkspaceAtom] = getBlockSuiteWorkspaceAtom(workspaceId);
return get(currentWorkspaceAtom);
});

View File

@@ -201,7 +201,7 @@ export type UpdaterHandlers = {
downloadUpdate: () => Promise<void>;
getConfig: () => Promise<UpdaterConfig>;
setConfig: (newConfig: Partial<UpdaterConfig>) => Promise<void>;
checkForUpdatesAndNotify: () => Promise<{ version: string } | null>;
checkForUpdates: () => Promise<{ version: string } | null>;
};
export type WorkspaceHandlers = {