refactor(electron): nestjsfy

This commit is contained in:
Peng Xiao
2025-04-24 14:54:30 +08:00
parent 899ffd1ad3
commit 68ab87f5c5
178 changed files with 7139 additions and 5617 deletions
@@ -5,6 +5,6 @@ import type { FrameworkProvider } from '@toeverything/infra';
export function patchForClipboardInElectron(framework: FrameworkProvider) {
const desktopApi = framework.get(DesktopApiService);
return NativeClipboardExtension({
copyAsPNG: desktopApi.handler.clipboard.copyAsPNG,
copyAsPNG: desktopApi.handler.ui.writeImageToClipboard,
});
}
@@ -1,87 +0,0 @@
import { apis } from '@affine/electron-api';
import type { AppConfigSchema } from '@toeverything/infra';
import { AppConfigStorage, defaultAppConfig } from '@toeverything/infra';
import type { Dispatch } from 'react';
import { useEffect, useMemo, useState } from 'react';
/**
* Helper class to get/set app config from main process
*/
class AppConfigProxy {
value: AppConfigSchema = defaultAppConfig;
async getSync(): Promise<AppConfigSchema> {
if (!apis) {
throw new Error('electron apis is not found');
}
return (this.value = await apis.configStorage.get());
}
async setSync(): Promise<void> {
if (!apis) {
throw new Error('electron apis is not found');
}
await apis.configStorage.set(this.value);
}
get(): AppConfigSchema {
return this.value;
}
set(data: AppConfigSchema) {
this.value = data;
this.setSync().catch(console.error);
}
}
export const appConfigProxy = new AppConfigProxy();
const storage = BUILD_CONFIG.isElectron
? new AppConfigStorage({
config: defaultAppConfig,
get: () => appConfigProxy.get(),
set: v => appConfigProxy.set(v),
})
: new AppConfigStorage({
config: defaultAppConfig,
get: () => JSON.parse(localStorage.getItem('app_config') ?? 'null'),
set: config => localStorage.setItem('app_config', JSON.stringify(config)),
});
export const appConfigStorage = storage;
export function useAppConfigStorage(): [
AppConfigSchema,
Dispatch<AppConfigSchema>,
];
export function useAppConfigStorage(
key: keyof AppConfigSchema
): [AppConfigSchema[typeof key], Dispatch<AppConfigSchema[typeof key]>];
/**
* Get reactive app config
* @param key
* @returns
*/
export function useAppConfigStorage(key?: keyof AppConfigSchema) {
const [_config, _setConfig] = useState(storage.get());
useEffect(() => {
storage.set(_config);
}, [_config]);
const value = useMemo(() => (key ? _config[key] : _config), [_config, key]);
const setValue = useMemo(() => {
if (key) {
return (value: AppConfigSchema[typeof key]) => {
_setConfig(cfg => ({ ...cfg, [key]: value }));
};
} else {
return (config: AppConfigSchema) => {
_setConfig(config);
};
}
}, [_setConfig, key]);
return [value, setValue];
}
@@ -135,7 +135,7 @@ export const useAppUpdater = () => {
setCheckingForUpdates(true);
try {
const updateInfo = await apis?.updater.checkForUpdates();
return updateInfo?.version ?? false;
return updateInfo?.isUpdateAvailable ?? false;
} catch (err) {
console.error('Error checking for updates:', err);
return null;
@@ -14,7 +14,7 @@ import {
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { DesktopApiService } from '@affine/core/modules/desktop-api';
import { MeetingSettingsService } from '@affine/core/modules/media/services/meeting-settings';
import type { MeetingSettingsSchema } from '@affine/electron/main/shared-state-schema';
import type { MeetingSettingsSchema } from '@affine/electron-api';
import { Trans, useI18n } from '@affine/i18n';
import {
ArrowRightSmallIcon,
@@ -39,7 +39,7 @@ export const PageNotFound = ({
);
useEffect(() => {
desktopApi?.handler.ui.pingAppLayoutReady().catch(console.error);
desktopApi?.handler.ui.pingAppLayoutReady(true).catch(console.error);
}, [desktopApi]);
// not using workbench location or router location deliberately
@@ -124,7 +124,7 @@ export const Component = ({
const desktopApi = useServiceOptional(DesktopApiService);
useEffect(() => {
desktopApi?.handler.ui.pingAppLayoutReady().catch(console.error);
desktopApi?.handler.ui.pingAppLayoutReady(true).catch(console.error);
}, [desktopApi]);
useEffect(() => {
@@ -1,33 +1,11 @@
import { DesktopApiService } from '@affine/core/modules/desktop-api';
import { useServiceOptional } from '@toeverything/infra';
import { useCallback } from 'react';
import { redirect } from 'react-router-dom';
import { Onboarding } from '../../../components/affine/onboarding/onboarding';
import { appConfigStorage } from '../../../components/hooks/use-app-config-storage';
/**
* /onboarding page
*
* only for electron
*/
export const loader = () => {
if (!BUILD_CONFIG.isElectron && !appConfigStorage.get('onBoarding')) {
// onboarding is off, redirect to index
return redirect('/');
}
return null;
};
export const Component = () => {
const desktopApi = useServiceOptional(DesktopApiService);
const openApp = useCallback(() => {
desktopApi?.handler.ui.handleOpenMainApp().catch(err => {
console.log('failed to open main app', err);
});
}, [desktopApi]);
// todo: add back open main app when needed
}, []);
return <Onboarding onOpenApp={openApp} />;
};
@@ -405,7 +405,7 @@ export const AppTabsHeader = ({
useEffect(() => {
if (mode === 'app') {
desktopApi.handler.ui.pingAppLayoutReady().catch(console.error);
desktopApi.handler.ui.pingAppLayoutReady(true).catch(console.error);
}
}, [mode, desktopApi]);
@@ -12,8 +12,8 @@ export class ElectronApiImpl extends Service implements DesktopApiProvider {
throw new Error('Failed to initialize DesktopApiImpl');
}
}
handler = apis;
events = events;
sharedStorage = sharedStorage;
appInfo = appInfo!;
handler: typeof apis = apis;
events: typeof events = events;
sharedStorage: typeof sharedStorage = sharedStorage;
appInfo: NonNullable<typeof appInfo> = appInfo!;
}
@@ -1,7 +1,7 @@
import type {
SpellCheckStateKey,
SpellCheckStateSchema,
} from '@affine/electron/main/shared-state-schema';
} from '@affine/electron-api';
import type { Language } from '@affine/i18n';
import { LiveData, Service } from '@toeverything/infra';
@@ -1,7 +1,4 @@
import type {
MenubarStateKey,
MenubarStateSchema,
} from '@affine/electron/main/shared-state-schema';
import type { MenubarStateKey, MenubarStateSchema } from '@affine/electron-api';
import { LiveData, Service } from '@toeverything/infra';
import type { GlobalStateService } from '../../storage';
@@ -1,7 +1,7 @@
import type {
MeetingSettingsKey,
MeetingSettingsSchema,
} from '@affine/electron/main/shared-state-schema';
} from '@affine/electron-api';
import { LiveData, Service } from '@toeverything/infra';
import { defaults } from 'lodash-es';
@@ -126,7 +126,7 @@ export class MeetingSettingsService extends Service {
// the following methods are only available on MacOS right?
async showRecordingPermissionSetting(type: 'screen' | 'microphone') {
return this.desktopApiService?.handler.recording.showRecordingPermissionSetting(
type
{ type }
);
}