mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-23 13:29:02 +08:00
feat(android): integrate web api & native AI chat button (#10239)
This commit is contained in:
@@ -4,7 +4,14 @@ import { configureMobileModules } from '@affine/core/mobile/modules';
|
||||
import { VirtualKeyboardProvider } from '@affine/core/mobile/modules/virtual-keyboard';
|
||||
import { router } from '@affine/core/mobile/router';
|
||||
import { configureCommonModules } from '@affine/core/modules';
|
||||
import { AuthService, DefaultServerService } from '@affine/core/modules/cloud';
|
||||
import { AIButtonProvider } from '@affine/core/modules/ai-button';
|
||||
import {
|
||||
AuthService,
|
||||
DefaultServerService,
|
||||
ServersService,
|
||||
} from '@affine/core/modules/cloud';
|
||||
import { DocsService } from '@affine/core/modules/doc';
|
||||
import { GlobalContextService } from '@affine/core/modules/global-context';
|
||||
import { I18nProvider } from '@affine/core/modules/i18n';
|
||||
import { LifecycleService } from '@affine/core/modules/lifecycle';
|
||||
import {
|
||||
@@ -14,8 +21,20 @@ import {
|
||||
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 { WorkspacesService } from '@affine/core/modules/workspace';
|
||||
import { configureBrowserWorkspaceFlavours } from '@affine/core/modules/workspace-engine';
|
||||
import { I18n } from '@affine/i18n';
|
||||
import { StoreManagerClient } from '@affine/nbstore/worker/client';
|
||||
import {
|
||||
defaultBlockMarkdownAdapterMatchers,
|
||||
docLinkBaseURLMiddleware,
|
||||
InlineDeltaToMarkdownAdapterExtensions,
|
||||
MarkdownAdapter,
|
||||
MarkdownInlineToDeltaAdapterExtensions,
|
||||
titleMiddleware,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { Container } from '@blocksuite/affine/global/di';
|
||||
import { Transformer } from '@blocksuite/affine/store';
|
||||
import { App as CapacitorApp } from '@capacitor/app';
|
||||
import { Keyboard } from '@capacitor/keyboard';
|
||||
import { StatusBar, Style } from '@capacitor/status-bar';
|
||||
@@ -27,6 +46,9 @@ import { useTheme } from 'next-themes';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
|
||||
import { AffineTheme } from './plugins/affine-theme';
|
||||
import { AIButton } from './plugins/ai-button';
|
||||
|
||||
const storeManagerClient = new StoreManagerClient(
|
||||
new OpClient(
|
||||
new Worker(
|
||||
@@ -88,6 +110,102 @@ framework.impl(VirtualKeyboardProvider, {
|
||||
},
|
||||
});
|
||||
|
||||
framework.impl(AIButtonProvider, {
|
||||
presentAIButton: () => {
|
||||
return AIButton.present();
|
||||
},
|
||||
dismissAIButton: () => {
|
||||
return AIButton.dismiss();
|
||||
},
|
||||
});
|
||||
|
||||
// ------ some apis for native ------
|
||||
(window as any).getCurrentServerBaseUrl = () => {
|
||||
const globalContextService = frameworkProvider.get(GlobalContextService);
|
||||
const currentServerId = globalContextService.globalContext.serverId.get();
|
||||
const serversService = frameworkProvider.get(ServersService);
|
||||
const defaultServerService = frameworkProvider.get(DefaultServerService);
|
||||
const currentServer =
|
||||
(currentServerId ? serversService.server$(currentServerId).value : null) ??
|
||||
defaultServerService.server;
|
||||
return currentServer.baseUrl;
|
||||
};
|
||||
(window as any).getCurrentI18nLocale = () => {
|
||||
return I18n.language;
|
||||
};
|
||||
(window as any).getCurrentWorkspaceId = () => {
|
||||
const globalContextService = frameworkProvider.get(GlobalContextService);
|
||||
return globalContextService.globalContext.workspaceId.get();
|
||||
};
|
||||
(window as any).getCurrentDocId = () => {
|
||||
const globalContextService = frameworkProvider.get(GlobalContextService);
|
||||
return globalContextService.globalContext.docId.get();
|
||||
};
|
||||
(window as any).getCurrentDocContentInMarkdown = async () => {
|
||||
const globalContextService = frameworkProvider.get(GlobalContextService);
|
||||
const currentWorkspaceId =
|
||||
globalContextService.globalContext.workspaceId.get();
|
||||
const currentDocId = globalContextService.globalContext.docId.get();
|
||||
const workspacesService = frameworkProvider.get(WorkspacesService);
|
||||
const workspaceRef = currentWorkspaceId
|
||||
? workspacesService.openByWorkspaceId(currentWorkspaceId)
|
||||
: null;
|
||||
if (!workspaceRef) {
|
||||
return;
|
||||
}
|
||||
const { workspace, dispose: disposeWorkspace } = workspaceRef;
|
||||
|
||||
const docsService = workspace.scope.get(DocsService);
|
||||
const docRef = currentDocId ? docsService.open(currentDocId) : null;
|
||||
if (!docRef) {
|
||||
return;
|
||||
}
|
||||
const { doc, release: disposeDoc } = docRef;
|
||||
|
||||
try {
|
||||
const blockSuiteDoc = doc.blockSuiteDoc;
|
||||
|
||||
const transformer = new Transformer({
|
||||
schema: blockSuiteDoc.workspace.schema,
|
||||
blobCRUD: blockSuiteDoc.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => blockSuiteDoc.workspace.createDoc({ id }),
|
||||
get: (id: string) => blockSuiteDoc.workspace.getDoc(id),
|
||||
delete: (id: string) => blockSuiteDoc.workspace.removeDoc(id),
|
||||
},
|
||||
middlewares: [
|
||||
docLinkBaseURLMiddleware(blockSuiteDoc.workspace.id),
|
||||
titleMiddleware(blockSuiteDoc.workspace.meta.docMetas),
|
||||
],
|
||||
});
|
||||
const snapshot = transformer.docToSnapshot(blockSuiteDoc);
|
||||
|
||||
const container = new Container();
|
||||
[
|
||||
...MarkdownInlineToDeltaAdapterExtensions,
|
||||
...defaultBlockMarkdownAdapterMatchers,
|
||||
...InlineDeltaToMarkdownAdapterExtensions,
|
||||
].forEach(ext => {
|
||||
ext.setup(container);
|
||||
});
|
||||
const provider = container.provider();
|
||||
|
||||
const adapter = new MarkdownAdapter(transformer, provider);
|
||||
if (!snapshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const markdownResult = await adapter.fromDocSnapshot({
|
||||
snapshot,
|
||||
assets: transformer.assetsManager,
|
||||
});
|
||||
return markdownResult.file;
|
||||
} finally {
|
||||
disposeDoc();
|
||||
disposeWorkspace();
|
||||
}
|
||||
};
|
||||
|
||||
// setup application lifecycle events, and emit application start event
|
||||
window.addEventListener('focus', () => {
|
||||
frameworkProvider.get(LifecycleService).applicationFocus();
|
||||
@@ -130,7 +248,7 @@ CapacitorApp.addListener('appUrlOpen', ({ url }) => {
|
||||
console.error(e);
|
||||
});
|
||||
|
||||
const EdgeToEdgeCompatibilityProvider = () => {
|
||||
const ThemeProvider = () => {
|
||||
const { resolvedTheme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -145,8 +263,10 @@ const EdgeToEdgeCompatibilityProvider = () => {
|
||||
EdgeToEdge.setBackgroundColor({
|
||||
color: resolvedTheme === 'dark' ? '#000000' : '#F5F5F5',
|
||||
}).catch(console.error);
|
||||
AffineTheme.onThemeChanged({
|
||||
darkMode: resolvedTheme === 'dark',
|
||||
}).catch(console.error);
|
||||
}, [resolvedTheme]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -156,7 +276,7 @@ export function App() {
|
||||
<FrameworkRoot framework={frameworkProvider}>
|
||||
<I18nProvider>
|
||||
<AffineContext store={getCurrentStore()}>
|
||||
<EdgeToEdgeCompatibilityProvider />
|
||||
<ThemeProvider />
|
||||
<RouterProvider
|
||||
fallbackElement={<AppFallback />}
|
||||
router={router}
|
||||
|
||||
Reference in New Issue
Block a user