fix(env): is mobile flag (#8005)

only 'mobile' entry has isMobile = true flag
This commit is contained in:
EYHN 2024-09-04 09:21:36 +00:00
parent 53886a7cd3
commit 2524491bd1
No known key found for this signature in database
GPG Key ID: 46C9E26A75AB276C
78 changed files with 169 additions and 205 deletions

View File

@ -34,8 +34,8 @@ const createPattern = packageName => [
{ {
group: ['@affine/env/constant'], group: ['@affine/env/constant'],
message: message:
'Do not import from @affine/env/constant. Use `environment.isDesktop` instead', 'Do not import from @affine/env/constant. Use `environment.isElectron` instead',
importNames: ['isDesktop'], importNames: ['isElectron'],
}, },
]; ];

View File

@ -2,19 +2,16 @@
import type { DocCollection } from '@blocksuite/store'; import type { DocCollection } from '@blocksuite/store';
declare global { declare global {
interface Window { // eslint-disable-next-line no-var
__appInfo: { var __appInfo: {
electron: boolean; electron: boolean;
schema: string; schema: string;
windowName: string; windowName: string;
}; };
}
} }
//#region runtime variables //#region runtime variables
export const isBrowser = typeof window !== 'undefined'; export const isElectron = !!globalThis.__appInfo?.electron;
export const isServer = !isBrowser && typeof navigator === 'undefined';
export const isDesktop = isBrowser && !!window.__appInfo?.electron;
//#endregion //#endregion
export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace'; export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace';
export const UNTITLED_WORKSPACE_NAME = 'Untitled'; export const UNTITLED_WORKSPACE_NAME = 'Untitled';

View File

@ -2,7 +2,7 @@
import { assertEquals } from '@blocksuite/global/utils'; import { assertEquals } from '@blocksuite/global/utils';
import { z } from 'zod'; import { z } from 'zod';
import { isDesktop, isServer } from './constant.js'; import { isElectron } from './constant.js';
import { UaHelper } from './ua-helper.js'; import { UaHelper } from './ua-helper.js';
export const runtimeFlagsSchema = z.object({ export const runtimeFlagsSchema = z.object({
@ -10,6 +10,7 @@ export const runtimeFlagsSchema = z.object({
serverUrlPrefix: z.string(), serverUrlPrefix: z.string(),
appVersion: z.string(), appVersion: z.string(),
editorVersion: z.string(), editorVersion: z.string(),
distribution: z.enum(['browser', 'desktop', 'admin', 'mobile']),
appBuildType: z.union([ appBuildType: z.union([
z.literal('stable'), z.literal('stable'),
z.literal('beta'), z.literal('beta'),
@ -35,18 +36,19 @@ export const runtimeFlagsSchema = z.object({
export type RuntimeConfig = z.infer<typeof runtimeFlagsSchema>; export type RuntimeConfig = z.infer<typeof runtimeFlagsSchema>;
type BrowserBase = { export type Environment = {
/**
* @example https://app.affine.pro
* @example http://localhost:3000
*/
origin: string;
isDesktop: boolean;
isBrowser: true;
isServer: false;
isDebug: boolean; isDebug: boolean;
// browser special properties // Edition
isDesktopEdition: boolean;
isMobileEdition: boolean;
// Platform/Entry
isElectron: boolean;
isDesktopWeb: boolean;
isMobileWeb: boolean;
// Device
isLinux: boolean; isLinux: boolean;
isMacOs: boolean; isMacOs: boolean;
isIOS: boolean; isIOS: boolean;
@ -55,37 +57,9 @@ type BrowserBase = {
isFireFox: boolean; isFireFox: boolean;
isMobile: boolean; isMobile: boolean;
isChrome: boolean; isChrome: boolean;
chromeVersion?: number;
}; };
type NonChromeBrowser = BrowserBase & {
isChrome: false;
};
type ChromeBrowser = BrowserBase & {
isSafari: false;
isFireFox: false;
isChrome: true;
chromeVersion: number;
};
type Browser = NonChromeBrowser | ChromeBrowser;
type Server = {
isDesktop: false;
isBrowser: false;
isServer: true;
isDebug: boolean;
};
interface Desktop extends ChromeBrowser {
isDesktop: true;
isBrowser: true;
isServer: false;
isDebug: boolean;
}
export type Environment = Browser | Server | Desktop;
function setupRuntimeConfig() { function setupRuntimeConfig() {
if (!process.env.RUNTIME_CONFIG) { if (!process.env.RUNTIME_CONFIG) {
return; return;
@ -106,31 +80,43 @@ export function setupGlobal() {
let environment: Environment; let environment: Environment;
const isDebug = process.env.NODE_ENV === 'development'; const isDebug = process.env.NODE_ENV === 'development';
if (isServer) {
if (!globalThis.navigator) {
environment = { environment = {
isDesktop: false, isDesktopEdition: false,
isBrowser: false, isMobileEdition: false,
isServer: true, isElectron: false,
isDesktopWeb: false,
isMobileWeb: false,
isMobile: false,
isDebug, isDebug,
} satisfies Server; isLinux: false,
isMacOs: false,
isSafari: false,
isWindows: false,
isFireFox: false,
isChrome: false,
isIOS: false,
};
} else { } else {
const uaHelper = new UaHelper(navigator); const uaHelper = new UaHelper(globalThis.navigator);
environment = { environment = {
origin: window.location.origin, isDesktopEdition: runtimeConfig.distribution !== 'mobile',
isDesktop, isMobileEdition: runtimeConfig.distribution === 'mobile',
isBrowser: true, isDesktopWeb: runtimeConfig.distribution === 'browser',
isServer: false, isMobileWeb: runtimeConfig.distribution === 'mobile',
isElectron,
isDebug, isDebug,
isMobile: uaHelper.isMobile,
isLinux: uaHelper.isLinux, isLinux: uaHelper.isLinux,
isMacOs: uaHelper.isMacOs, isMacOs: uaHelper.isMacOs,
isSafari: uaHelper.isSafari, isSafari: uaHelper.isSafari,
isWindows: uaHelper.isWindows, isWindows: uaHelper.isWindows,
isFireFox: uaHelper.isFireFox, isFireFox: uaHelper.isFireFox,
isMobile: uaHelper.isMobile,
isChrome: uaHelper.isChrome, isChrome: uaHelper.isChrome,
isIOS: uaHelper.isIOS, isIOS: uaHelper.isIOS,
} as Browser; };
// Chrome on iOS is still Safari // Chrome on iOS is still Safari
if (environment.isChrome && !environment.isIOS) { if (environment.isChrome && !environment.isIOS) {
assertEquals(environment.isSafari, false); assertEquals(environment.isSafari, false);
@ -141,9 +127,10 @@ export function setupGlobal() {
isFireFox: false, isFireFox: false,
isChrome: true, isChrome: true,
chromeVersion: uaHelper.getChromeVersion(), chromeVersion: uaHelper.getChromeVersion(),
} satisfies ChromeBrowser; };
} }
} }
globalThis.environment = environment; globalThis.environment = environment;
globalThis.$AFFINE_SETUP = true; globalThis.$AFFINE_SETUP = true;

View File

@ -44,7 +44,7 @@ export const dateFormatOptions: DateFormats[] = [
]; ];
const appSettingBaseAtom = atomWithStorage<AppSetting>('affine-settings', { const appSettingBaseAtom = atomWithStorage<AppSetting>('affine-settings', {
clientBorder: environment.isDesktop && !environment.isWindows, clientBorder: environment.isElectron && !environment.isWindows,
windowFrameStyle: 'frameless', windowFrameStyle: 'frameless',
dateFormat: dateFormatOptions[0], dateFormat: dateFormatOptions[0],
startWeekOnMonday: false, startWeekOnMonday: false,
@ -61,7 +61,7 @@ type SetStateAction<Value> = Value | ((prev: Value) => Value);
const appSettingEffect = atomEffect(get => { const appSettingEffect = atomEffect(get => {
const settings = get(appSettingBaseAtom); const settings = get(appSettingBaseAtom);
// some values in settings should be synced into electron side // some values in settings should be synced into electron side
if (environment.isDesktop) { if (environment.isElectron) {
logger.debug('sync settings to electron', settings); logger.debug('sync settings to electron', settings);
// this api type in @affine/electron-api, but it is circular dependency this package, use any here // this api type in @affine/electron-api, but it is circular dependency this package, use any here
(window as any).apis?.updater (window as any).apis?.updater

View File

@ -1,7 +1,7 @@
import type { FlagInfo } from './types'; import type { FlagInfo } from './types';
const isNotStableBuild = runtimeConfig.appBuildType !== 'stable'; const isNotStableBuild = runtimeConfig.appBuildType !== 'stable';
const isDesktopEnvironment = environment.isDesktop; const isDesktopEnvironment = environment.isElectron;
const isCanaryBuild = runtimeConfig.appBuildType === 'canary'; const isCanaryBuild = runtimeConfig.appBuildType === 'canary';
export const AFFINE_FLAGS = { export const AFFINE_FLAGS = {

View File

@ -20,7 +20,7 @@ export const AffineOtherPageLayout = ({
return ( return (
<div className={styles.root}> <div className={styles.root}>
{environment.isDesktop ? null : ( {environment.isElectron ? null : (
<div className={styles.topNav}> <div className={styles.topNav}>
<a href="/" rel="noreferrer" className={styles.affineLogo}> <a href="/" rel="noreferrer" className={styles.affineLogo}>
<Logo1Icon width={24} height={24} /> <Logo1Icon width={24} height={24} />

View File

@ -119,8 +119,8 @@ export const OnboardingPage = ({
() => questions?.[questionIdx], () => questions?.[questionIdx],
[questionIdx, questions] [questionIdx, questions]
); );
const isMacosDesktop = environment.isDesktop && environment.isMacOs; const isMacosDesktop = environment.isElectron && environment.isMacOs;
const isWindowsDesktop = environment.isDesktop && environment.isWindows; const isWindowsDesktop = environment.isElectron && environment.isWindows;
if (!questions) { if (!questions) {
return null; return null;

View File

@ -10,7 +10,7 @@ const DesktopThemeSync = memo(function DesktopThemeSync() {
const lastThemeRef = useRef(theme); const lastThemeRef = useRef(theme);
const onceRef = useRef(false); const onceRef = useRef(false);
if (lastThemeRef.current !== theme || !onceRef.current) { if (lastThemeRef.current !== theme || !onceRef.current) {
if (environment.isDesktop && theme) { if (environment.isElectron && theme) {
apis?.ui apis?.ui
.handleThemeChange(theme as 'dark' | 'light' | 'system') .handleThemeChange(theme as 'dark' | 'light' | 'system')
.catch(err => { .catch(err => {

View File

@ -1,5 +1,4 @@
export * from './menu.types'; export * from './menu.types';
import { isMobile } from '../../utils/env';
import { DesktopMenuItem } from './desktop/item'; import { DesktopMenuItem } from './desktop/item';
import { DesktopMenu } from './desktop/root'; import { DesktopMenu } from './desktop/root';
import { DesktopMenuSeparator } from './desktop/separator'; import { DesktopMenuSeparator } from './desktop/separator';
@ -10,10 +9,12 @@ import { MobileMenu } from './mobile/root';
import { MobileMenuSeparator } from './mobile/separator'; import { MobileMenuSeparator } from './mobile/separator';
import { MobileMenuSub } from './mobile/sub'; import { MobileMenuSub } from './mobile/sub';
const MenuItem = isMobile() ? MobileMenuItem : DesktopMenuItem; const MenuItem = environment.isMobileEdition ? MobileMenuItem : DesktopMenuItem;
const MenuSeparator = isMobile() ? MobileMenuSeparator : DesktopMenuSeparator; const MenuSeparator = environment.isMobileEdition
const MenuSub = isMobile() ? MobileMenuSub : DesktopMenuSub; ? MobileMenuSeparator
const Menu = isMobile() ? MobileMenu : DesktopMenu; : DesktopMenuSeparator;
const MenuSub = environment.isMobileEdition ? MobileMenuSub : DesktopMenuSub;
const Menu = environment.isMobileEdition ? MobileMenu : DesktopMenu;
export { export {
DesktopMenu, DesktopMenu,

View File

@ -1,7 +1,6 @@
import { DoneIcon } from '@blocksuite/icons/rc'; import { DoneIcon } from '@blocksuite/icons/rc';
import clsx from 'clsx'; import clsx from 'clsx';
import { isMobile } from '../../utils/env';
import type { MenuItemProps } from './menu.types'; import type { MenuItemProps } from './menu.types';
import { mobileMenuItem } from './mobile/styles.css'; import { mobileMenuItem } from './mobile/styles.css';
import * as styles from './styles.css'; import * as styles from './styles.css';
@ -27,7 +26,7 @@ export const useMenuItem = <T extends MenuItemProps>({
checked, checked,
selected, selected,
block, block,
[mobileMenuItem]: isMobile(), [mobileMenuItem]: environment.isMobileEdition,
}, },
propsClassName propsClassName
); );

View File

@ -12,7 +12,6 @@ import clsx from 'clsx';
import type { CSSProperties, MouseEvent } from 'react'; import type { CSSProperties, MouseEvent } from 'react';
import { forwardRef, useCallback, useEffect, useState } from 'react'; import { forwardRef, useCallback, useEffect, useState } from 'react';
import { isMobile } from '../../utils/env';
import type { IconButtonProps } from '../button'; import type { IconButtonProps } from '../button';
import { IconButton } from '../button'; import { IconButton } from '../button';
import * as styles from './styles.css'; import * as styles from './styles.css';
@ -151,9 +150,7 @@ export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
children, children,
contentWrapperClassName, contentWrapperClassName,
contentWrapperStyle, contentWrapperStyle,
animation = environment.isBrowser && environment.isMobile animation = environment.isMobileEdition ? 'slideBottom' : 'fadeScaleTop',
? 'slideBottom'
: 'fadeScaleTop',
fullScreen, fullScreen,
...otherProps ...otherProps
} = props; } = props;
@ -225,7 +222,7 @@ export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
`anim-${animation}`, `anim-${animation}`,
styles.modalOverlay, styles.modalOverlay,
overlayClassName, overlayClassName,
{ mobile: isMobile() } { mobile: environment.isMobileEdition }
)} )}
style={{ style={{
...overlayStyle, ...overlayStyle,

View File

@ -1,3 +0,0 @@
export const isMobile = () => {
return environment.isBrowser && environment.isMobile;
};

View File

@ -23,7 +23,7 @@ export function registerAffineCreationCommands({
category: 'affine:creation', category: 'affine:creation',
label: t['com.affine.cmdk.affine.new-page'](), label: t['com.affine.cmdk.affine.new-page'](),
icon: <PlusIcon />, icon: <PlusIcon />,
keyBinding: environment.isDesktop keyBinding: environment.isElectron
? { ? {
binding: '$mod+N', binding: '$mod+N',
skipRegister: true, skipRegister: true,
@ -73,7 +73,7 @@ export function registerAffineCreationCommands({
icon: <ImportIcon />, icon: <ImportIcon />,
label: t['com.affine.cmdk.affine.import-workspace'](), label: t['com.affine.cmdk.affine.import-workspace'](),
preconditionStrategy: () => { preconditionStrategy: () => {
return environment.isDesktop; return environment.isElectron;
}, },
run() { run() {
track.$.cmdk.workspace.createWorkspace({ track.$.cmdk.workspace.createWorkspace({

View File

@ -183,7 +183,7 @@ export function registerAffineSettingsCommands({
`, `,
category: 'affine:settings', category: 'affine:settings',
icon: <SettingsIcon />, icon: <SettingsIcon />,
preconditionStrategy: () => environment.isDesktop, preconditionStrategy: () => environment.isElectron,
run() { run() {
track.$.cmdk.settings.changeAppSetting({ track.$.cmdk.settings.changeAppSetting({
key: 'clientBorder', key: 'clientBorder',
@ -231,7 +231,7 @@ export function registerAffineSettingsCommands({
]()}`, ]()}`,
category: 'affine:settings', category: 'affine:settings',
icon: <SettingsIcon />, icon: <SettingsIcon />,
preconditionStrategy: () => environment.isDesktop, preconditionStrategy: () => environment.isElectron,
run() { run() {
track.$.cmdk.settings.changeAppSetting({ track.$.cmdk.settings.changeAppSetting({
key: 'enableNoisyBackground', key: 'enableNoisyBackground',
@ -257,7 +257,7 @@ export function registerAffineSettingsCommands({
]()}`, ]()}`,
category: 'affine:settings', category: 'affine:settings',
icon: <SettingsIcon />, icon: <SettingsIcon />,
preconditionStrategy: () => environment.isDesktop && environment.isMacOs, preconditionStrategy: () => environment.isElectron && environment.isMacOs,
run() { run() {
track.$.cmdk.settings.changeAppSetting({ track.$.cmdk.settings.changeAppSetting({
key: 'enableBlurBackground', key: 'enableBlurBackground',

View File

@ -16,7 +16,7 @@ export const AppContainer = (props: WorkspaceRootProps) => {
useNoisyBackground={appSettings.enableNoisyBackground} useNoisyBackground={appSettings.enableNoisyBackground}
useBlurBackground={ useBlurBackground={
appSettings.enableBlurBackground && appSettings.enableBlurBackground &&
environment.isDesktop && environment.isElectron &&
environment.isMacOs environment.isMacOs
} }
{...props} {...props}

View File

@ -57,7 +57,7 @@ function OAuthProvider({ provider }: { provider: OAuthProviderType }) {
try { try {
setIsConnecting(true); setIsConnecting(true);
const url = await authService.oauthPreflight(provider); const url = await authService.oauthPreflight(provider);
if (environment.isDesktop) { if (environment.isElectron) {
await apis?.ui.openExternal(url); await apis?.ui.openExternal(url);
} else { } else {
popupWindow(url); popupWindow(url);

View File

@ -122,7 +122,7 @@ const useSendEmail = (emailType: AuthPanelProps<'sendEmail'>['emailType']) => {
return trigger({ return trigger({
email, email,
callbackUrl: `/auth/${callbackUrl}?isClient=${ callbackUrl: `/auth/${callbackUrl}?isClient=${
environment.isDesktop ? 'true' : 'false' environment.isElectron ? 'true' : 'false'
}`, }`,
}); });
}, },

View File

@ -14,7 +14,7 @@ type Challenge = {
}; };
const challengeFetcher = async (url: string) => { const challengeFetcher = async (url: string) => {
if (!environment.isDesktop) { if (!environment.isElectron) {
return undefined; return undefined;
} }
@ -31,7 +31,7 @@ const challengeFetcher = async (url: string) => {
}; };
const generateChallengeResponse = async (challenge: string) => { const generateChallengeResponse = async (challenge: string) => {
if (!environment.isDesktop) { if (!environment.isElectron) {
return undefined; return undefined;
} }
@ -56,7 +56,7 @@ export const Captcha = () => {
return null; return null;
} }
if (environment.isDesktop) { if (environment.isElectron) {
if (response) { if (response) {
return <div className={style.captchaWrapper}>Making Challenge</div>; return <div className={style.captchaWrapper}>Making Challenge</div>;
} else { } else {
@ -87,7 +87,7 @@ export const useCaptcha = (): [string | undefined, string?] => {
useEffect(() => { useEffect(() => {
if ( if (
hasCaptchaFeature && hasCaptchaFeature &&
environment.isDesktop && environment.isElectron &&
challenge?.challenge && challenge?.challenge &&
prevChallenge.current !== challenge.challenge prevChallenge.current !== challenge.challenge
) { ) {
@ -104,7 +104,7 @@ export const useCaptcha = (): [string | undefined, string?] => {
return ['XXXX.DUMMY.TOKEN.XXXX']; return ['XXXX.DUMMY.TOKEN.XXXX'];
} }
if (environment.isDesktop) { if (environment.isElectron) {
if (response) { if (response) {
return [response, challenge?.challenge]; return [response, challenge?.challenge];
} else { } else {

View File

@ -43,7 +43,7 @@ export const Onboarding = ({ onOpenApp }: OnboardingProps) => {
return ( return (
<div <div
className={styles.onboarding} className={styles.onboarding}
data-is-desktop={environment.isDesktop} data-is-desktop={environment.isElectron}
data-is-window={!!status.activeId || !!status.unfoldingId} data-is-window={!!status.activeId || !!status.unfoldingId}
> >
<div className={styles.offsetOrigin}> <div className={styles.offsetOrigin}>

View File

@ -72,7 +72,7 @@ export const AboutAffine = () => {
name={t['com.affine.aboutAFFiNE.version.editor.title']()} name={t['com.affine.aboutAFFiNE.version.editor.title']()}
desc={runtimeConfig.editorVersion} desc={runtimeConfig.editorVersion}
/> />
{environment.isDesktop ? ( {environment.isElectron ? (
<> <>
<UpdateCheckSection /> <UpdateCheckSection />
<SettingRow <SettingRow

View File

@ -85,7 +85,7 @@ export const AppearanceSettings = () => {
<LanguageMenu /> <LanguageMenu />
</div> </div>
</SettingRow> </SettingRow>
{environment.isDesktop ? ( {environment.isElectron ? (
<SettingRow <SettingRow
name={t['com.affine.appearanceSettings.clientBorder.title']()} name={t['com.affine.appearanceSettings.clientBorder.title']()}
desc={t['com.affine.appearanceSettings.clientBorder.description']()} desc={t['com.affine.appearanceSettings.clientBorder.description']()}
@ -97,7 +97,7 @@ export const AppearanceSettings = () => {
/> />
</SettingRow> </SettingRow>
) : null} ) : null}
{runtimeConfig.enableNewSettingUnstableApi && environment.isDesktop ? ( {runtimeConfig.enableNewSettingUnstableApi && environment.isElectron ? (
<SettingRow <SettingRow
name={t['com.affine.appearanceSettings.windowFrame.title']()} name={t['com.affine.appearanceSettings.windowFrame.title']()}
desc={t['com.affine.appearanceSettings.windowFrame.description']()} desc={t['com.affine.appearanceSettings.windowFrame.description']()}
@ -141,7 +141,7 @@ export const AppearanceSettings = () => {
</SettingWrapper> </SettingWrapper>
) : null} ) : null}
{environment.isDesktop ? ( {environment.isElectron ? (
<SettingWrapper <SettingWrapper
title={t['com.affine.appearanceSettings.sidebar.title']()} title={t['com.affine.appearanceSettings.sidebar.title']()}
> >

View File

@ -13,7 +13,7 @@ export const ThemeEditorSetting = () => {
const modified = useLiveData(themeEditor.modified$); const modified = useLiveData(themeEditor.modified$);
const open = useCallback(() => { const open = useCallback(() => {
if (environment.isDesktop) { if (environment.isElectron) {
apis?.ui.openThemeEditor().catch(console.error); apis?.ui.openThemeEditor().catch(console.error);
} else { } else {
popupWindow('/theme-editor'); popupWindow('/theme-editor');

View File

@ -85,7 +85,7 @@ const FontFamilySettings = () => {
const radioItems = useMemo(() => { const radioItems = useMemo(() => {
const items = getBaseFontStyleOptions(t); const items = getBaseFontStyleOptions(t);
if (!environment.isDesktop) return items; if (!environment.isElectron) return items;
// resolve custom fonts // resolve custom fonts
const customOption = fontStyleOptions.find(opt => opt.key === 'Custom'); const customOption = fontStyleOptions.find(opt => opt.key === 'Custom');
@ -274,7 +274,7 @@ const CustomFontFamilySettings = () => {
}, },
[editorSettingService.editorSetting] [editorSettingService.editorSetting]
); );
if (settings.fontFamily !== 'Custom' || !environment.isDesktop) { if (settings.fontFamily !== 'Custom' || !environment.isElectron) {
return null; return null;
} }
return ( return (

View File

@ -67,7 +67,7 @@ export const WorkspaceSettingDetail = ({
<EnableCloudPanel /> <EnableCloudPanel />
<MembersPanel /> <MembersPanel />
</SettingWrapper> </SettingWrapper>
{environment.isDesktop && ( {environment.isElectron && (
<SettingWrapper title={t['Storage and Export']()}> <SettingWrapper title={t['Storage and Export']()}>
<ExportPanel <ExportPanel
workspace={workspace} workspace={workspace}

View File

@ -151,7 +151,7 @@ export const AFFiNESharePage = (props: ShareMenuProps) => {
} }
}, [shareInfoService, t]); }, [shareInfoService, t]);
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
const { onClickCopyLink } = useSharingUrl({ const { onClickCopyLink } = useSharingUrl({
workspaceId, workspaceId,

View File

@ -49,7 +49,7 @@ const SubscriptionChangedNotifyFooter = ({
); );
}; };
const isDesktop = environment.isDesktop; const isDesktop = environment.isElectron;
export const useUpgradeNotify = () => { export const useUpgradeNotify = () => {
const t = useI18n(); const t = useI18n();
const prevNotifyIdRef = useRef<string | number | null>(null); const prevNotifyIdRef = useRef<string | number | null>(null);

View File

@ -2,7 +2,7 @@ import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils'; import { atomWithStorage } from 'jotai/utils';
export const APP_SIDEBAR_OPEN = 'app-sidebar-open'; export const APP_SIDEBAR_OPEN = 'app-sidebar-open';
export const isMobile = window.innerWidth < 768 && !environment.isDesktop; export const isMobile = window.innerWidth < 768 && !environment.isElectron;
export const appSidebarOpenAtom = atomWithStorage(APP_SIDEBAR_OPEN, !isMobile); export const appSidebarOpenAtom = atomWithStorage(APP_SIDEBAR_OPEN, !isMobile);
export const appSidebarFloatingAtom = atom(isMobile); export const appSidebarFloatingAtom = atom(isMobile);

View File

@ -49,7 +49,7 @@ export function AppSidebar({
useEffect(() => { useEffect(() => {
// do not float app sidebar on desktop // do not float app sidebar on desktop
if (environment.isDesktop) { if (environment.isElectron) {
return; return;
} }
@ -79,8 +79,8 @@ export function AppSidebar({
}; };
}, [open, setFloating, setOpen, width]); }, [open, setFloating, setOpen, width]);
const hasRightBorder = !environment.isDesktop && !clientBorder; const hasRightBorder = !environment.isElectron && !clientBorder;
const isMacosDesktop = environment.isDesktop && environment.isMacOs; const isMacosDesktop = environment.isElectron && environment.isMacOs;
return ( return (
<> <>
<ResizePanel <ResizePanel
@ -105,7 +105,7 @@ export function AppSidebar({
data-client-border={clientBorder} data-client-border={clientBorder}
> >
<nav className={navStyle} data-testid="app-sidebar"> <nav className={navStyle} data-testid="app-sidebar">
{!environment.isDesktop && <SidebarHeader />} {!environment.isElectron && <SidebarHeader />}
<div className={navBodyStyle} data-testid="sliderBar-inner"> <div className={navBodyStyle} data-testid="sliderBar-inner">
{children} {children}
</div> </div>

View File

@ -13,7 +13,7 @@ interface QuickSearchInputProps extends HTMLAttributes<HTMLDivElement> {
// Although it is called an input, it is actually a button. // Although it is called an input, it is actually a button.
export function QuickSearchInput({ onClick, ...props }: QuickSearchInputProps) { export function QuickSearchInput({ onClick, ...props }: QuickSearchInputProps) {
const t = useI18n(); const t = useI18n();
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
return ( return (
<div <div

View File

@ -206,7 +206,7 @@ export const PageHeaderMenuButton = ({
setEditing(!isEditing); setEditing(!isEditing);
}, [isEditing, page.id, page.readonly, setDocReadonly]); }, [isEditing, page.id, page.readonly, setDocReadonly]);
const isMobile = environment.isBrowser && environment.isMobile; const isMobile = environment.isMobileEdition;
const mobileEditMenuItem = ( const mobileEditMenuItem = (
<MenuItem <MenuItem
prefixIcon={isEditing ? <SaveIcon /> : <EditIcon />} prefixIcon={isEditing ? <SaveIcon /> : <EditIcon />}
@ -293,7 +293,7 @@ export const PageHeaderMenuButton = ({
{t['com.affine.workbench.tab.page-menu-open']()} {t['com.affine.workbench.tab.page-menu-open']()}
</MenuItem> </MenuItem>
{environment.isDesktop && ( {environment.isElectron && (
<MenuItem <MenuItem
prefixIcon={<SplitViewIcon />} prefixIcon={<SplitViewIcon />}
data-testid="editor-option-menu-open-in-split-new" data-testid="editor-option-menu-open-in-split-new"

View File

@ -182,7 +182,7 @@ export const PageOperationCell = ({
{t['com.affine.workbench.tab.page-menu-open']()} {t['com.affine.workbench.tab.page-menu-open']()}
</MenuItem> </MenuItem>
{environment.isDesktop && enableSplitView ? ( {environment.isElectron && enableSplitView ? (
<MenuItem onClick={onOpenInSplitView} prefixIcon={<SplitViewIcon />}> <MenuItem onClick={onOpenInSplitView} prefixIcon={<SplitViewIcon />}>
{t['com.affine.workbench.split-view.page-menu-open']()} {t['com.affine.workbench.split-view.page-menu-open']()}
</MenuItem> </MenuItem>

View File

@ -156,7 +156,7 @@ export const CollectionOperations = ({
name: t['com.affine.workbench.tab.page-menu-open'](), name: t['com.affine.workbench.tab.page-menu-open'](),
click: openCollectionNewTab, click: openCollectionNewTab,
}, },
...(enableMultiView && environment.isDesktop ...(enableMultiView && environment.isElectron
? [ ? [
{ {
icon: <SplitViewIcon />, icon: <SplitViewIcon />,

View File

@ -29,7 +29,7 @@ const DEFAULT_SHOW_LIST: IslandItemNames[] = [
const DESKTOP_SHOW_LIST: IslandItemNames[] = [...DEFAULT_SHOW_LIST]; const DESKTOP_SHOW_LIST: IslandItemNames[] = [...DEFAULT_SHOW_LIST];
type IslandItemNames = 'whatNew' | 'contact' | 'shortcuts'; type IslandItemNames = 'whatNew' | 'contact' | 'shortcuts';
const showList = environment.isDesktop ? DESKTOP_SHOW_LIST : DEFAULT_SHOW_LIST; const showList = environment.isElectron ? DESKTOP_SHOW_LIST : DEFAULT_SHOW_LIST;
export const HelpIsland = () => { export const HelpIsland = () => {
const { globalContextService } = useServices({ const { globalContextService } = useServices({

View File

@ -112,7 +112,7 @@ export const RootAppSidebar = (): ReactElement => {
); );
useEffect(() => { useEffect(() => {
if (environment.isDesktop) { if (environment.isElectron) {
return events?.applicationMenu.onNewPageAction(() => { return events?.applicationMenu.onNewPageAction(() => {
apis?.ui apis?.ui
.isActiveTab() .isActiveTab()
@ -206,7 +206,7 @@ export const RootAppSidebar = (): ReactElement => {
</div> </div>
</SidebarScrollableContainer> </SidebarScrollableContainer>
<SidebarContainer> <SidebarContainer>
{environment.isDesktop ? <UpdaterButton /> : <AppDownloadButton />} {environment.isElectron ? <UpdaterButton /> : <AppDownloadButton />}
</SidebarContainer> </SidebarContainer>
</AppSidebar> </AppSidebar>
); );

View File

@ -12,19 +12,15 @@ import { AuthService } from '../modules/cloud';
const minimumChromeVersion = 106; const minimumChromeVersion = 106;
const shouldShowWarning = (() => { const shouldShowWarning = (() => {
if (environment.isDesktop) { if (environment.isElectron) {
// even though desktop has compatibility issues, // even though desktop has compatibility issues,
// we don't want to show the warning // we don't want to show the warning
return false; return false;
} }
if (!environment.isBrowser) {
// disable in SSR
return false;
}
if (environment.isMobile) { if (environment.isMobile) {
return true; return true;
} }
if (environment.isChrome) { if (environment.isChrome && environment.chromeVersion) {
return environment.chromeVersion < minimumChromeVersion; return environment.chromeVersion < minimumChromeVersion;
} }
return false; return false;
@ -32,14 +28,14 @@ const shouldShowWarning = (() => {
const OSWarningMessage = () => { const OSWarningMessage = () => {
const t = useI18n(); const t = useI18n();
const notChrome = environment.isBrowser && !environment.isChrome; const notChrome = !environment.isChrome;
const notGoodVersion = const notGoodVersion =
environment.isBrowser &&
environment.isChrome && environment.isChrome &&
environment.chromeVersion &&
environment.chromeVersion < minimumChromeVersion; environment.chromeVersion < minimumChromeVersion;
// TODO(@L-Sun): remove this message when mobile version is able to edit. // TODO(@L-Sun): remove this message when mobile version is able to edit.
if ('isMobile' in environment && environment.isMobile) { if (environment.isMobile) {
return <span>{t['com.affine.top-tip.mobile']()}</span>; return <span>{t['com.affine.top-tip.mobile']()}</span>;
} }
@ -80,7 +76,7 @@ export const TopTip = ({
if ( if (
showLocalDemoTips && showLocalDemoTips &&
!environment.isDesktop && !environment.isElectron &&
workspace.flavour === WorkspaceFlavour.LOCAL workspace.flavour === WorkspaceFlavour.LOCAL
) { ) {
return ( return (

View File

@ -15,7 +15,7 @@ export const AddWorkspace = ({
return ( return (
<div> <div>
{environment.isDesktop ? ( {environment.isElectron ? (
<MenuItem <MenuItem
block={true} block={true}
prefixIcon={<ImportIcon />} prefixIcon={<ImportIcon />}

View File

@ -60,7 +60,7 @@ const UnSyncWorkspaceStatus = () => {
const LocalWorkspaceStatus = () => { const LocalWorkspaceStatus = () => {
return ( return (
<> <>
{!environment.isDesktop ? ( {!environment.isElectron ? (
<InformationFillDuotoneIcon style={{ color: cssVar('errorColor') }} /> <InformationFillDuotoneIcon style={{ color: cssVar('errorColor') }} />
) : ( ) : (
<LocalWorkspaceIcon /> <LocalWorkspaceIcon />
@ -98,7 +98,7 @@ const useSyncEngineSyncProgress = (meta: WorkspaceMetadata) => {
let content; let content;
// TODO(@eyhn): add i18n // TODO(@eyhn): add i18n
if (workspace.flavour === WorkspaceFlavour.LOCAL) { if (workspace.flavour === WorkspaceFlavour.LOCAL) {
if (!environment.isDesktop) { if (!environment.isElectron) {
content = 'This is a local demo workspace.'; content = 'This is a local demo workspace.';
} else { } else {
content = 'Saved locally'; content = 'Saved locally';

View File

@ -26,8 +26,8 @@ export const AppContainer = ({
children, children,
...rest ...rest
}: WorkspaceRootProps) => { }: WorkspaceRootProps) => {
const noisyBackground = useNoisyBackground && environment.isDesktop; const noisyBackground = useNoisyBackground && environment.isElectron;
const blurBackground = environment.isDesktop && useBlurBackground; const blurBackground = environment.isElectron && useBlurBackground;
return ( return (
<div <div
{...rest} {...rest}
@ -57,7 +57,7 @@ export const MainContainer = forwardRef<
<div <div
{...props} {...props}
className={clsx(mainContainerStyle, className)} className={clsx(mainContainerStyle, className)}
data-is-desktop={environment.isDesktop} data-is-desktop={environment.isElectron}
data-transparent={false} data-transparent={false}
data-client-border={appSettings.clientBorder} data-client-border={appSettings.clientBorder}
data-side-bar-open={appSideBarOpen} data-side-bar-open={appSideBarOpen}

View File

@ -18,7 +18,7 @@ export function useRegisterFindInPageCommands() {
}, [findInPage]); }, [findInPage]);
useEffect(() => { useEffect(() => {
if (!environment.isDesktop) { if (!environment.isElectron) {
return; return;
} }
const unsubs: Array<() => void> = []; const unsubs: Array<() => void> = [];

View File

@ -284,7 +284,7 @@ export const useMarkdownShortcuts = (): ShortcutsInfo => {
const macMarkdownShortcuts = useMacMarkdownShortcuts(); const macMarkdownShortcuts = useMacMarkdownShortcuts();
const winMarkdownShortcuts = useWinMarkdownShortcuts(); const winMarkdownShortcuts = useWinMarkdownShortcuts();
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
return { return {
title: t['com.affine.shortcutsTitle.markdownSyntax'](), title: t['com.affine.shortcutsTitle.markdownSyntax'](),
shortcuts: isMac ? macMarkdownShortcuts : winMarkdownShortcuts, shortcuts: isMac ? macMarkdownShortcuts : winMarkdownShortcuts,
@ -296,7 +296,7 @@ export const usePageShortcuts = (): ShortcutsInfo => {
const macPageShortcuts = useMacPageKeyboardShortcuts(); const macPageShortcuts = useMacPageKeyboardShortcuts();
const winPageShortcuts = useWinPageKeyboardShortcuts(); const winPageShortcuts = useWinPageKeyboardShortcuts();
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
return { return {
title: t['com.affine.shortcutsTitle.page'](), title: t['com.affine.shortcutsTitle.page'](),
shortcuts: isMac ? macPageShortcuts : winPageShortcuts, shortcuts: isMac ? macPageShortcuts : winPageShortcuts,
@ -308,7 +308,7 @@ export const useEdgelessShortcuts = (): ShortcutsInfo => {
const macEdgelessShortcuts = useMacEdgelessKeyboardShortcuts(); const macEdgelessShortcuts = useMacEdgelessKeyboardShortcuts();
const winEdgelessShortcuts = useWinEdgelessKeyboardShortcuts(); const winEdgelessShortcuts = useWinEdgelessKeyboardShortcuts();
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
return { return {
title: t['com.affine.shortcutsTitle.edgeless'](), title: t['com.affine.shortcutsTitle.edgeless'](),
shortcuts: isMac ? macEdgelessShortcuts : winEdgelessShortcuts, shortcuts: isMac ? macEdgelessShortcuts : winEdgelessShortcuts,
@ -320,7 +320,7 @@ export const useGeneralShortcuts = (): ShortcutsInfo => {
const macGeneralShortcuts = useMacGeneralKeyboardShortcuts(); const macGeneralShortcuts = useMacGeneralKeyboardShortcuts();
const winGeneralShortcuts = useWinGeneralKeyboardShortcuts(); const winGeneralShortcuts = useWinGeneralKeyboardShortcuts();
const isMac = environment.isBrowser && environment.isMacOs; const isMac = environment.isMacOs;
return { return {
title: t['com.affine.shortcutsTitle.general'](), title: t['com.affine.shortcutsTitle.general'](),
shortcuts: isMac ? macGeneralShortcuts : winGeneralShortcuts, shortcuts: isMac ? macGeneralShortcuts : winGeneralShortcuts,

View File

@ -35,7 +35,7 @@ export const appConfigProxy = new AppConfigProxy();
setupGlobal(); setupGlobal();
const storage = environment.isDesktop const storage = environment.isElectron
? new AppConfigStorage({ ? new AppConfigStorage({
config: defaultAppConfig, config: defaultAppConfig,
get: () => appConfigProxy.get(), get: () => appConfigProxy.get(),

View File

@ -1,6 +1,5 @@
import type { UpdateMeta } from '@affine/electron-api'; import type { UpdateMeta } from '@affine/electron-api';
import { apis, events } from '@affine/electron-api'; import { apis, events } from '@affine/electron-api';
import { isBrowser } from '@affine/env/constant';
import { appSettingAtom } from '@toeverything/infra'; import { appSettingAtom } from '@toeverything/infra';
import { atom, useAtom, useAtomValue } from 'jotai'; import { atom, useAtom, useAtomValue } from 'jotai';
import { atomWithObservable, atomWithStorage } from 'jotai/utils'; import { atomWithObservable, atomWithStorage } from 'jotai/utils';
@ -30,7 +29,7 @@ function rpcToObservable<
return new Observable<T | null>(subscriber => { return new Observable<T | null>(subscriber => {
subscriber.next(initialValue); subscriber.next(initialValue);
onSubscribe?.(); onSubscribe?.();
if (!isBrowser || !environment.isDesktop || !event) { if (!environment.isElectron || !event) {
subscriber.complete(); subscriber.complete();
return; return;
} }
@ -76,18 +75,12 @@ export const changelogCheckedAtom = atomWithStorage<Record<string, boolean>>(
export const checkingForUpdatesAtom = atom(false); export const checkingForUpdatesAtom = atom(false);
export const currentVersionAtom = atom(async () => { export const currentVersionAtom = atom(async () => {
if (!isBrowser) {
return null;
}
const currentVersion = await apis?.updater.currentVersion(); const currentVersion = await apis?.updater.currentVersion();
return currentVersion; return currentVersion;
}); });
const currentChangelogUnreadAtom = atom( const currentChangelogUnreadAtom = atom(
async get => { async get => {
if (!isBrowser) {
return false;
}
const mapping = get(changelogCheckedAtom); const mapping = get(changelogCheckedAtom);
const currentVersion = await get(currentVersionAtom); const currentVersion = await get(currentVersionAtom);
if (currentVersion) { if (currentVersion) {

View File

@ -3,7 +3,7 @@ import { useEffect } from 'react';
export function useDocumentTitle(newTitle?: string | null) { export function useDocumentTitle(newTitle?: string | null) {
useEffect(() => { useEffect(() => {
if (environment.isDesktop || !newTitle) { if (environment.isElectron || !newTitle) {
return noop; return noop;
} }

View File

@ -223,7 +223,9 @@ const WorkspaceLayoutUIContainer = ({ children }: PropsWithChildren) => {
); );
const resizing = useAtomValue(appSidebarResizingAtom); const resizing = useAtomValue(appSidebarResizingAtom);
const LayoutComponent = environment.isDesktop ? DesktopLayout : BrowserLayout; const LayoutComponent = environment.isElectron
? DesktopLayout
: BrowserLayout;
return ( return (
<AppContainer data-current-path={currentPath} resizing={resizing}> <AppContainer data-current-path={currentPath} resizing={resizing}>

View File

@ -36,7 +36,7 @@ function createMixpanel() {
environment: runtimeConfig.appBuildType, environment: runtimeConfig.appBuildType,
editorVersion: runtimeConfig.editorVersion, editorVersion: runtimeConfig.editorVersion,
isSelfHosted: Boolean(runtimeConfig.isSelfHosted), isSelfHosted: Boolean(runtimeConfig.isSelfHosted),
isDesktop: environment.isDesktop, isDesktop: environment.isElectron,
}); });
}, },
reset() { reset() {

View File

@ -304,7 +304,7 @@ export const AppTabsHeader = ({
const sidebarWidth = useAtomValue(appSidebarWidthAtom); const sidebarWidth = useAtomValue(appSidebarWidthAtom);
const sidebarOpen = useAtomValue(appSidebarOpenAtom); const sidebarOpen = useAtomValue(appSidebarOpenAtom);
const sidebarResizing = useAtomValue(appSidebarResizingAtom); const sidebarResizing = useAtomValue(appSidebarResizingAtom);
const isMacosDesktop = environment.isDesktop && environment.isMacOs; const isMacosDesktop = environment.isElectron && environment.isMacOs;
const fullScreen = useIsFullScreen(); const fullScreen = useIsFullScreen();
const tabsHeaderService = useService(AppTabsHeaderService); const tabsHeaderService = useService(AppTabsHeaderService);
@ -413,7 +413,7 @@ export const AppTabsHeader = ({
className={clsx(styles.root, className)} className={clsx(styles.root, className)}
style={style} style={style}
data-mode={mode} data-mode={mode}
data-is-windows={environment.isDesktop && environment.isWindows} data-is-windows={environment.isElectron && environment.isWindows}
> >
<div <div
style={{ style={{
@ -474,7 +474,7 @@ export const AppTabsHeader = ({
<IconButton size="24" onClick={onToggleRightSidebar}> <IconButton size="24" onClick={onToggleRightSidebar}>
<RightSidebarIcon /> <RightSidebarIcon />
</IconButton> </IconButton>
{environment.isDesktop && environment.isWindows ? ( {environment.isElectron && environment.isWindows ? (
<WindowsAppControls /> <WindowsAppControls />
) : null} ) : null}
</div> </div>

View File

@ -88,7 +88,7 @@ export class AuthService extends Service {
email, email,
// we call it [callbackUrl] instead of [redirect_uri] // we call it [callbackUrl] instead of [redirect_uri]
// to make it clear the url is used to finish the sign-in process instead of redirect after signed-in // to make it clear the url is used to finish the sign-in process instead of redirect after signed-in
callbackUrl: `/magic-link?client=${environment.isDesktop ? appInfo?.schema : 'web'}`, callbackUrl: `/magic-link?client=${environment.isElectron ? appInfo?.schema : 'web'}`,
}), }),
headers: { headers: {
'content-type': 'application/json', 'content-type': 'application/json',
@ -131,7 +131,7 @@ export class AuthService extends Service {
'state', 'state',
JSON.stringify({ JSON.stringify({
state: oauthUrl.searchParams.get('state'), state: oauthUrl.searchParams.get('state'),
client: environment.isDesktop ? appInfo?.schema : 'web', client: environment.isElectron ? appInfo?.schema : 'web',
}) })
); );
url = oauthUrl.toString(); url = oauthUrl.toString();

View File

@ -5,7 +5,7 @@ import { fromPromise, Service } from '@toeverything/infra';
import { BackendError, NetworkError } from '../error'; import { BackendError, NetworkError } from '../error';
export function getAffineCloudBaseUrl(): string { export function getAffineCloudBaseUrl(): string {
if (environment.isDesktop) { if (environment.isElectron) {
return runtimeConfig.serverUrlPrefix; return runtimeConfig.serverUrlPrefix;
} }
const { protocol, hostname, port } = window.location; const { protocol, hostname, port } = window.location;

View File

@ -28,7 +28,7 @@ const getDefaultSubscriptionSuccessCallbackLink = (
plan === SubscriptionPlan.AI ? '/ai-upgrade-success' : '/upgrade-success'; plan === SubscriptionPlan.AI ? '/ai-upgrade-success' : '/upgrade-success';
const urlString = getAffineCloudBaseUrl() + path; const urlString = getAffineCloudBaseUrl() + path;
const url = new URL(urlString); const url = new URL(urlString);
if (environment.isDesktop && appInfo) { if (environment.isElectron && appInfo) {
url.searchParams.set('schema', appInfo.schema); url.searchParams.set('schema', appInfo.schema);
} }
return url.toString(); return url.toString();

View File

@ -183,7 +183,7 @@ export const useExplorerCollectionNodeOperations = (
</MenuItem> </MenuItem>
), ),
}, },
...(environment.isDesktop && enableMultiView ...(environment.isElectron && enableMultiView
? [ ? [
{ {
index: 99, index: 99,

View File

@ -181,7 +181,7 @@ export const useExplorerDocNodeOperations = (
</MenuItem> </MenuItem>
), ),
}, },
...(enableMultiView && environment.isDesktop ...(enableMultiView && environment.isElectron
? [ ? [
{ {
index: 100, index: 100,

View File

@ -119,7 +119,7 @@ export const useExplorerTagNodeOperations = (
</MenuItem> </MenuItem>
), ),
}, },
...(enableMultiView && environment.isDesktop ...(enableMultiView && environment.isElectron
? [ ? [
{ {
index: 100, index: 100,

View File

@ -40,7 +40,7 @@ export class Navigator extends Entity {
); );
back() { back() {
if (!environment.isDesktop) { if (!environment.isElectron) {
window.history.back(); window.history.back();
} else { } else {
this.history$.value.back(); this.history$.value.back();
@ -48,7 +48,7 @@ export class Navigator extends Entity {
} }
forward() { forward() {
if (!environment.isDesktop) { if (!environment.isElectron) {
window.history.forward(); window.history.forward();
} else { } else {
this.history$.value.forward(); this.history$.value.forward();

View File

@ -44,7 +44,7 @@ export const NavigationButtons = () => {
}; };
}, [navigator]); }, [navigator]);
if (!environment.isDesktop) { if (!environment.isElectron) {
return null; return null;
} }

View File

@ -125,7 +125,7 @@ export const DocPeekViewControls = ({
peekView.close('none'); peekView.close('none');
}, },
}, },
environment.isDesktop && { environment.isElectron && {
icon: <SplitViewIcon />, icon: <SplitViewIcon />,
nameKey: 'split-view', nameKey: 'split-view',
name: t['com.affine.peek-view-controls.open-doc-in-split-view'](), name: t['com.affine.peek-view-controls.open-doc-in-split-view'](),

View File

@ -283,7 +283,7 @@ export const CMDKGroup = ({
}; };
const CMDKKeyBinding = ({ keyBinding }: { keyBinding: string }) => { const CMDKKeyBinding = ({ keyBinding }: { keyBinding: string }) => {
const isMacOS = environment.isBrowser && environment.isMacOs; const isMacOS = environment.isMacOs;
const fragments = useMemo(() => { const fragments = useMemo(() => {
return keyBinding.split('+').map(fragment => { return keyBinding.split('+').map(fragment => {
if (fragment === '$mod') { if (fragment === '$mod') {

View File

@ -13,7 +13,7 @@ export class DesktopStateSynchronizer extends Service {
} }
startSync = () => { startSync = () => {
if (!environment.isDesktop) { if (!environment.isElectron) {
return; return;
} }

View File

@ -54,7 +54,7 @@ export const RouteContainer = () => {
return ( return (
<div className={styles.root}> <div className={styles.root}>
<div className={styles.header}> <div className={styles.header}>
{viewPosition.isFirst && !environment.isDesktop && ( {viewPosition.isFirst && !environment.isElectron && (
<SidebarSwitch <SidebarSwitch
show={!leftSidebarOpen} show={!leftSidebarOpen}
className={styles.leftSidebarButton} className={styles.leftSidebarButton}
@ -64,7 +64,7 @@ export const RouteContainer = () => {
viewId={view.id} viewId={view.id}
className={styles.viewHeaderContainer} className={styles.viewHeaderContainer}
/> />
{viewPosition.isLast && !environment.isDesktop && ( {viewPosition.isLast && !environment.isElectron && (
<ToggleButton <ToggleButton
show={!sidebarOpen} show={!sidebarOpen}
className={styles.rightSidebarButton} className={styles.rightSidebarButton}

View File

@ -38,7 +38,7 @@ export const SidebarContainer = ({
viewId={view.id} viewId={view.id}
className={clsx( className={clsx(
styles.sidebarBodyTarget, styles.sidebarBodyTarget,
!environment.isDesktop && styles.borderTop !environment.isElectron && styles.borderTop
)} )}
/> />
)) ))

View File

@ -44,7 +44,7 @@ export const Header = ({ floating, children, onToggle }: HeaderProps) => {
return ( return (
<Container className={styles.header} floating={floating}> <Container className={styles.header} floating={floating}>
{children} {children}
{!environment.isDesktop && ( {!environment.isElectron && (
<> <>
<div className={styles.spacer} /> <div className={styles.spacer} />
<ToggleButton onToggle={onToggle} /> <ToggleButton onToggle={onToggle} />

View File

@ -40,7 +40,7 @@ export const WorkbenchLink = forwardRef<HTMLAnchorElement, WorkbenchLinkProps>(
} }
const at = (() => { const at = (() => {
if (isNewTabTrigger(event)) { if (isNewTabTrigger(event)) {
return event.altKey && enableMultiView && environment.isDesktop return event.altKey && enableMultiView && environment.isElectron
? 'tail' ? 'tail'
: 'new-tab'; : 'new-tab';
} }

View File

@ -22,7 +22,7 @@ import { ViewIslandRegistryProvider } from './view-islands';
import { ViewRoot } from './view-root'; import { ViewRoot } from './view-root';
import * as styles from './workbench-root.css'; import * as styles from './workbench-root.css';
const useAdapter = environment.isDesktop const useAdapter = environment.isElectron
? useBindWorkbenchToDesktopRouter ? useBindWorkbenchToDesktopRouter
: useBindWorkbenchToBrowserRouter; : useBindWorkbenchToBrowserRouter;

View File

@ -47,7 +47,7 @@ export class LocalWorkspaceFlavourProvider
JSON.stringify(allWorkspaceIDs.filter(x => x !== id)) JSON.stringify(allWorkspaceIDs.filter(x => x !== id))
); );
if (apis && environment.isDesktop) { if (apis && environment.isElectron) {
await apis.workspace.delete(id); await apis.workspace.delete(id);
} }

View File

@ -20,7 +20,7 @@ export const SignIn = () => {
const isLoggedIn = status === 'authenticated' && !isRevalidating; const isLoggedIn = status === 'authenticated' && !isRevalidating;
useEffect(() => { useEffect(() => {
if (environment.isDesktop && appInfo?.windowName === 'hidden-window') { if (environment.isElectron && appInfo?.windowName === 'hidden-window') {
return; return;
} }

View File

@ -11,7 +11,7 @@ import {
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper'; import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
export const loader = () => { export const loader = () => {
if (!environment.isDesktop && !appConfigStorage.get('onBoarding')) { if (!environment.isElectron && !appConfigStorage.get('onBoarding')) {
// onboarding is off, redirect to index // onboarding is off, redirect to index
return redirect('/'); return redirect('/');
} }
@ -24,7 +24,7 @@ export const Component = () => {
const [, setOnboarding] = useAppConfigStorage('onBoarding'); const [, setOnboarding] = useAppConfigStorage('onBoarding');
const openApp = useCallback(() => { const openApp = useCallback(() => {
if (environment.isDesktop) { if (environment.isElectron) {
assertExists(apis); assertExists(apis);
apis.ui.handleOpenMainApp().catch(err => { apis.ui.handleOpenMainApp().catch(err => {
console.log('failed to open main app', err); console.log('failed to open main app', err);

View File

@ -258,7 +258,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
); );
const [refCallback, hasScrollTop] = useHasScrollTop(); const [refCallback, hasScrollTop] = useHasScrollTop();
const dynamicTopBorder = environment.isDesktop; const dynamicTopBorder = environment.isElectron;
const openOutlinePanel = useCallback(() => { const openOutlinePanel = useCallback(() => {
workbench.openSidebar(); workbench.openSidebar();

View File

@ -23,7 +23,7 @@ export const useDetailPageHeaderResponsive = (availableWidth: number) => {
viewPosition.isLast && viewPosition.isLast &&
!rightSidebarOpen && !rightSidebarOpen &&
!(hidePresent && hideShare) && !(hidePresent && hideShare) &&
!environment.isDesktop; !environment.isElectron;
return { return {
hideShare, hideShare,

View File

@ -99,7 +99,7 @@ export const Component = (): ReactElement => {
if (workspaceNotFound) { if (workspaceNotFound) {
if ( if (
detailDocRoute /* */ && detailDocRoute /* */ &&
!environment.isDesktop /* only browser has share page */ !environment.isElectron /* only browser has share page */
) { ) {
return ( return (
<SharePage <SharePage

View File

@ -26,7 +26,7 @@ export const EmptyPageList = ({
icon={<PlusIcon />} icon={<PlusIcon />}
/> />
); );
if (environment.isDesktop) { if (environment.isElectron) {
const shortcut = environment.isMacOs ? '⌘ + N' : 'Ctrl + N'; const shortcut = environment.isMacOs ? '⌘ + N' : 'Ctrl + N';
return ( return (
<Trans i18nKey="emptyAllPagesClient"> <Trans i18nKey="emptyAllPagesClient">

View File

@ -63,7 +63,7 @@ export const Setting = () => {
); );
useEffect(() => { useEffect(() => {
if (environment.isDesktop) { if (environment.isElectron) {
return events?.applicationMenu.openAboutPageInSettingModal(() => return events?.applicationMenu.openAboutPageInSettingModal(() =>
setOpenSettingModalAtom({ setOpenSettingModalAtom({
activeTab: 'about', activeTab: 'about',
@ -123,7 +123,7 @@ export function CurrentWorkspaceModals() {
)} )}
<AiLoginRequiredModal /> <AiLoginRequiredModal />
<PeekViewManagerModal /> <PeekViewManagerModal />
{environment.isDesktop && <FindInPageModal />} {environment.isElectron && <FindInPageModal />}
<MoveToTrash.ConfirmModal <MoveToTrash.ConfirmModal
open={trashConfirmOpen} open={trashConfirmOpen}
onConfirm={handleOnConfirm} onConfirm={handleOnConfirm}

View File

@ -1,15 +1,10 @@
import { isBrowser } from '@affine/env/constant';
import createCache from '@emotion/cache'; import createCache from '@emotion/cache';
export default function createEmotionCache() { export default function createEmotionCache() {
let insertionPoint; const emotionInsertionPoint = document.querySelector<HTMLMetaElement>(
'meta[name="emotion-insertion-point"]'
if (isBrowser) { );
const emotionInsertionPoint = document.querySelector<HTMLMetaElement>( const insertionPoint = emotionInsertionPoint ?? undefined;
'meta[name="emotion-insertion-point"]'
);
insertionPoint = emotionInsertionPoint ?? undefined;
}
return createCache({ key: 'affine', insertionPoint }); return createCache({ key: 'affine', insertionPoint });
} }

View File

@ -42,7 +42,7 @@ const desktopWhiteList = [
'/magic-link', '/magic-link',
]; ];
if ( if (
!environment.isDesktop && !environment.isElectron &&
environment.isDebug && environment.isDebug &&
desktopWhiteList.every(path => !location.pathname.startsWith(path)) desktopWhiteList.every(path => !location.pathname.startsWith(path))
) { ) {

View File

@ -6,7 +6,7 @@ import * as styles from './shell.css';
export function ShellRoot() { export function ShellRoot() {
const { appSettings } = useAppSettingHelper(); const { appSettings } = useAppSettingHelper();
const translucent = const translucent =
environment.isDesktop && environment.isElectron &&
environment.isMacOs && environment.isMacOs &&
appSettings.enableBlurBackground; appSettings.enableBlurBackground;
return ( return (

View File

@ -10,7 +10,7 @@ import { gqlFetcherFactory } from './fetcher';
setupGlobal(); setupGlobal();
export function getBaseUrl(): string { export function getBaseUrl(): string {
if (environment.isDesktop) { if (environment.isElectron) {
return runtimeConfig.serverUrlPrefix; return runtimeConfig.serverUrlPrefix;
} }
if (typeof window === 'undefined') { if (typeof window === 'undefined') {

View File

@ -29,7 +29,7 @@ import { RouterProvider } from 'react-router-dom';
import { configureMobileModules } from './modules'; import { configureMobileModules } from './modules';
import { router } from './router'; import { router } from './router';
if (!environment.isBrowser && environment.isDebug) { if (environment.isElectron && environment.isDebug) {
document.body.innerHTML = `<h1 style="color:red;font-size:5rem;text-align:center;">Don't run web entry in electron.</h1>`; document.body.innerHTML = `<h1 style="color:red;font-size:5rem;text-align:center;">Don't run web entry in electron.</h1>`;
throw new Error('Wrong distribution'); throw new Error('Wrong distribution');
} }

View File

@ -31,7 +31,7 @@ import type { PropsWithChildren, ReactElement } from 'react';
import { lazy, Suspense } from 'react'; import { lazy, Suspense } from 'react';
import { RouterProvider } from 'react-router-dom'; import { RouterProvider } from 'react-router-dom';
if (!environment.isBrowser && environment.isDebug) { if (environment.isElectron && environment.isDebug) {
document.body.innerHTML = `<h1 style="color:red;font-size:5rem;text-align:center;">Don't run web entry in electron.</h1>`; document.body.innerHTML = `<h1 style="color:red;font-size:5rem;text-align:center;">Don't run web entry in electron.</h1>`;
throw new Error('Wrong distribution'); throw new Error('Wrong distribution');
} }

View File

@ -6,7 +6,6 @@ import '@affine/core/bootstrap/preload';
import { performanceLogger } from '@affine/core/shared'; import { performanceLogger } from '@affine/core/shared';
import { appInfo } from '@affine/electron-api'; import { appInfo } from '@affine/electron-api';
import { isDesktop } from '@affine/env/constant';
import { import {
init, init,
reactRouterV6BrowserTracingIntegration, reactRouterV6BrowserTracingIntegration,
@ -28,7 +27,7 @@ function main() {
performanceMainLogger.info('start'); performanceMainLogger.info('start');
// skip bootstrap setup for desktop onboarding // skip bootstrap setup for desktop onboarding
if (isDesktop && appInfo?.windowName === 'onboarding') { if (environment.isElectron && appInfo?.windowName === 'onboarding') {
performanceMainLogger.info('skip setup'); performanceMainLogger.info('skip setup');
} else { } else {
performanceMainLogger.info('setup start'); performanceMainLogger.info('setup start');

View File

@ -7,6 +7,7 @@ export function getRuntimeConfig(buildFlags: BuildFlags): RuntimeConfig {
const buildPreset: Record<BuildFlags['channel'], RuntimeConfig> = { const buildPreset: Record<BuildFlags['channel'], RuntimeConfig> = {
get stable() { get stable() {
return { return {
distribution: buildFlags.distribution,
appBuildType: 'stable' as const, appBuildType: 'stable' as const,
serverUrlPrefix: 'https://app.affine.pro', serverUrlPrefix: 'https://app.affine.pro',
appVersion: packageJson.version, appVersion: packageJson.version,