From 835fdc33c0041dd2cc4249ee9785b1098aaba9a5 Mon Sep 17 00:00:00 2001 From: pengx17 Date: Tue, 29 Oct 2024 05:49:49 +0000 Subject: [PATCH] feat(core): add open link in app to doc menu (#8597) add "open in desktop app" menu item for editor fix AF-1547 --- packages/common/env/src/constant.ts | 2 +- .../frontend/apps/electron/renderer/app.tsx | 8 +- .../apps/electron/src/main/deep-link.ts | 19 +++++ .../apps/electron/src/preload/electron-api.ts | 6 +- packages/frontend/apps/ios/src/app.tsx | 10 +-- .../core/src/components/affine/auth/oauth.tsx | 14 ++-- .../general-setting/about/index.tsx | 5 +- .../affine/subscription-landing/index.tsx | 4 +- .../block-suite-header/menu/index.tsx | 18 ++++ .../components/hooks/use-navigate-helper.ts | 6 +- .../core/src/desktop/pages/open-app.tsx | 83 +++++++------------ .../core/src/modules/cloud/services/auth.ts | 2 +- .../src/modules/cloud/stores/subscription.ts | 8 +- .../core/src/modules/open-in-app/constant.ts | 44 ++++++++++ .../core/src/modules/open-in-app/utils.ts | 32 +++++++ .../frontend/core/src/modules/url/index.ts | 6 +- .../modules/url/providers/client-schema.ts | 8 +- .../core/src/modules/url/services/url.ts | 8 +- .../modules/workspace-engine/impls/local.ts | 51 ++++++++---- .../i18n/src/i18n-completenesses.json | 4 +- packages/frontend/i18n/src/resources/en.json | 1 + 21 files changed, 222 insertions(+), 117 deletions(-) create mode 100644 packages/frontend/core/src/modules/open-in-app/constant.ts create mode 100644 packages/frontend/core/src/modules/open-in-app/utils.ts diff --git a/packages/common/env/src/constant.ts b/packages/common/env/src/constant.ts index 13b2fdd714..43dfd43062 100644 --- a/packages/common/env/src/constant.ts +++ b/packages/common/env/src/constant.ts @@ -5,7 +5,7 @@ declare global { // eslint-disable-next-line no-var var __appInfo: { electron: boolean; - schema: string; + scheme: string; windowName: string; }; } diff --git a/packages/frontend/apps/electron/renderer/app.tsx b/packages/frontend/apps/electron/renderer/app.tsx index bc4dce229e..58618a8220 100644 --- a/packages/frontend/apps/electron/renderer/app.tsx +++ b/packages/frontend/apps/electron/renderer/app.tsx @@ -11,7 +11,7 @@ import { I18nProvider } from '@affine/core/modules/i18n'; import { configureElectronStateStorageImpls } from '@affine/core/modules/storage'; import { CustomThemeModifier } from '@affine/core/modules/theme-editor'; import { - ClientSchemaProvider, + ClientSchemeProvider, PopupWindowProvider, } from '@affine/core/modules/url'; import { configureSqliteUserspaceStorageProvider } from '@affine/core/modules/userspace'; @@ -71,9 +71,9 @@ framework.impl(PopupWindowProvider, { }); }, }); -framework.impl(ClientSchemaProvider, { - getClientSchema() { - return appInfo?.schema; +framework.impl(ClientSchemeProvider, { + getClientScheme() { + return appInfo?.scheme; }, }); framework.impl(ValidatorProvider, { diff --git a/packages/frontend/apps/electron/src/main/deep-link.ts b/packages/frontend/apps/electron/src/main/deep-link.ts index a119cc3867..a38ac591a8 100644 --- a/packages/frontend/apps/electron/src/main/deep-link.ts +++ b/packages/frontend/apps/electron/src/main/deep-link.ts @@ -6,6 +6,7 @@ import { buildType, isDev } from './config'; import { logger } from './logger'; import { uiSubjects } from './ui'; import { + addTab, getMainWindow, openUrlInHiddenWindow, openUrlInMainWindow, @@ -81,6 +82,24 @@ async function handleAffineUrl(url: string) { method, payload, }); + } else if ( + urlObj.searchParams.get('new-tab') && + urlObj.pathname.startsWith('/workspace') + ) { + // @todo(@forehalo): refactor router utilities + // basename of /workspace/xxx/yyy is /workspace/xxx + const basename = urlObj.pathname.split('/').slice(0, 3).join('/'); + const pathname = '/' + urlObj.pathname.split('/').slice(3).join('/'); + + await addTab({ + basename, + show: true, + view: { + path: { + pathname: pathname, + }, + }, + }); } else { const hiddenWindow = urlObj.searchParams.get('hidden') ? await openUrlInHiddenWindow(urlObj) diff --git a/packages/frontend/apps/electron/src/preload/electron-api.ts b/packages/frontend/apps/electron/src/preload/electron-api.ts index 6b47e36935..f02f741f6e 100644 --- a/packages/frontend/apps/electron/src/preload/electron-api.ts +++ b/packages/frontend/apps/electron/src/preload/electron-api.ts @@ -41,9 +41,9 @@ const ReleaseTypeSchema = z.enum(['stable', 'beta', 'canary', 'internal']); const envBuildType = (process.env.BUILD_TYPE || 'canary').trim().toLowerCase(); const buildType = ReleaseTypeSchema.parse(envBuildType); const isDev = process.env.NODE_ENV === 'development'; -let schema = +let scheme = buildType === 'stable' ? 'affine' : (`affine-${envBuildType}` as Schema); -schema = isDev ? 'affine-dev' : schema; +scheme = isDev ? 'affine-dev' : scheme; export const appInfo = { electron: true, @@ -53,7 +53,7 @@ export const appInfo = { viewId: process.argv.find(arg => arg.startsWith('--view-id='))?.split('=')[1] ?? 'unknown', - schema, + scheme, }; function getMainAPIs() { diff --git a/packages/frontend/apps/ios/src/app.tsx b/packages/frontend/apps/ios/src/app.tsx index 3dceaa3181..3317f1c7fc 100644 --- a/packages/frontend/apps/ios/src/app.tsx +++ b/packages/frontend/apps/ios/src/app.tsx @@ -7,10 +7,8 @@ import { configureCommonModules } from '@affine/core/modules'; import { AuthService, WebSocketAuthProvider } from '@affine/core/modules/cloud'; import { I18nProvider } from '@affine/core/modules/i18n'; import { configureLocalStorageStateStorageImpls } from '@affine/core/modules/storage'; -import { - ClientSchemaProvider, - PopupWindowProvider, -} from '@affine/core/modules/url'; +import { PopupWindowProvider } from '@affine/core/modules/url'; +import { ClientSchemeProvider } from '@affine/core/modules/url/providers/client-schema'; import { configureIndexedDBUserspaceStorageProvider } from '@affine/core/modules/userspace'; import { configureBrowserWorkbenchModule } from '@affine/core/modules/workbench'; import { @@ -51,8 +49,8 @@ framework.impl(PopupWindowProvider, { }).catch(console.error); }, }); -framework.impl(ClientSchemaProvider, { - getClientSchema() { +framework.impl(ClientSchemeProvider, { + getClientScheme() { return 'affine'; }, }); diff --git a/packages/frontend/core/src/components/affine/auth/oauth.tsx b/packages/frontend/core/src/components/affine/auth/oauth.tsx index 01d61128f7..3f8b65cdbb 100644 --- a/packages/frontend/core/src/components/affine/auth/oauth.tsx +++ b/packages/frontend/core/src/components/affine/auth/oauth.tsx @@ -35,7 +35,7 @@ export function OAuth({ redirectUrl }: { redirectUrl?: string }) { const oauthProviders = useLiveData( serverConfig.config$.map(r => r?.oauthProviders) ); - const schema = urlService.getClientSchema(); + const scheme = urlService.getClientScheme(); if (!oauth) { return ; @@ -46,7 +46,7 @@ export function OAuth({ redirectUrl }: { redirectUrl?: string }) { key={provider} provider={provider} redirectUrl={redirectUrl} - schema={schema} + scheme={scheme} popupWindow={url => { urlService.openPopupWindow(url); }} @@ -57,12 +57,12 @@ export function OAuth({ redirectUrl }: { redirectUrl?: string }) { function OAuthProvider({ provider, redirectUrl, - schema, + scheme, popupWindow, }: { provider: OAuthProviderType; redirectUrl?: string; - schema?: string; + scheme?: string; popupWindow: (url: string) => void; }) { const { icon } = OAuthProviderMap[provider]; @@ -76,8 +76,8 @@ function OAuthProvider({ params.set('redirect_uri', redirectUrl); } - if (schema) { - params.set('client', schema); + if (scheme) { + params.set('client', scheme); } // TODO: Android app scheme not implemented @@ -87,7 +87,7 @@ function OAuthProvider({ BUILD_CONFIG.serverUrlPrefix + `/oauth/login?${params.toString()}`; popupWindow(oauthUrl); - }, [popupWindow, provider, redirectUrl, schema]); + }, [popupWindow, provider, redirectUrl, scheme]); return (