Files
AFFiNE-Mirror/packages/frontend/apps/android/src/app.tsx
T

132 lines
4.0 KiB
TypeScript

import { AffineContext } from '@affine/core/components/context';
import { AppFallback } from '@affine/core/mobile/components/app-fallback';
import { configureMobileModules } from '@affine/core/mobile/modules';
import { router } from '@affine/core/mobile/router';
import { configureCommonModules } from '@affine/core/modules';
import { AuthService, DefaultServerService } from '@affine/core/modules/cloud';
import { I18nProvider } from '@affine/core/modules/i18n';
import { LifecycleService } from '@affine/core/modules/lifecycle';
import {
configureLocalStorageStateStorageImpls,
NbstoreProvider,
} from '@affine/core/modules/storage';
import { PopupWindowProvider } from '@affine/core/modules/url';
import { ClientSchemeProvider } from '@affine/core/modules/url/providers/client-schema';
import { configureBrowserWorkbenchModule } from '@affine/core/modules/workbench';
import { configureBrowserWorkspaceFlavours } from '@affine/core/modules/workspace-engine';
import { StoreManagerClient } from '@affine/nbstore/worker/client';
import { App as CapacitorApp } from '@capacitor/app';
import { InAppBrowser } from '@capgo/inappbrowser';
import { Framework, FrameworkRoot, getCurrentStore } from '@toeverything/infra';
import { OpClient } from '@toeverything/infra/op';
import { Suspense } from 'react';
import { RouterProvider } from 'react-router-dom';
const storeManagerClient = new StoreManagerClient(
new OpClient(
new Worker(
new URL(/* webpackChunkName: "nbstore" */ './nbstore.ts', import.meta.url)
)
)
);
window.addEventListener('beforeunload', () => {
storeManagerClient.dispose();
});
const future = {
v7_startTransition: true,
} as const;
const framework = new Framework();
configureCommonModules(framework);
configureBrowserWorkbenchModule(framework);
configureLocalStorageStateStorageImpls(framework);
configureBrowserWorkspaceFlavours(framework);
configureMobileModules(framework);
framework.impl(NbstoreProvider, {
openStore(key, options) {
const { store, dispose } = storeManagerClient.open(key, options);
return {
store,
dispose: () => {
dispose();
},
};
},
});
const frameworkProvider = framework.provider();
framework.impl(PopupWindowProvider, {
open: (url: string) => {
InAppBrowser.open({
url: url,
}).catch(console.error);
},
});
framework.impl(ClientSchemeProvider, {
getClientScheme() {
return 'affine';
},
});
// setup application lifecycle events, and emit application start event
window.addEventListener('focus', () => {
frameworkProvider.get(LifecycleService).applicationFocus();
});
frameworkProvider.get(LifecycleService).applicationStart();
CapacitorApp.addListener('appUrlOpen', ({ url }) => {
// try to close browser if it's open
InAppBrowser.close().catch(e => console.error('Failed to close browser', e));
const urlObj = new URL(url);
if (urlObj.hostname === 'authentication') {
const method = urlObj.searchParams.get('method');
const payload = JSON.parse(urlObj.searchParams.get('payload') ?? 'false');
if (
!method ||
(method !== 'magic-link' && method !== 'oauth') ||
!payload
) {
console.error('Invalid authentication url', url);
return;
}
const authService = frameworkProvider
.get(DefaultServerService)
.server.scope.get(AuthService);
if (method === 'oauth') {
authService
.signInOauth(payload.code, payload.state, payload.provider)
.catch(console.error);
} else if (method === 'magic-link') {
authService
.signInMagicLink(payload.email, payload.token)
.catch(console.error);
}
}
}).catch(e => {
console.error(e);
});
export function App() {
return (
<Suspense>
<FrameworkRoot framework={frameworkProvider}>
<I18nProvider>
<AffineContext store={getCurrentStore()}>
<RouterProvider
fallbackElement={<AppFallback />}
router={router}
future={future}
/>
</AffineContext>
</I18nProvider>
</FrameworkRoot>
</Suspense>
);
}