mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(core): open app in electron app entry (#8637)
fix PD-208 fix PD-210 fix PD-209 fix AF-1495
This commit is contained in:
@@ -5,11 +5,8 @@ import {
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useAppUpdater } from '@affine/core/components/hooks/use-app-updater';
|
||||
import {
|
||||
appIconMap,
|
||||
appNames,
|
||||
} from '@affine/core/modules/open-in-app/constant';
|
||||
import { UrlService } from '@affine/core/modules/url';
|
||||
import { appIconMap, appNames } from '@affine/core/utils';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { mixpanel } from '@affine/track';
|
||||
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { useAppSettingHelper } from '../../../../../components/hooks/affine/use-app-setting-helper';
|
||||
import { LanguageMenu } from '../../../language-menu';
|
||||
import { OpenInAppLinksMenu } from './links';
|
||||
import { settingWrapper } from './style.css';
|
||||
import { ThemeEditorSetting } from './theme-editor-setting';
|
||||
|
||||
@@ -106,6 +107,17 @@ export const AppearanceSettings = () => {
|
||||
{enableThemeEditor ? <ThemeEditorSetting /> : null}
|
||||
</SettingWrapper>
|
||||
|
||||
{BUILD_CONFIG.isWeb ? (
|
||||
<SettingWrapper title={t['com.affine.setting.appearance.links']()}>
|
||||
<SettingRow
|
||||
name={t['com.affine.setting.appearance.open-in-app']()}
|
||||
desc={t['com.affine.setting.appearance.open-in-app.hint']()}
|
||||
data-testid="open-in-app-links-trigger"
|
||||
>
|
||||
<OpenInAppLinksMenu />
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
) : null}
|
||||
{BUILD_CONFIG.isElectron ? (
|
||||
<SettingWrapper
|
||||
title={t['com.affine.appearanceSettings.sidebar.title']()}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const menu = style({
|
||||
background: cssVar('white'),
|
||||
width: '250px',
|
||||
maxHeight: '30vh',
|
||||
overflowY: 'auto',
|
||||
});
|
||||
|
||||
export const menuItem = style({
|
||||
color: cssVar('textPrimaryColor'),
|
||||
selectors: {
|
||||
'&[data-selected=true]': {
|
||||
color: cssVar('primaryColor'),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Menu, MenuItem, MenuTrigger } from '@affine/component';
|
||||
import {
|
||||
OpenInAppService,
|
||||
OpenLinkMode,
|
||||
} from '@affine/core/modules/open-in-app';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import * as styles from './links.css';
|
||||
|
||||
export const OpenInAppLinksMenu = () => {
|
||||
const t = useI18n();
|
||||
const openInAppService = useService(OpenInAppService);
|
||||
const currentOpenInAppMode = useLiveData(openInAppService.openLinkMode$);
|
||||
|
||||
const options = useMemo(
|
||||
() =>
|
||||
Object.values(OpenLinkMode).map(mode => ({
|
||||
label:
|
||||
t.t(`com.affine.setting.appearance.open-in-app.${mode}`) ||
|
||||
`com.affine.setting.appearance.open-in-app.${mode}`,
|
||||
value: mode,
|
||||
})),
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
items={options.map(option => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={option.value}
|
||||
title={option.label}
|
||||
onSelect={() => openInAppService.setOpenLinkMode(option.value)}
|
||||
data-selected={currentOpenInAppMode === option.value}
|
||||
>
|
||||
{option.label}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
contentOptions={{
|
||||
className: styles.menu,
|
||||
align: 'end',
|
||||
}}
|
||||
>
|
||||
<MenuTrigger
|
||||
style={{ textTransform: 'capitalize', fontWeight: 600, width: '250px' }}
|
||||
block={true}
|
||||
>
|
||||
{options.find(option => option.value === currentOpenInAppMode)?.label}
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
@@ -18,14 +18,14 @@ const UpgradeSuccessLayout = ({
|
||||
const t = useI18n();
|
||||
const [params] = useSearchParams();
|
||||
|
||||
const { jumpToIndex, openInApp } = useNavigateHelper();
|
||||
const { jumpToIndex, jumpToOpenInApp } = useNavigateHelper();
|
||||
const openAffine = useCallback(() => {
|
||||
if (params.get('scheme')) {
|
||||
openInApp(params.get('scheme') ?? 'affine', 'bring-to-front');
|
||||
jumpToOpenInApp('bring-to-front');
|
||||
} else {
|
||||
jumpToIndex();
|
||||
}
|
||||
}, [jumpToIndex, openInApp, params]);
|
||||
}, [jumpToIndex, jumpToOpenInApp, params]);
|
||||
|
||||
const subtitle = (
|
||||
<div className={styles.leftContentText}>
|
||||
|
||||
@@ -25,7 +25,7 @@ import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||
import { useDetailPageHeaderResponsive } from '@affine/core/desktop/pages/workspace/detail-page/use-header-responsive';
|
||||
import { DocInfoService } from '@affine/core/modules/doc-info';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { getOpenUrlInDesktopAppLink } from '@affine/core/modules/open-in-app/utils';
|
||||
import { OpenInAppService } from '@affine/core/modules/open-in-app/services';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { ViewService } from '@affine/core/modules/workbench/services/view';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
@@ -52,6 +52,7 @@ import {
|
||||
FeatureFlagService,
|
||||
useLiveData,
|
||||
useService,
|
||||
useServiceOptional,
|
||||
WorkspaceService,
|
||||
} from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
@@ -92,6 +93,7 @@ export const PageHeaderMenuButton = ({
|
||||
const enableSnapshotImportExport = useLiveData(
|
||||
featureFlagService.flags.enable_snapshot_import_export.$
|
||||
);
|
||||
const openInAppService = useServiceOptional(OpenInAppService);
|
||||
|
||||
const { favorite, toggleFavorite } = useFavorite(pageId);
|
||||
|
||||
@@ -265,11 +267,8 @@ export const PageHeaderMenuButton = ({
|
||||
);
|
||||
|
||||
const onOpenInDesktop = useCallback(() => {
|
||||
const url = getOpenUrlInDesktopAppLink(window.location.href, true);
|
||||
if (url) {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
}, []);
|
||||
openInAppService?.showOpenInAppPage();
|
||||
}, [openInAppService]);
|
||||
|
||||
const EditMenu = (
|
||||
<>
|
||||
@@ -376,7 +375,8 @@ export const PageHeaderMenuButton = ({
|
||||
data-testid="editor-option-menu-delete"
|
||||
onSelect={handleOpenTrashModal}
|
||||
/>
|
||||
{BUILD_CONFIG.isWeb ? (
|
||||
{BUILD_CONFIG.isWeb &&
|
||||
workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD ? (
|
||||
<MenuItem
|
||||
prefixIcon={<LocalWorkspaceIcon />}
|
||||
data-testid="editor-option-menu-link"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { toURLSearchParams } from '@affine/core/modules/navigation';
|
||||
import { getOpenUrlInDesktopAppLink } from '@affine/core/modules/open-in-app';
|
||||
import type { DocMode } from '@blocksuite/affine/blocks';
|
||||
import { createContext, useCallback, useContext, useMemo } from 'react';
|
||||
import type { NavigateFunction, NavigateOptions } from 'react-router-dom';
|
||||
@@ -159,10 +160,16 @@ export function useNavigateHelper() {
|
||||
[navigate]
|
||||
);
|
||||
|
||||
const openInApp = useCallback(
|
||||
(scheme: string, path: string) => {
|
||||
const encodedUrl = encodeURIComponent(`${scheme}://${path}`);
|
||||
return navigate(`/open-app/url?scheme=${scheme}&url=${encodedUrl}`);
|
||||
const jumpToOpenInApp = useCallback(
|
||||
(url: string, newTab = true) => {
|
||||
const deeplink = getOpenUrlInDesktopAppLink(url, newTab);
|
||||
|
||||
if (!deeplink) {
|
||||
return;
|
||||
}
|
||||
|
||||
const encodedUrl = encodeURIComponent(deeplink);
|
||||
return navigate(`/open-app/url?url=${encodedUrl}`);
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
@@ -189,7 +196,7 @@ export function useNavigateHelper() {
|
||||
jumpToCollections,
|
||||
jumpToTags,
|
||||
jumpToTag,
|
||||
openInApp,
|
||||
jumpToOpenInApp,
|
||||
jumpToImportTemplate,
|
||||
}),
|
||||
[
|
||||
@@ -204,7 +211,7 @@ export function useNavigateHelper() {
|
||||
jumpToCollections,
|
||||
jumpToTags,
|
||||
jumpToTag,
|
||||
openInApp,
|
||||
jumpToOpenInApp,
|
||||
jumpToImportTemplate,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -5,11 +5,11 @@ import {
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import {
|
||||
AddPageButton,
|
||||
AppDownloadButton,
|
||||
AppSidebar,
|
||||
CategoryDivider,
|
||||
MenuItem,
|
||||
MenuLinkItem,
|
||||
OpenInAppCard,
|
||||
QuickSearchInput,
|
||||
SidebarContainer,
|
||||
SidebarScrollableContainer,
|
||||
@@ -190,7 +190,7 @@ export const RootAppSidebar = (): ReactElement => {
|
||||
</div>
|
||||
</SidebarScrollableContainer>
|
||||
<SidebarContainer>
|
||||
{BUILD_CONFIG.isElectron ? <UpdaterButton /> : <AppDownloadButton />}
|
||||
{BUILD_CONFIG.isElectron ? <UpdaterButton /> : <OpenInAppCard />}
|
||||
</SidebarContainer>
|
||||
</AppSidebar>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user