mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-30 00:29:46 +08:00
@@ -7,6 +7,11 @@ import { router } from '@affine/core/desktop/router';
|
||||
import { configureCommonModules } from '@affine/core/modules';
|
||||
import { configureAppTabsHeaderModule } from '@affine/core/modules/app-tabs-header';
|
||||
import { ValidatorProvider } from '@affine/core/modules/cloud';
|
||||
import {
|
||||
configureDesktopApiModule,
|
||||
DesktopApiService,
|
||||
} from '@affine/core/modules/desktop-api';
|
||||
import { configureFindInPageModule } from '@affine/core/modules/find-in-page';
|
||||
import { I18nProvider } from '@affine/core/modules/i18n';
|
||||
import { configureElectronStateStorageImpls } from '@affine/core/modules/storage';
|
||||
import { CustomThemeModifier } from '@affine/core/modules/theme-editor';
|
||||
@@ -21,7 +26,6 @@ import {
|
||||
configureSqliteWorkspaceEngineStorageProvider,
|
||||
} from '@affine/core/modules/workspace-engine';
|
||||
import createEmotionCache from '@affine/core/utils/create-emotion-cache';
|
||||
import { apis, appInfo } from '@affine/electron-api';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import {
|
||||
Framework,
|
||||
@@ -32,6 +36,8 @@ import {
|
||||
import { Suspense } from 'react';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
|
||||
import { DesktopThemeSync } from './theme-sync';
|
||||
|
||||
const desktopWhiteList = [
|
||||
'/open-app/signin-redirect',
|
||||
'/open-app/url',
|
||||
@@ -64,26 +70,38 @@ configureSqliteWorkspaceEngineStorageProvider(framework);
|
||||
configureSqliteUserspaceStorageProvider(framework);
|
||||
configureDesktopWorkbenchModule(framework);
|
||||
configureAppTabsHeaderModule(framework);
|
||||
framework.impl(PopupWindowProvider, {
|
||||
open: (url: string) => {
|
||||
apis?.ui.openExternal(url).catch(e => {
|
||||
console.error('Failed to open external URL', e);
|
||||
});
|
||||
},
|
||||
configureFindInPageModule(framework);
|
||||
configureDesktopApiModule(framework);
|
||||
|
||||
framework.impl(PopupWindowProvider, p => {
|
||||
const apis = p.get(DesktopApiService).api;
|
||||
return {
|
||||
open: (url: string) => {
|
||||
apis.handler.ui.openExternal(url).catch(e => {
|
||||
console.error('Failed to open external URL', e);
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
framework.impl(ClientSchemeProvider, {
|
||||
getClientScheme() {
|
||||
return appInfo?.scheme;
|
||||
},
|
||||
framework.impl(ClientSchemeProvider, p => {
|
||||
const appInfo = p.get(DesktopApiService).appInfo;
|
||||
return {
|
||||
getClientScheme() {
|
||||
return appInfo?.scheme;
|
||||
},
|
||||
};
|
||||
});
|
||||
framework.impl(ValidatorProvider, {
|
||||
async validate(_challenge, resource) {
|
||||
const token = await apis?.ui?.getChallengeResponse(resource);
|
||||
if (!token) {
|
||||
throw new Error('Challenge failed');
|
||||
}
|
||||
return token;
|
||||
},
|
||||
framework.impl(ValidatorProvider, p => {
|
||||
const apis = p.get(DesktopApiService).api;
|
||||
return {
|
||||
async validate(_challenge, resource) {
|
||||
const token = await apis.handler.ui.getChallengeResponse(resource);
|
||||
if (!token) {
|
||||
throw new Error('Challenge failed');
|
||||
}
|
||||
return token;
|
||||
},
|
||||
};
|
||||
});
|
||||
const frameworkProvider = framework.provider();
|
||||
|
||||
@@ -100,6 +118,7 @@ export function App() {
|
||||
<CacheProvider value={cache}>
|
||||
<I18nProvider>
|
||||
<AffineContext store={getCurrentStore()}>
|
||||
<DesktopThemeSync />
|
||||
<Telemetry />
|
||||
<CustomThemeModifier />
|
||||
<GlobalLoading />
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
import './setup';
|
||||
|
||||
import { appConfigProxy } from '@affine/core/components/hooks/use-app-config-storage';
|
||||
import { apis, appInfo, events } from '@affine/electron-api';
|
||||
import {
|
||||
init,
|
||||
reactRouterV6BrowserTracingIntegration,
|
||||
setTags,
|
||||
} from '@sentry/react';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { StrictMode, useEffect } from 'react';
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import {
|
||||
createRoutesFromChildren,
|
||||
matchRoutes,
|
||||
useLocation,
|
||||
useNavigationType,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import { App } from './app';
|
||||
|
||||
@@ -26,82 +13,6 @@ function main() {
|
||||
.getSync()
|
||||
.catch(() => console.error('failed to load app config'));
|
||||
|
||||
// skip bootstrap setup for desktop onboarding
|
||||
if (
|
||||
!(
|
||||
appInfo?.windowName === 'onboarding' ||
|
||||
appInfo?.windowName === 'theme-editor'
|
||||
)
|
||||
) {
|
||||
if (BUILD_CONFIG.debug || window.SENTRY_RELEASE) {
|
||||
// https://docs.sentry.io/platforms/javascript/guides/electron/
|
||||
init({
|
||||
dsn: process.env.SENTRY_DSN,
|
||||
environment: process.env.BUILD_TYPE ?? 'development',
|
||||
integrations: [
|
||||
reactRouterV6BrowserTracingIntegration({
|
||||
useEffect,
|
||||
useLocation,
|
||||
useNavigationType,
|
||||
createRoutesFromChildren,
|
||||
matchRoutes,
|
||||
}),
|
||||
],
|
||||
});
|
||||
setTags({
|
||||
appVersion: BUILD_CONFIG.appVersion,
|
||||
editorVersion: BUILD_CONFIG.editorVersion,
|
||||
});
|
||||
|
||||
apis?.ui.handleNetworkChange(navigator.onLine);
|
||||
window.addEventListener('offline', () => {
|
||||
apis?.ui.handleNetworkChange(false);
|
||||
});
|
||||
window.addEventListener('online', () => {
|
||||
apis?.ui.handleNetworkChange(true);
|
||||
});
|
||||
}
|
||||
|
||||
const handleMaximized = (maximized: boolean | undefined) => {
|
||||
document.documentElement.dataset.maximized = String(maximized);
|
||||
};
|
||||
const handleFullscreen = (fullscreen: boolean | undefined) => {
|
||||
document.documentElement.dataset.fullscreen = String(fullscreen);
|
||||
};
|
||||
apis?.ui.isMaximized().then(handleMaximized).catch(console.error);
|
||||
apis?.ui.isFullScreen().then(handleFullscreen).catch(console.error);
|
||||
events?.ui.onMaximized(handleMaximized);
|
||||
events?.ui.onFullScreen(handleFullscreen);
|
||||
|
||||
const tabId = appInfo?.viewId;
|
||||
const handleActiveTabChange = (active: boolean) => {
|
||||
document.documentElement.dataset.active = String(active);
|
||||
};
|
||||
|
||||
if (tabId) {
|
||||
apis?.ui
|
||||
.isActiveTab()
|
||||
.then(active => {
|
||||
handleActiveTabChange(active);
|
||||
events?.ui.onActiveTabChanged(id => {
|
||||
handleActiveTabChange(id === tabId);
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
||||
const handleResize = debounce(() => {
|
||||
apis?.ui.handleWindowResize().catch(console.error);
|
||||
}, 50);
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener('dragstart', () => {
|
||||
document.documentElement.dataset.dragging = 'true';
|
||||
});
|
||||
window.addEventListener('dragend', () => {
|
||||
document.documentElement.dataset.dragging = 'false';
|
||||
});
|
||||
}
|
||||
|
||||
mountApp();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
AppTabsHeader,
|
||||
configureAppTabsHeaderModule,
|
||||
} from '@affine/core/modules/app-tabs-header';
|
||||
import { configureDesktopApiModule } from '@affine/core/modules/desktop-api';
|
||||
import { configureI18nModule, I18nProvider } from '@affine/core/modules/i18n';
|
||||
import { configureElectronStateStorageImpls } from '@affine/core/modules/storage';
|
||||
import { SplitViewFallback } from '@affine/core/modules/workbench/view/split-view/split-view';
|
||||
@@ -23,6 +24,7 @@ configureElectronStateStorageImpls(framework);
|
||||
configureAppTabsHeaderModule(framework);
|
||||
configureAppSidebarModule(framework);
|
||||
configureI18nModule(framework);
|
||||
configureDesktopApiModule(framework);
|
||||
const frameworkProvider = framework.provider();
|
||||
|
||||
export function App() {
|
||||
|
||||
@@ -1,28 +1,16 @@
|
||||
import './setup';
|
||||
|
||||
import { apis, events } from '@affine/electron-api';
|
||||
import { events } from '@affine/electron-api';
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
import { App } from './app';
|
||||
|
||||
async function main() {
|
||||
const handleMaximized = (maximized: boolean | undefined) => {
|
||||
document.documentElement.dataset.maximized = String(maximized);
|
||||
};
|
||||
const handleFullscreen = (fullscreen: boolean | undefined) => {
|
||||
document.documentElement.dataset.fullscreen = String(fullscreen);
|
||||
};
|
||||
const handleActive = (active: boolean | undefined) => {
|
||||
document.documentElement.dataset.active = String(active);
|
||||
};
|
||||
|
||||
apis?.ui.isMaximized().then(handleMaximized).catch(console.error);
|
||||
apis?.ui.isFullScreen().then(handleFullscreen).catch(console.error);
|
||||
events?.ui.onMaximized(handleMaximized);
|
||||
events?.ui.onFullScreen(handleFullscreen);
|
||||
events?.ui.onTabShellViewActiveChange(handleActive);
|
||||
|
||||
mountApp();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DesktopApiService } from '@affine/core/modules/desktop-api/service';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { useRef } from 'react';
|
||||
|
||||
export const DesktopThemeSync = () => {
|
||||
const { theme } = useTheme();
|
||||
const lastThemeRef = useRef(theme);
|
||||
const onceRef = useRef(false);
|
||||
|
||||
const handler = useService(DesktopApiService).api.handler;
|
||||
|
||||
if (lastThemeRef.current !== theme || !onceRef.current) {
|
||||
if (BUILD_CONFIG.isElectron && theme) {
|
||||
handler.ui
|
||||
.handleThemeChange(theme as 'dark' | 'light' | 'system')
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
lastThemeRef.current = theme;
|
||||
onceRef.current = true;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Reference in New Issue
Block a user