mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-14 08:36:22 +08:00
refactor(core): adjust core struct (#8218)
packages/frontend/core/src hooks -> components/hooks atoms -> components/atoms layouts -> components/layouts providers -> components/providers mixpanel -> @affine/track ~~shared~~ ~~unexpected-application-state~~
This commit is contained in:
+1
-6
@@ -10,17 +10,12 @@ import { DumpInfo } from './error-basic/info-logger';
|
||||
import { AnyErrorFallback } from './error-fallbacks/any-error-fallback';
|
||||
import { NoPageRootFallback } from './error-fallbacks/no-page-root-fallback';
|
||||
import { PageNotFoundDetail } from './error-fallbacks/page-not-found-fallback';
|
||||
import { RecoverableErrorFallback } from './error-fallbacks/recoverable-error-fallback';
|
||||
|
||||
/**
|
||||
* Register all fallback components here.
|
||||
* If have new one just add it to the set.
|
||||
*/
|
||||
const fallbacks = new Set([
|
||||
PageNotFoundDetail,
|
||||
RecoverableErrorFallback,
|
||||
NoPageRootFallback,
|
||||
]);
|
||||
const fallbacks = new Set([PageNotFoundDetail, NoPageRootFallback]);
|
||||
|
||||
function getErrorFallbackComponent(error: any): FC<FallbackProps> {
|
||||
for (const Component of fallbacks) {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { useTheme } from 'next-themes';
|
||||
import type { FC, PropsWithChildren, ReactNode } from 'react';
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { useCallback } from 'react';
|
||||
import {
|
||||
RouteLogic,
|
||||
useNavigateHelper,
|
||||
} from '../../../../hooks/use-navigate-helper';
|
||||
} from '../../../../components/hooks/use-navigate-helper';
|
||||
import { ErrorDetail, ErrorStatus } from '../error-basic/error-detail';
|
||||
import { createErrorFallback } from '../error-basic/fallback-creator';
|
||||
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { RecoverableError } from '../../../../unexpected-application-state/errors';
|
||||
import { ContactUS, ErrorDetail } from '../error-basic/error-detail';
|
||||
import { createErrorFallback } from '../error-basic/fallback-creator';
|
||||
|
||||
export const RecoverableErrorFallback = createErrorFallback(
|
||||
RecoverableError,
|
||||
props => {
|
||||
const { error, resetError } = props;
|
||||
const t = useI18n();
|
||||
const [count, rerender] = useState(0);
|
||||
|
||||
const canRetry = error.canRetry();
|
||||
const buttonDesc = useMemo(() => {
|
||||
if (canRetry) {
|
||||
return t['com.affine.error.refetch']();
|
||||
}
|
||||
return t['com.affine.error.reload']();
|
||||
}, [canRetry, t]);
|
||||
const onRetry = useCallback(async () => {
|
||||
if (canRetry) {
|
||||
rerender(count + 1);
|
||||
await error.retry();
|
||||
} else {
|
||||
document.location.reload();
|
||||
}
|
||||
}, [error, count, canRetry]);
|
||||
|
||||
return (
|
||||
<ErrorDetail
|
||||
title={t['com.affine.error.unexpected-error.title']()}
|
||||
resetError={resetError}
|
||||
buttonText={buttonDesc}
|
||||
onButtonClick={onRetry}
|
||||
description={[error.message, <ContactUS key="contact-us" />]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Button, FlexWrapper, notify } from '@affine/component';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { AiIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Button, IconButton, Modal } from '@affine/component';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useBlurRoot } from '@affine/core/hooks/use-blur-root';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import { useBlurRoot } from '@affine/core/components/hooks/use-blur-root';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { ArrowLeftSmallIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Button, notify } from '@affine/component';
|
||||
import {
|
||||
RouteLogic,
|
||||
useNavigateHelper,
|
||||
} from '@affine/core/hooks/use-navigate-helper';
|
||||
} from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { AiIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import type { PropsWithChildren, ReactElement } from 'react';
|
||||
|
||||
import { useAppSettingHelper } from '../../hooks/affine/use-app-setting-helper';
|
||||
import { useAppSettingHelper } from '../../components/hooks/affine/use-app-setting-helper';
|
||||
import { AppSidebarFallback, ShellAppSidebarFallback } from '../app-sidebar';
|
||||
import type { WorkspaceRootProps } from '../workspace';
|
||||
import {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
ModalHeader,
|
||||
} from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { useService } from '@toeverything/infra';
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
ModalHeader,
|
||||
} from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import type { FC } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useConfirmModal } from '@affine/component';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { authAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { atom, useAtom, useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { notify } from '@affine/component';
|
||||
import { AuthModal as AuthModalBase } from '@affine/component/auth-components';
|
||||
import { authAtom, type AuthAtomData } from '@affine/core/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { authAtom, type AuthAtomData } from '@affine/core/components/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { apis, events } from '@affine/electron-api';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
ModalHeader,
|
||||
} from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import {
|
||||
sendChangeEmailMutation,
|
||||
sendChangePasswordEmailMutation,
|
||||
@@ -17,7 +17,7 @@ import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { useMutation } from '../../../hooks/use-mutation';
|
||||
import { useMutation } from '../../../components/hooks/use-mutation';
|
||||
import { ServerConfigService } from '../../../modules/cloud';
|
||||
import type { AuthPanelProps } from './index';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
ModalHeader,
|
||||
} from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useService } from '@toeverything/infra';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { notify } from '@affine/component';
|
||||
import { AuthInput, ModalHeader } from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { ArrowRightBigIcon } from '@blocksuite/icons/rc';
|
||||
import { useService } from '@toeverything/infra';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { useCatchEventCallback } from '@affine/core/hooks/use-catch-event-hook';
|
||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { openSettingModalAtom } from '../../../atoms';
|
||||
import {
|
||||
ServerConfigService,
|
||||
SubscriptionService,
|
||||
} from '../../../modules/cloud';
|
||||
import { openSettingModalAtom } from '../../atoms';
|
||||
import * as styles from './style.css';
|
||||
|
||||
export const UserPlanButton = () => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Avatar, Input, Switch, toast } from '@affine/component';
|
||||
import type { ConfirmModalProps } from '@affine/component/ui/modal';
|
||||
import { ConfirmModal, Modal } from '@affine/component/ui/modal';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { authAtom } from '@affine/core/components/atoms';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { apis } from '@affine/electron-api';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
DocsService,
|
||||
useLiveData,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { CollectionService } from '@affine/core/modules/collection';
|
||||
import type { Collection } from '@affine/env/filter';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { CollectionService } from '@affine/core/modules/collection';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ViewLayersIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { OverlayModal } from '@affine/component';
|
||||
import { openHistoryTipsModalAtom } from '@affine/core/atoms';
|
||||
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
||||
import { openHistoryTipsModalAtom } from '@affine/core/components/atoms';
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OverlayModal } from '@affine/component';
|
||||
import { openIssueFeedbackModalAtom } from '@affine/core/atoms';
|
||||
import { openIssueFeedbackModalAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { DoneIcon } from '@blocksuite/icons/rc';
|
||||
import type { ReactElement } from 'react';
|
||||
import { memo } from 'react';
|
||||
|
||||
import { useLanguageHelper } from '../../../hooks/affine/use-language-helper';
|
||||
import { useLanguageHelper } from '../../../components/hooks/affine/use-language-helper';
|
||||
import * as styles from './style.css';
|
||||
|
||||
// Fixme: keyboard focus should be supported by Menu component
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { useDocCollectionPage } from '@affine/core/hooks/use-block-suite-workspace-page';
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import { useDocCollectionPage } from '@affine/core/components/hooks/use-block-suite-workspace-page';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import type { ListHistoryQuery } from '@affine/graphql';
|
||||
import { listHistoryQuery, recoverDocMutation } from '@affine/graphql';
|
||||
@@ -20,8 +20,8 @@ import {
|
||||
import {
|
||||
useMutateQueryResource,
|
||||
useMutation,
|
||||
} from '../../../hooks/use-mutation';
|
||||
import { useQueryInfinite } from '../../../hooks/use-query';
|
||||
} from '../../../components/hooks/use-mutation';
|
||||
import { useQueryInfinite } from '../../../components/hooks/use-query';
|
||||
import { CloudBlobStorage } from '../../../modules/workspace-engine/impls/engine/blob-cloud';
|
||||
|
||||
const logger = new DebugLogger('page-history');
|
||||
|
||||
@@ -2,13 +2,13 @@ import { Loading, Scrollable } from '@affine/component';
|
||||
import { EditorLoading } from '@affine/component/page-detail-skeleton';
|
||||
import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { Modal, useConfirmModal } from '@affine/component/ui/modal';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { useDocCollectionPageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import { useDocCollectionPageTitle } from '@affine/core/components/hooks/use-block-suite-workspace-page-title';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import { CloseIcon, ToggleCollapseIcon } from '@blocksuite/icons/rc';
|
||||
import type { Doc as BlockSuiteDoc, DocCollection } from '@blocksuite/store';
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from 'react';
|
||||
import { encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import { pageHistoryModalAtom } from '../../../atoms/page-history';
|
||||
import { pageHistoryModalAtom } from '../../atoms/page-history';
|
||||
import { BlockSuiteEditor } from '../../blocksuite/block-suite-editor';
|
||||
import { PureEditorModeSwitch } from '../../blocksuite/block-suite-mode-switch';
|
||||
import { AffineErrorBoundary } from '../affine-error-boundary';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { MenuProps } from '@affine/component';
|
||||
import { Button, IconButton, Menu, MenuItem, Tooltip } from '@affine/component';
|
||||
import { useCurrentWorkspacePropertiesAdapter } from '@affine/core/hooks/use-affine-adapter';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useCurrentWorkspacePropertiesAdapter } from '@affine/core/components/hooks/use-affine-adapter';
|
||||
import { DocLinksService } from '@affine/core/modules/doc-link';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import type {
|
||||
@@ -10,6 +9,7 @@ import type {
|
||||
PagePropertyType,
|
||||
} from '@affine/core/modules/properties/services/schema';
|
||||
import { i18nTime, useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import {
|
||||
ArrowDownSmallIcon,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { MenuProps } from '@affine/component';
|
||||
import { IconButton, Input, Menu, Scrollable } from '@affine/component';
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { WorkspaceLegacyProperties } from '@affine/core/modules/properties';
|
||||
import type { Tag } from '@affine/core/modules/tag';
|
||||
import { DeleteTagConfirmModal, TagService } from '@affine/core/modules/tag';
|
||||
|
||||
+5
-2
@@ -1,10 +1,13 @@
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { openQuotaModalAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import {
|
||||
openQuotaModalAtom,
|
||||
openSettingModalAtom,
|
||||
} from '@affine/core/components/atoms';
|
||||
import { UserQuotaService } from '@affine/core/modules/cloud';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||
import bytes from 'bytes';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { openQuotaModalAtom } from '@affine/core/atoms';
|
||||
import { openQuotaModalAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { useJournalHelper } from '@affine/core/hooks/use-journal';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import { useJournalHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import {
|
||||
PeekViewService,
|
||||
useInsidePeekView,
|
||||
} from '@affine/core/modules/peek-view';
|
||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import {
|
||||
BlockLinkIcon,
|
||||
|
||||
+2
-2
@@ -1,7 +1,6 @@
|
||||
import { Button, ErrorMessage, Skeleton } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import {
|
||||
ServerConfigService,
|
||||
SubscriptionService,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
} from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { useSetAtom } from 'jotai';
|
||||
|
||||
+5
-5
@@ -5,11 +5,11 @@ import {
|
||||
} from '@affine/component/setting-components';
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useCatchEventCallback } from '@affine/core/hooks/use-catch-event-hook';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { ArrowRightSmallIcon, CameraIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
useEnsureLiveData,
|
||||
@@ -21,12 +21,12 @@ import { useSetAtom } from 'jotai';
|
||||
import type { FC } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { AuthService, ServerConfigService } from '../../../../modules/cloud';
|
||||
import {
|
||||
authAtom,
|
||||
openSettingModalAtom,
|
||||
openSignOutModalAtom,
|
||||
} from '../../../../atoms';
|
||||
import { AuthService, ServerConfigService } from '../../../../modules/cloud';
|
||||
} from '../../../atoms';
|
||||
import { Upload } from '../../../pure/file-upload';
|
||||
import { AIUsagePanel } from './ai-usage-panel';
|
||||
import { StorageProgress } from './storage-progress';
|
||||
|
||||
+3
-3
@@ -4,13 +4,13 @@ import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useAppUpdater } from '@affine/core/hooks/use-app-updater';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { useAppUpdater } from '@affine/core/components/hooks/use-app-updater';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { mixpanel } from '@affine/track';
|
||||
import { ArrowRightSmallIcon, OpenInNewIcon } from '@blocksuite/icons/rc';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
import { useAppSettingHelper } from '../../../../../components/hooks/affine/use-app-setting-helper';
|
||||
import { appIconMap, appNames } from '../../../../../pages/open-app';
|
||||
import { popupWindow } from '../../../../../utils';
|
||||
import { relatedLinks } from './config';
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { Loading } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAppUpdater } from '@affine/core/hooks/use-app-updater';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useAppUpdater } from '@affine/core/components/hooks/use-app-updater';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { dateFormatOptions } from '@toeverything/infra';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
import { useAppSettingHelper } from '../../../../../components/hooks/affine/use-app-setting-helper';
|
||||
|
||||
interface DateFormatMenuContentProps {
|
||||
currentOption: DateFormats;
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import { windowFrameStyleOptions } from '@toeverything/infra';
|
||||
import { useTheme } from 'next-themes';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||
import { useAppSettingHelper } from '../../../../../components/hooks/affine/use-app-setting-helper';
|
||||
import { LanguageMenu } from '../../../language-menu';
|
||||
import { Page } from '../editor/page';
|
||||
import { DateFormatSetting } from './date-format-setting';
|
||||
|
||||
+6
-6
@@ -7,9 +7,8 @@ import {
|
||||
} from '@affine/component/setting-components';
|
||||
import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { Loading } from '@affine/component/ui/loading';
|
||||
import { getUpgradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { getUpgradeQuestionnaireLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import {
|
||||
AuthService,
|
||||
InvoicesService,
|
||||
@@ -25,18 +24,19 @@ import {
|
||||
UserFriendlyError,
|
||||
} from '@affine/graphql';
|
||||
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { useMutation } from '../../../../../components/hooks/use-mutation';
|
||||
import { popupWindow } from '../../../../../utils';
|
||||
import {
|
||||
openSettingModalAtom,
|
||||
type PlansScrollAnchor,
|
||||
} from '../../../../../atoms';
|
||||
import { useMutation } from '../../../../../hooks/use-mutation';
|
||||
import { popupWindow } from '../../../../../utils';
|
||||
} from '../../../../atoms';
|
||||
import { CancelAction, ResumeAction } from '../plans/actions';
|
||||
import { AICancel, AIResume, AISubscribe } from '../plans/ai/actions';
|
||||
import { BelieverCard } from '../plans/lifetime/believer-card';
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { Button, Checkbox, Loading, Switch, Tooltip } from '@affine/component';
|
||||
import { SettingHeader } from '@affine/component/setting-components';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
ArrowRightSmallIcon,
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { track } from '@affine/track';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import { Button, type ButtonProps, useConfirmModal } from '@affine/component';
|
||||
import { useDowngradeNotify } from '@affine/core/components/affine/subscription-landing/notify';
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { getDowngradeQuestionnaireLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useState } from 'react';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Button, type ButtonProps } from '@affine/component';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { authAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
+2
-2
@@ -4,11 +4,11 @@ import {
|
||||
notify,
|
||||
useConfirmModal,
|
||||
} from '@affine/component';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { SubscriptionPlan } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { SingleSelectSelectSolidIcon } from '@blocksuite/icons/rc';
|
||||
import { useService } from '@toeverything/infra';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import { Button, type ButtonProps, Skeleton } from '@affine/component';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { popupWindow } from '@affine/core/utils';
|
||||
import { SubscriptionPlan, SubscriptionRecurring } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { SettingHeader } from '@affine/component/setting-components';
|
||||
import {
|
||||
openSettingModalAtom,
|
||||
type PlansScrollAnchor,
|
||||
} from '@affine/core/atoms';
|
||||
} from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ArrowRightBigIcon, ArrowUpSmallIcon } from '@blocksuite/icons/rc';
|
||||
import * as Collapsible from '@radix-ui/react-collapsible';
|
||||
|
||||
+4
-4
@@ -1,13 +1,13 @@
|
||||
import { Button, type ButtonProps } from '@affine/component/ui/button';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { generateSubscriptionCallbackLink } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { AuthService, SubscriptionService } from '@affine/core/modules/cloud';
|
||||
import { popupWindow } from '@affine/core/utils';
|
||||
import type { SubscriptionRecurring } from '@affine/graphql';
|
||||
import { SubscriptionPlan, SubscriptionStatus } from '@affine/graphql';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { DoneIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
@@ -16,7 +16,7 @@ import { nanoid } from 'nanoid';
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { authAtom } from '../../../../../atoms/index';
|
||||
import { authAtom } from '../../../../atoms/index';
|
||||
import { CancelAction, ResumeAction } from './actions';
|
||||
import type { DynamicPrice, FixedPrice } from './cloud-plans';
|
||||
import { ConfirmLoadingModal } from './modals';
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@ import {
|
||||
} from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
import type { ShortcutsInfo } from '../../../../../hooks/affine/use-shortcuts';
|
||||
import type { ShortcutsInfo } from '../../../../../components/hooks/affine/use-shortcuts';
|
||||
import {
|
||||
useEdgelessShortcuts,
|
||||
useGeneralShortcuts,
|
||||
useMarkdownShortcuts,
|
||||
usePageShortcuts,
|
||||
} from '../../../../../hooks/affine/use-shortcuts';
|
||||
} from '../../../../../components/hooks/affine/use-shortcuts';
|
||||
import { shortcutKey, shortcutKeyContainer, shortcutRow } from './style.css';
|
||||
|
||||
const ShortcutsPanel = ({
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Modal } from '@affine/component/ui/modal';
|
||||
import {
|
||||
openIssueFeedbackModalAtom,
|
||||
openStarAFFiNEModalAtom,
|
||||
} from '@affine/core/atoms';
|
||||
} from '@affine/core/components/atoms';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { Trans } from '@affine/i18n';
|
||||
import { ContactWithUsIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
+3
-3
@@ -5,12 +5,12 @@ import {
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { UserFeatureService } from '@affine/core/modules/cloud/services/user-feature';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { Logo1Icon } from '@blocksuite/icons/rc';
|
||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||
import {
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
useMemo,
|
||||
} from 'react';
|
||||
|
||||
import { authAtom } from '../../../../atoms';
|
||||
import { authAtom } from '../../../atoms';
|
||||
import { UserPlanButton } from '../../auth/user-plan-button';
|
||||
import { useGeneralSettingList } from '../general-setting';
|
||||
import type { ActiveTab, WorkspaceSubTab } from '../types';
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { Input } from '@affine/component';
|
||||
import type { ConfirmModalProps } from '@affine/component/ui/modal';
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
|
||||
+6
-11
@@ -1,7 +1,7 @@
|
||||
import { notify } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { ConfirmModal } from '@affine/component/ui/modal';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons/rc';
|
||||
@@ -15,12 +15,11 @@ import {
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { openSettingModalAtom } from '../../../../../../atoms';
|
||||
import {
|
||||
RouteLogic,
|
||||
useNavigateHelper,
|
||||
} from '../../../../../../hooks/use-navigate-helper';
|
||||
import { WorkspaceSubPath } from '../../../../../../shared';
|
||||
} from '../../../../../../components/hooks/use-navigate-helper';
|
||||
import { openSettingModalAtom } from '../../../../../atoms';
|
||||
import { WorkspaceDeleteModal } from './delete';
|
||||
|
||||
export const DeleteLeaveWorkspace = () => {
|
||||
@@ -37,7 +36,7 @@ export const DeleteLeaveWorkspace = () => {
|
||||
});
|
||||
const t = useI18n();
|
||||
const workspace = workspaceService.workspace;
|
||||
const { jumpToSubPath, jumpToIndex } = useNavigateHelper();
|
||||
const { jumpToPage, jumpToIndex } = useNavigateHelper();
|
||||
// fixme: cloud regression
|
||||
const [showDelete, setShowDelete] = useState(false);
|
||||
const [showLeave, setShowLeave] = useState(false);
|
||||
@@ -72,11 +71,7 @@ export const DeleteLeaveWorkspace = () => {
|
||||
);
|
||||
// TODO(@eyhn): if there is no workspace, jump to a new page(wait for design)
|
||||
if (backWorkspace) {
|
||||
jumpToSubPath(
|
||||
backWorkspace?.id || '',
|
||||
WorkspaceSubPath.ALL,
|
||||
RouteLogic.REPLACE
|
||||
);
|
||||
jumpToPage(backWorkspace?.id || '', 'all', RouteLogic.REPLACE);
|
||||
} else {
|
||||
jumpToIndex(RouteLogic.REPLACE);
|
||||
}
|
||||
@@ -96,7 +91,7 @@ export const DeleteLeaveWorkspace = () => {
|
||||
isOwner,
|
||||
t,
|
||||
workspaceList,
|
||||
jumpToSubPath,
|
||||
jumpToPage,
|
||||
jumpToIndex,
|
||||
workspacesService,
|
||||
workspacePermissionService,
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { openSettingModalAtom } from '../../../../../atoms';
|
||||
import { openSettingModalAtom } from '../../../../atoms';
|
||||
|
||||
export interface PublishPanelProps {
|
||||
workspace: Workspace | null;
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { notify } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useSystemOnline } from '@affine/core/hooks/use-system-online';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useSystemOnline } from '@affine/core/components/hooks/use-system-online';
|
||||
import { apis } from '@affine/electron-api';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { Workspace, WorkspaceMetadata } from '@toeverything/infra';
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useWorkspace } from '@affine/core/hooks/use-workspace';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { useWorkspace } from '@affine/core/components/hooks/use-workspace';
|
||||
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { ArrowRightSmallIcon } from '@blocksuite/icons/rc';
|
||||
|
||||
+4
-4
@@ -11,11 +11,10 @@ import { Button, IconButton } from '@affine/component/ui/button';
|
||||
import { Loading } from '@affine/component/ui/loading';
|
||||
import { Menu, MenuItem } from '@affine/component/ui/menu';
|
||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
||||
import { useInviteMember } from '@affine/core/hooks/affine/use-invite-member';
|
||||
import { useRevokeMemberPermission } from '@affine/core/hooks/affine/use-revoke-member-permission';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import { useInviteMember } from '@affine/core/components/hooks/affine/use-invite-member';
|
||||
import { useRevokeMemberPermission } from '@affine/core/components/hooks/affine/use-revoke-member-permission';
|
||||
import {
|
||||
type Member,
|
||||
WorkspaceMembersService,
|
||||
@@ -25,6 +24,7 @@ import { WorkspaceQuotaService } from '@affine/core/modules/quota';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { Permission, UserFriendlyError } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { MoreVerticalIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
useEnsureLiveData,
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { FlexWrapper, Input, notify, Wrapper } from '@affine/component';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
|
||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||
import { Upload } from '@affine/core/components/pure/file-upload';
|
||||
import { useCatchEventCallback } from '@affine/core/hooks/use-catch-event-hook';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
import { validateAndReduceImage } from '@affine/core/utils/reduce-image';
|
||||
import { UNTITLED_WORKSPACE_NAME } from '@affine/env/constant';
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { WorkspaceShareSettingService } from '@affine/core/modules/share-setting';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { Button, IconButton, Menu } from '@affine/component';
|
||||
import { SettingHeader } from '@affine/component/setting-components';
|
||||
import { useWorkspaceInfo } from '@affine/core/hooks/use-workspace-info';
|
||||
import { useWorkspaceInfo } from '@affine/core/components/hooks/use-workspace-info';
|
||||
import type { PageInfoCustomPropertyMeta } from '@affine/core/modules/properties/services/schema';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import {
|
||||
@@ -20,8 +20,8 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { useCurrentWorkspacePropertiesAdapter } from '../../../../../hooks/use-affine-adapter';
|
||||
import { useWorkspace } from '../../../../../hooks/use-workspace';
|
||||
import { useCurrentWorkspacePropertiesAdapter } from '../../../../../components/hooks/use-affine-adapter';
|
||||
import { useWorkspace } from '../../../../../components/hooks/use-workspace';
|
||||
import type { PagePropertyIcon } from '../../../page-properties';
|
||||
import {
|
||||
nameToIcon,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { track } from '@affine/track';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
import { type Workspace } from '@toeverything/infra';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { useExportPage } from '@affine/core/components/hooks/affine/use-export-page';
|
||||
import {
|
||||
ExportMenuItems,
|
||||
PrintMenuItems,
|
||||
} from '@affine/core/components/page-list';
|
||||
import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
|
||||
+4
-4
@@ -1,13 +1,12 @@
|
||||
import { notify, Skeleton } from '@affine/component';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import {
|
||||
getSelectedNodes,
|
||||
useSharingUrl,
|
||||
} from '@affine/core/hooks/affine/use-share-url';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
} from '@affine/core/components/hooks/affine/use-share-url';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { ServerConfigService } from '@affine/core/modules/cloud';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
|
||||
@@ -15,6 +14,7 @@ import { ShareInfoService } from '@affine/core/modules/share-doc';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { PublicPageMode } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import {
|
||||
BlockIcon,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OverlayModal } from '@affine/component';
|
||||
import { openStarAFFiNEModalAtom } from '@affine/core/atoms';
|
||||
import { openStarAFFiNEModalAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AuthPageContainer } from '@affine/component/auth-components';
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { useSubscriptionNotifyWriter } from '@affine/core/hooks/affine/use-subscription-notify';
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { useSubscriptionNotifyWriter } from '@affine/core/components/hooks/affine/use-subscription-notify';
|
||||
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import { type ReactNode, useCallback } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCatchEventCallback } from '@affine/core/hooks/use-catch-event-hook';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||
import { track } from '@affine/track';
|
||||
import { CloseIcon, DownloadIcon } from '@blocksuite/icons/rc';
|
||||
import clsx from 'clsx';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Tooltip } from '@affine/component';
|
||||
import { useCatchEventCallback } from '@affine/core/hooks/use-catch-event-hook';
|
||||
import { useCatchEventCallback } from '@affine/core/components/hooks/use-catch-event-hook';
|
||||
import { popupWindow } from '@affine/core/utils';
|
||||
import { Unreachable } from '@affine/env/constant';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Skeleton } from '@affine/component';
|
||||
import { ResizePanel } from '@affine/component/resize-panel';
|
||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||
import { NavigateContext } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { useAppSettingHelper } from '@affine/core/components/hooks/affine/use-app-setting-helper';
|
||||
import { NavigateContext } from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { useServiceOptional, WorkspaceService } from '@toeverything/infra';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
import type { SettingProps } from '../affine/setting-modal';
|
||||
import type { ActiveTab } from '../affine/setting-modal/types';
|
||||
// modal atoms
|
||||
export const openWorkspacesModalAtom = atom(false);
|
||||
/**
|
||||
* @deprecated use `useSignOut` hook instated
|
||||
*/
|
||||
export const openSignOutModalAtom = atom(false);
|
||||
export const openQuotaModalAtom = atom(false);
|
||||
export const openStarAFFiNEModalAtom = atom(false);
|
||||
export const openIssueFeedbackModalAtom = atom(false);
|
||||
export const openHistoryTipsModalAtom = atom(false);
|
||||
export const openInfoModalAtom = atom(false);
|
||||
|
||||
export const rightSidebarWidthAtom = atom(320);
|
||||
|
||||
export type PlansScrollAnchor =
|
||||
| 'aiPricingPlan'
|
||||
| 'cloudPricingPlan'
|
||||
| 'lifetimePricingPlan';
|
||||
export type SettingAtom = {
|
||||
open: boolean;
|
||||
workspaceMetadata?: SettingProps['workspaceMetadata'];
|
||||
} & (
|
||||
| {
|
||||
activeTab: 'plans';
|
||||
scrollAnchor?: PlansScrollAnchor;
|
||||
}
|
||||
| { activeTab: Exclude<ActiveTab, 'plans'> }
|
||||
);
|
||||
|
||||
export const openSettingModalAtom = atom<SettingAtom>({
|
||||
activeTab: 'appearance',
|
||||
open: false,
|
||||
});
|
||||
|
||||
export type AuthAtomData =
|
||||
| { state: 'signIn' }
|
||||
| {
|
||||
state: 'afterSignUpSendEmail';
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
state: 'afterSignInSendEmail';
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
state: 'signInWithPassword';
|
||||
email: string;
|
||||
}
|
||||
| {
|
||||
state: 'sendEmail';
|
||||
email: string;
|
||||
emailType:
|
||||
| 'setPassword'
|
||||
| 'changePassword'
|
||||
| 'changeEmail'
|
||||
| 'verifyEmail';
|
||||
};
|
||||
|
||||
export const authAtom = atom<
|
||||
AuthAtomData & {
|
||||
openModal: boolean;
|
||||
}
|
||||
>({
|
||||
openModal: false,
|
||||
state: 'signIn',
|
||||
});
|
||||
|
||||
export type AllPageFilterOption = 'docs' | 'collections' | 'tags';
|
||||
export const allPageFilterSelectAtom = atom<AllPageFilterOption>('docs');
|
||||
|
||||
export const openWorkspaceListModalAtom = atom(false);
|
||||
@@ -0,0 +1,7 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
// make page history controllable by atom to make it easier to use in CMDK
|
||||
export const pageHistoryModalAtom = atom({
|
||||
open: false,
|
||||
pageId: '',
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { atom } from 'jotai';
|
||||
|
||||
export type TrashModal = {
|
||||
open: boolean;
|
||||
pageIds: string[];
|
||||
pageTitles: string[];
|
||||
};
|
||||
|
||||
export const trashModalAtom = atom<TrashModal>({
|
||||
open: false,
|
||||
pageIds: [],
|
||||
pageTitles: [],
|
||||
});
|
||||
+2
-2
@@ -1,14 +1,14 @@
|
||||
import { notify } from '@affine/component';
|
||||
import { authAtom, openSettingModalAtom } from '@affine/core/atoms';
|
||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||
import { toggleGeneralAIOnboarding } from '@affine/core/components/affine/ai-onboarding/apis';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { authAtom, openSettingModalAtom } from '@affine/core/components/atoms';
|
||||
import {
|
||||
getBaseUrl,
|
||||
type getCopilotHistoriesQuery,
|
||||
type RequestOptions,
|
||||
} from '@affine/graphql';
|
||||
import { Trans } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { UnauthorizedError } from '@blocksuite/blocks';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import { getCurrentStore } from '@toeverything/infra';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||
import { mixpanel, track } from '@affine/core/mixpanel';
|
||||
import { mixpanel, track } from '@affine/track';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import { lowerCase, omit } from 'lodash-es';
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
|
||||
import { useJournalInfoHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
useConfirmModal,
|
||||
useLitPortalFactory,
|
||||
} from '@affine/component';
|
||||
import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
|
||||
import { useJournalInfoHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import { PeekViewService } from '@affine/core/modules/peek-view';
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@ import { notify } from '@affine/component';
|
||||
import {
|
||||
generateUrl,
|
||||
type UseSharingUrl,
|
||||
} from '@affine/core/hooks/affine/use-share-url';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
} from '@affine/core/components/hooks/affine/use-share-url';
|
||||
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { I18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DatabaseBlockModel, MenuOptions } from '@blocksuite/blocks';
|
||||
import { LinkIcon } from '@blocksuite/icons/lit';
|
||||
import type { FrameworkProvider } from '@toeverything/infra';
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@ import {
|
||||
AIEdgelessRootBlockSpec,
|
||||
AIPageRootBlockSpec,
|
||||
} from '@affine/core/blocksuite/presets/ai';
|
||||
import { mixpanel } from '@affine/core/mixpanel';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-settting';
|
||||
import { mixpanel } from '@affine/track';
|
||||
import { ConfigExtension, type ExtensionType } from '@blocksuite/block-std';
|
||||
import {
|
||||
EdgelessRootBlockSpec,
|
||||
|
||||
+1
-1
@@ -7,7 +7,6 @@ import {
|
||||
toReactNode,
|
||||
type useConfirmModal,
|
||||
} from '@affine/component';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import type { EditorService } from '@affine/core/modules/editor';
|
||||
import { resolveLinkToDoc } from '@affine/core/modules/navigation';
|
||||
import type { PeekViewService } from '@affine/core/modules/peek-view';
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
} from '@affine/core/modules/quicksearch';
|
||||
import { ExternalLinksQuickSearchSession } from '@affine/core/modules/quicksearch/impls/external-links';
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
type BlockService,
|
||||
BlockViewIdentifier,
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { WorkspacePropertiesAdapter } from '@affine/core/modules/properties';
|
||||
import { I18n, i18nTime } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
import type { AffineInlineEditor } from '@blocksuite/blocks';
|
||||
import { LinkedWidgetUtils } from '@blocksuite/blocks';
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@ import { notify } from '@affine/component';
|
||||
import {
|
||||
generateUrl,
|
||||
type UseSharingUrl,
|
||||
} from '@affine/core/hooks/affine/use-share-url';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
} from '@affine/core/components/hooks/affine/use-share-url';
|
||||
import { getAffineCloudBaseUrl } from '@affine/core/modules/cloud/services/fetch';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { I18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||
import type {
|
||||
GfxBlockElementModel,
|
||||
|
||||
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { FavoriteTag } from '@affine/core/components/page-list';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { toast } from '@affine/core/utils';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { IconButton } from '@affine/component';
|
||||
import { openInfoModalAtom } from '@affine/core/atoms';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { openInfoModalAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { InformationIcon } from '@blocksuite/icons/rc';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { WeekDatePicker } from '@affine/component';
|
||||
import {
|
||||
useJournalInfoHelper,
|
||||
useJournalRouteHelper,
|
||||
} from '@affine/core/hooks/use-journal';
|
||||
} from '@affine/core/components/hooks/use-journal';
|
||||
import type { Doc, DocCollection } from '@blocksuite/store';
|
||||
import dayjs from 'dayjs';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Button } from '@affine/component';
|
||||
import { useJournalRouteHelper } from '@affine/core/hooks/use-journal';
|
||||
import { useJournalRouteHelper } from '@affine/core/components/hooks/use-journal';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { DocCollection } from '@blocksuite/store';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
+10
-10
@@ -5,27 +5,27 @@ import {
|
||||
MenuSeparator,
|
||||
MenuSub,
|
||||
} from '@affine/component/ui/menu';
|
||||
import { PageHistoryModal } from '@affine/core/components/affine/page-history-modal';
|
||||
import { ShareMenuContent } from '@affine/core/components/affine/share-page-modal/share-menu';
|
||||
import {
|
||||
openHistoryTipsModalAtom,
|
||||
openInfoModalAtom,
|
||||
} from '@affine/core/atoms';
|
||||
import { PageHistoryModal } from '@affine/core/components/affine/page-history-modal';
|
||||
import { ShareMenuContent } from '@affine/core/components/affine/share-page-modal/share-menu';
|
||||
} from '@affine/core/components/atoms';
|
||||
import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/use-block-suite-meta-helper';
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { useExportPage } from '@affine/core/components/hooks/affine/use-export-page';
|
||||
import { useTrashModalHelper } from '@affine/core/components/hooks/affine/use-trash-modal-helper';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import { Export, MoveToTrash } from '@affine/core/components/page-list';
|
||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||
import { useBlockSuiteMetaHelper } from '@affine/core/hooks/affine/use-block-suite-meta-helper';
|
||||
import { useEnableCloud } from '@affine/core/hooks/affine/use-enable-cloud';
|
||||
import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
|
||||
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useDocMetaHelper } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { ViewService } from '@affine/core/modules/workbench/services/view';
|
||||
import { useDetailPageHeaderResponsive } from '@affine/core/pages/workspace/detail-page/use-header-responsive';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
DuplicateIcon,
|
||||
EdgelessIcon,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { InlineEditProps } from '@affine/component';
|
||||
import { InlineEdit } from '@affine/component';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
DocsService,
|
||||
useLiveData,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { RadioGroup, type RadioItem, toast, Tooltip } from '@affine/component';
|
||||
import { registerAffineCommand } from '@affine/core/commands';
|
||||
import { track } from '@affine/core/mixpanel';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { Button } from '@affine/component';
|
||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
export const ImportTemplateButton = ({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button } from '@affine/component/ui/button';
|
||||
import { authAtom } from '@affine/core/atoms';
|
||||
import { authAtom } from '@affine/core/components/atoms';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Avatar } from '@affine/component/ui/avatar';
|
||||
import { Menu, MenuItem, MenuSeparator } from '@affine/component/ui/menu';
|
||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { SignOutIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @vitest-environment happy-dom
|
||||
*/
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { useSystemOnline } from '../use-system-online';
|
||||
|
||||
describe('useSystemOnline', () => {
|
||||
test('should be online', () => {
|
||||
const systemOnlineHook = renderHook(() => useSystemOnline());
|
||||
expect(systemOnlineHook.result.current).toBe(true);
|
||||
});
|
||||
|
||||
test('should be offline', () => {
|
||||
const systemOnlineHook = renderHook(() => useSystemOnline());
|
||||
vi.spyOn(navigator, 'onLine', 'get').mockReturnValue(false);
|
||||
expect(systemOnlineHook.result.current).toBe(true);
|
||||
window.dispatchEvent(new Event('offline'));
|
||||
systemOnlineHook.rerender();
|
||||
expect(systemOnlineHook.result.current).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import React, { type DependencyList } from 'react';
|
||||
|
||||
export type AsyncErrorHandler = (error: Error) => void;
|
||||
|
||||
/**
|
||||
* App should provide a global error handler for async callback in the root.
|
||||
*/
|
||||
export const AsyncCallbackContext = React.createContext<AsyncErrorHandler>(
|
||||
e => {
|
||||
console.error(e);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Translate async function to sync function and handle error automatically.
|
||||
* Only accept void function, return data here is meaningless.
|
||||
*/
|
||||
export function useAsyncCallback<T extends any[]>(
|
||||
callback: (...args: T) => Promise<void>,
|
||||
deps: DependencyList
|
||||
): (...args: T) => void {
|
||||
const handleAsyncError = React.useContext(AsyncCallbackContext);
|
||||
return React.useCallback(
|
||||
(...args: any) => {
|
||||
callback(...args).catch(e => handleAsyncError(e));
|
||||
},
|
||||
[...deps] // eslint-disable-line react-hooks/exhaustive-deps
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# AFFiNE Hooks
|
||||
|
||||
> This directory will be moved to `@affine/worksapce/affine/hooks` in the future.
|
||||
|
||||
Only put hooks in this directory if they are specific to AFFiNE, for example
|
||||
if they are using the AFFiNE API, or if the `AffineWorkspace` is required.
|
||||
@@ -0,0 +1,88 @@
|
||||
import { toast } from '@affine/component';
|
||||
import { useBlockSuiteDocMeta } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import type { AllPageListConfig } from '@affine/core/components/page-list';
|
||||
import { FavoriteTag } from '@affine/core/components/page-list';
|
||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { ShareDocsListService } from '@affine/core/modules/share-doc';
|
||||
import { PublicPageMode } from '@affine/graphql';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { DocMeta } from '@blocksuite/store';
|
||||
import { useLiveData, useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
|
||||
/**
|
||||
* @deprecated very poor performance
|
||||
*/
|
||||
export const useAllPageListConfig = () => {
|
||||
const currentWorkspace = useService(WorkspaceService).workspace;
|
||||
const shareDocsListService = useService(ShareDocsListService);
|
||||
const shareDocs = useLiveData(shareDocsListService.shareDocs?.list$);
|
||||
|
||||
useEffect(() => {
|
||||
// TODO(@eyhn): loading & error UI
|
||||
shareDocsListService.shareDocs?.revalidate();
|
||||
}, [shareDocsListService]);
|
||||
|
||||
const workspace = currentWorkspace.docCollection;
|
||||
const pageMetas = useBlockSuiteDocMeta(workspace);
|
||||
const pageMap = useMemo(
|
||||
() => Object.fromEntries(pageMetas.map(page => [page.id, page])),
|
||||
[pageMetas]
|
||||
);
|
||||
const favAdapter = useService(CompatibleFavoriteItemsAdapter);
|
||||
const t = useI18n();
|
||||
const favoriteItems = useLiveData(favAdapter.favorites$);
|
||||
|
||||
const isActive = useCallback(
|
||||
(page: DocMeta) => {
|
||||
return favoriteItems.some(fav => fav.id === page.id);
|
||||
},
|
||||
[favoriteItems]
|
||||
);
|
||||
const onToggleFavoritePage = useCallback(
|
||||
(page: DocMeta) => {
|
||||
const status = isActive(page);
|
||||
favAdapter.toggle(page.id, 'doc');
|
||||
toast(
|
||||
status
|
||||
? t['com.affine.toastMessage.removedFavorites']()
|
||||
: t['com.affine.toastMessage.addedFavorites']()
|
||||
);
|
||||
},
|
||||
[favAdapter, isActive, t]
|
||||
);
|
||||
|
||||
return useMemo<AllPageListConfig>(() => {
|
||||
return {
|
||||
allPages: pageMetas,
|
||||
getPublicMode(id) {
|
||||
const mode = shareDocs?.find(shareDoc => shareDoc.id === id)?.mode;
|
||||
if (mode === PublicPageMode.Edgeless) {
|
||||
return 'edgeless';
|
||||
} else if (mode === PublicPageMode.Page) {
|
||||
return 'page';
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
docCollection: currentWorkspace.docCollection,
|
||||
getPage: id => pageMap[id],
|
||||
favoriteRender: page => {
|
||||
return (
|
||||
<FavoriteTag
|
||||
style={{ marginRight: 8 }}
|
||||
onClick={() => onToggleFavoritePage(page)}
|
||||
active={isActive(page)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
}, [
|
||||
pageMetas,
|
||||
currentWorkspace.docCollection,
|
||||
shareDocs,
|
||||
pageMap,
|
||||
isActive,
|
||||
onToggleFavoritePage,
|
||||
]);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { AppSetting } from '@toeverything/infra';
|
||||
import { appSettingAtom } from '@toeverything/infra';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
export function useAppSettingHelper() {
|
||||
const [appSettings, setAppSettings] = useAtom(appSettingAtom);
|
||||
|
||||
const updateSettings = useCallback(
|
||||
<K extends keyof AppSetting>(key: K, value: AppSetting[K]) => {
|
||||
setAppSettings(prevSettings => ({ ...prevSettings, [key]: value }));
|
||||
},
|
||||
[setAppSettings]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
appSettings,
|
||||
updateSettings,
|
||||
}),
|
||||
[appSettings, updateSettings]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import { useDocCollectionHelper } from '@affine/core/components/hooks/use-block-suite-workspace-helper';
|
||||
import type { DocMode } from '@blocksuite/blocks';
|
||||
import { DocsService, useService, WorkspaceService } from '@toeverything/infra';
|
||||
import { useCallback } from 'react';
|
||||
import { applyUpdate, encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import { useNavigateHelper } from '../use-navigate-helper';
|
||||
|
||||
export function useBlockSuiteMetaHelper() {
|
||||
const workspace = useService(WorkspaceService).workspace;
|
||||
const { setDocMeta, getDocMeta, setDocTitle, setDocReadonly } =
|
||||
useDocMetaHelper();
|
||||
const { createDoc } = useDocCollectionHelper(workspace.docCollection);
|
||||
const { openPage } = useNavigateHelper();
|
||||
const docRecordList = useService(DocsService).list;
|
||||
|
||||
// TODO-Doma
|
||||
// "Remove" may cause ambiguity here. Consider renaming as "moveToTrash".
|
||||
const removeToTrash = useCallback(
|
||||
(docId: string) => {
|
||||
const docRecord = docRecordList.doc$(docId).value;
|
||||
if (docRecord) {
|
||||
docRecord.moveToTrash();
|
||||
setDocReadonly(docId, true);
|
||||
}
|
||||
},
|
||||
[docRecordList, setDocReadonly]
|
||||
);
|
||||
|
||||
const restoreFromTrash = useCallback(
|
||||
(docId: string) => {
|
||||
const docRecord = docRecordList.doc$(docId).value;
|
||||
if (docRecord) {
|
||||
docRecord.restoreFromTrash();
|
||||
setDocReadonly(docId, false);
|
||||
}
|
||||
},
|
||||
[docRecordList, setDocReadonly]
|
||||
);
|
||||
|
||||
const permanentlyDeletePage = useCallback(
|
||||
(pageId: string) => {
|
||||
workspace.docCollection.removeDoc(pageId);
|
||||
},
|
||||
[workspace]
|
||||
);
|
||||
|
||||
const duplicate = useAsyncCallback(
|
||||
async (pageId: string, openPageAfterDuplication: boolean = true) => {
|
||||
const currentPagePrimaryMode =
|
||||
docRecordList.doc$(pageId).value?.primaryMode$.value;
|
||||
const currentPageMeta = getDocMeta(pageId);
|
||||
const newPage = createDoc();
|
||||
const currentPage = workspace.docCollection.getDoc(pageId);
|
||||
|
||||
newPage.load();
|
||||
if (!currentPageMeta || !currentPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const update = encodeStateAsUpdate(currentPage.spaceDoc);
|
||||
applyUpdate(newPage.spaceDoc, update);
|
||||
|
||||
setDocMeta(newPage.id, {
|
||||
tags: currentPageMeta.tags,
|
||||
});
|
||||
|
||||
const lastDigitRegex = /\((\d+)\)$/;
|
||||
const match = currentPageMeta?.title?.match(lastDigitRegex);
|
||||
const newNumber = match ? parseInt(match[1], 10) + 1 : 1;
|
||||
|
||||
const newPageTitle =
|
||||
currentPageMeta?.title?.replace(lastDigitRegex, '') + `(${newNumber})`;
|
||||
|
||||
docRecordList
|
||||
.doc$(newPage.id)
|
||||
.value?.setPrimaryMode(currentPagePrimaryMode || ('page' as DocMode));
|
||||
setDocTitle(newPage.id, newPageTitle);
|
||||
openPageAfterDuplication &&
|
||||
openPage(workspace.docCollection.id, newPage.id);
|
||||
},
|
||||
[
|
||||
docRecordList,
|
||||
getDocMeta,
|
||||
createDoc,
|
||||
workspace.docCollection,
|
||||
setDocMeta,
|
||||
setDocTitle,
|
||||
openPage,
|
||||
]
|
||||
);
|
||||
|
||||
return {
|
||||
removeToTrash,
|
||||
restoreFromTrash,
|
||||
permanentlyDeletePage,
|
||||
|
||||
duplicate,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import type { DeleteCollectionInfo } from '@affine/env/filter';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useDeleteCollectionInfo = () => {
|
||||
const authService = useService(AuthService);
|
||||
|
||||
const user = useLiveData(authService.session.account$);
|
||||
|
||||
return useMemo<DeleteCollectionInfo | null>(
|
||||
() => (user ? { userName: user.label, userId: user.id } : null),
|
||||
[user]
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
import { notify, useConfirmModal } from '@affine/component';
|
||||
import { authAtom } from '@affine/core/components/atoms';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { Workspace } from '@toeverything/infra';
|
||||
import {
|
||||
useLiveData,
|
||||
useService,
|
||||
WorkspacesService,
|
||||
} from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useNavigateHelper } from '../use-navigate-helper';
|
||||
|
||||
interface ConfirmEnableCloudOptions {
|
||||
/**
|
||||
* Fired when the workspace is successfully enabled
|
||||
*/
|
||||
onSuccess?: () => void;
|
||||
/**
|
||||
* Fired when workspace is successfully enabled or user cancels the operation
|
||||
*/
|
||||
onFinished?: () => void;
|
||||
openPageId?: string;
|
||||
}
|
||||
type ConfirmEnableArgs = [Workspace, ConfirmEnableCloudOptions | undefined];
|
||||
|
||||
export const useEnableCloud = () => {
|
||||
const t = useI18n();
|
||||
const authService = useService(AuthService);
|
||||
const account = useLiveData(authService.session.account$);
|
||||
const loginStatus = useLiveData(useService(AuthService).session.status$);
|
||||
const setAuthAtom = useSetAtom(authAtom);
|
||||
const { openConfirmModal, closeConfirmModal } = useConfirmModal();
|
||||
const workspacesService = useService(WorkspacesService);
|
||||
const { jumpToPage } = useNavigateHelper();
|
||||
|
||||
const enableCloud = useCallback(
|
||||
async (ws: Workspace | null, options?: ConfirmEnableCloudOptions) => {
|
||||
try {
|
||||
if (!ws) return;
|
||||
if (!account) return;
|
||||
const { id: newId } = await workspacesService.transformLocalToCloud(
|
||||
ws,
|
||||
account.id
|
||||
);
|
||||
jumpToPage(newId, options?.openPageId || 'all');
|
||||
options?.onSuccess?.();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
notify.error({
|
||||
title: t['com.affine.workspace.enable-cloud.failed'](),
|
||||
});
|
||||
}
|
||||
},
|
||||
[account, jumpToPage, t, workspacesService]
|
||||
);
|
||||
|
||||
const openSignIn = useCallback(() => {
|
||||
setAuthAtom(prev => ({ ...prev, openModal: true }));
|
||||
}, [setAuthAtom]);
|
||||
|
||||
const signInOrEnableCloud = useCallback(
|
||||
async (...args: ConfirmEnableArgs) => {
|
||||
// not logged in, open login modal
|
||||
if (loginStatus === 'unauthenticated') {
|
||||
openSignIn();
|
||||
}
|
||||
|
||||
if (loginStatus === 'authenticated') {
|
||||
await enableCloud(...args);
|
||||
}
|
||||
},
|
||||
[enableCloud, loginStatus, openSignIn]
|
||||
);
|
||||
|
||||
const confirmEnableCloud = useCallback(
|
||||
(ws: Workspace, options?: ConfirmEnableCloudOptions) => {
|
||||
const { onSuccess, onFinished } = options ?? {};
|
||||
|
||||
const closeOnSuccess = () => {
|
||||
closeConfirmModal();
|
||||
onSuccess?.();
|
||||
};
|
||||
|
||||
openConfirmModal(
|
||||
{
|
||||
title: t['Enable AFFiNE Cloud'](),
|
||||
description: t['Enable AFFiNE Cloud Description'](),
|
||||
cancelText: t['com.affine.enableAffineCloudModal.button.cancel'](),
|
||||
confirmText:
|
||||
loginStatus === 'authenticated'
|
||||
? t['Enable']()
|
||||
: t['Sign in and Enable'](),
|
||||
confirmButtonOptions: {
|
||||
variant: 'primary',
|
||||
['data-testid' as string]: 'confirm-enable-affine-cloud-button',
|
||||
},
|
||||
onConfirm: async () =>
|
||||
await signInOrEnableCloud(ws, {
|
||||
...options,
|
||||
onSuccess: closeOnSuccess,
|
||||
}),
|
||||
onOpenChange: open => {
|
||||
if (!open) onFinished?.();
|
||||
},
|
||||
},
|
||||
{
|
||||
autoClose: false,
|
||||
}
|
||||
);
|
||||
},
|
||||
[closeConfirmModal, loginStatus, openConfirmModal, signInOrEnableCloud, t]
|
||||
);
|
||||
|
||||
return confirmEnableCloud;
|
||||
};
|
||||
@@ -0,0 +1,107 @@
|
||||
import { notify } from '@affine/component';
|
||||
import {
|
||||
pushGlobalLoadingEventAtom,
|
||||
resolveGlobalLoadingEventAtom,
|
||||
} from '@affine/component/global-loading';
|
||||
import { EditorService } from '@affine/core/modules/editor';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import {
|
||||
ExportManager,
|
||||
HtmlTransformer,
|
||||
MarkdownTransformer,
|
||||
printToPdf,
|
||||
} from '@blocksuite/blocks';
|
||||
import type { AffineEditorContainer } from '@blocksuite/presets';
|
||||
import type { Doc } from '@blocksuite/store';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { useAsyncCallback } from '../affine-async-hooks';
|
||||
|
||||
type ExportType = 'pdf' | 'html' | 'png' | 'markdown';
|
||||
|
||||
interface ExportHandlerOptions {
|
||||
page: Doc;
|
||||
editorContainer: AffineEditorContainer;
|
||||
type: ExportType;
|
||||
}
|
||||
|
||||
async function exportHandler({
|
||||
page,
|
||||
type,
|
||||
editorContainer,
|
||||
}: ExportHandlerOptions) {
|
||||
const editorRoot = document.querySelector('editor-host');
|
||||
track.$.sharePanel.$.export({
|
||||
type,
|
||||
});
|
||||
switch (type) {
|
||||
case 'html':
|
||||
await HtmlTransformer.exportDoc(page);
|
||||
return;
|
||||
case 'markdown':
|
||||
await MarkdownTransformer.exportDoc(page);
|
||||
return;
|
||||
case 'pdf':
|
||||
await printToPdf(editorContainer);
|
||||
return;
|
||||
case 'png': {
|
||||
await editorRoot?.std.get(ExportManager).exportPng();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const useExportPage = () => {
|
||||
const editor = useService(EditorService).editor;
|
||||
const editorContainer = useLiveData(editor.editorContainer$);
|
||||
const blocksuiteDoc = editor.doc.blockSuiteDoc;
|
||||
const pushGlobalLoadingEvent = useSetAtom(pushGlobalLoadingEventAtom);
|
||||
const resolveGlobalLoadingEvent = useSetAtom(resolveGlobalLoadingEventAtom);
|
||||
const t = useI18n();
|
||||
|
||||
const onClickHandler = useAsyncCallback(
|
||||
async (type: ExportType) => {
|
||||
if (editorContainer === null) return;
|
||||
|
||||
// editor container is wrapped by a proxy, we need to get the origin
|
||||
const originEditorContainer = (editorContainer as any)
|
||||
.origin as AffineEditorContainer;
|
||||
|
||||
const globalLoadingID = nanoid();
|
||||
pushGlobalLoadingEvent({
|
||||
key: globalLoadingID,
|
||||
});
|
||||
try {
|
||||
await exportHandler({
|
||||
page: blocksuiteDoc,
|
||||
type,
|
||||
editorContainer: originEditorContainer,
|
||||
});
|
||||
notify.success({
|
||||
title: t['com.affine.export.success.title'](),
|
||||
message: t['com.affine.export.success.message'](),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
notify.error({
|
||||
title: t['com.affine.export.error.title'](),
|
||||
message: t['com.affine.export.error.message'](),
|
||||
});
|
||||
} finally {
|
||||
resolveGlobalLoadingEvent(globalLoadingID);
|
||||
}
|
||||
},
|
||||
[
|
||||
blocksuiteDoc,
|
||||
editorContainer,
|
||||
pushGlobalLoadingEvent,
|
||||
resolveGlobalLoadingEvent,
|
||||
t,
|
||||
]
|
||||
);
|
||||
|
||||
return onClickHandler;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { Permission } from '@affine/graphql';
|
||||
import { inviteByEmailMutation } from '@affine/graphql';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMutation } from '../use-mutation';
|
||||
import { useMutateCloud } from './use-mutate-cloud';
|
||||
|
||||
export function useInviteMember(workspaceId: string) {
|
||||
const { trigger, isMutating } = useMutation({
|
||||
mutation: inviteByEmailMutation,
|
||||
});
|
||||
const mutate = useMutateCloud();
|
||||
return {
|
||||
invite: useCallback(
|
||||
async (email: string, permission: Permission, sendInviteMail = false) => {
|
||||
const res = await trigger({
|
||||
workspaceId,
|
||||
email,
|
||||
permission,
|
||||
sendInviteMail,
|
||||
});
|
||||
await mutate();
|
||||
// return is successful
|
||||
return res?.invite;
|
||||
},
|
||||
[mutate, trigger, workspaceId]
|
||||
),
|
||||
isMutating,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { LOCALES, useI18n } from '@affine/i18n';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
|
||||
export function useLanguageHelper() {
|
||||
const i18n = useI18n();
|
||||
const currentLanguage = useMemo(
|
||||
() => LOCALES.find(item => item.tag === i18n.language),
|
||||
[i18n.language]
|
||||
);
|
||||
const languagesList = useMemo(
|
||||
() =>
|
||||
LOCALES.map(item => ({
|
||||
tag: item.tag,
|
||||
originalName: item.originalName,
|
||||
name: item.name,
|
||||
Completeness: item.completeRate,
|
||||
})),
|
||||
[]
|
||||
);
|
||||
const onLanguageChange = useAsyncCallback(
|
||||
async (event: string) => {
|
||||
await i18n.changeLanguage(event);
|
||||
},
|
||||
[i18n]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentLanguage) {
|
||||
document.documentElement.lang = currentLanguage.tag;
|
||||
}
|
||||
}, [currentLanguage]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
currentLanguage,
|
||||
languagesList,
|
||||
onLanguageChange,
|
||||
}),
|
||||
[currentLanguage, languagesList, onLanguageChange]
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useSWRConfig } from 'swr';
|
||||
|
||||
export function useMutateCloud() {
|
||||
const { mutate } = useSWRConfig();
|
||||
return useCallback(async () => {
|
||||
// TODO(@eyhn): should not mutate all graphql cache
|
||||
return mutate(key => {
|
||||
if (Array.isArray(key)) {
|
||||
return key[0] === 'cloud';
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}, [mutate]);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { DocCollection } from '@blocksuite/store';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export function useReferenceLinkHelper(docCollection: DocCollection) {
|
||||
const addReferenceLink = useCallback(
|
||||
(pageId: string, referenceId: string) => {
|
||||
const page = docCollection?.getDoc(pageId);
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
const text = page.Text.fromDelta([
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
reference: {
|
||||
type: 'Subpage',
|
||||
pageId: referenceId,
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
const [frame] = page.getBlockByFlavour('affine:note');
|
||||
|
||||
frame && page.addBlock('affine:paragraph', { text }, frame.id);
|
||||
},
|
||||
[docCollection]
|
||||
);
|
||||
|
||||
return {
|
||||
addReferenceLink,
|
||||
};
|
||||
}
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
import { toast } from '@affine/component';
|
||||
import {
|
||||
PreconditionStrategy,
|
||||
registerAffineCommand,
|
||||
} from '@affine/core/commands';
|
||||
import { openInfoModalAtom } from '@affine/core/components/atoms';
|
||||
import type { Editor } from '@affine/core/modules/editor';
|
||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import { EdgelessIcon, HistoryIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
DocService,
|
||||
useLiveData,
|
||||
useService,
|
||||
WorkspaceService,
|
||||
} from '@toeverything/infra';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { pageHistoryModalAtom } from '../../../components/atoms/page-history';
|
||||
import { useBlockSuiteMetaHelper } from './use-block-suite-meta-helper';
|
||||
import { useExportPage } from './use-export-page';
|
||||
import { useTrashModalHelper } from './use-trash-modal-helper';
|
||||
|
||||
export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
|
||||
const doc = useService(DocService).doc;
|
||||
const docId = doc.id;
|
||||
const mode = useLiveData(editor.mode$);
|
||||
const t = useI18n();
|
||||
const workspace = useService(WorkspaceService).workspace;
|
||||
|
||||
const favAdapter = useService(CompatibleFavoriteItemsAdapter);
|
||||
const favorite = useLiveData(favAdapter.isFavorite$(docId, 'doc'));
|
||||
const trash = useLiveData(doc.trash$);
|
||||
|
||||
const setPageHistoryModalState = useSetAtom(pageHistoryModalAtom);
|
||||
const setInfoModalState = useSetAtom(openInfoModalAtom);
|
||||
|
||||
const openHistoryModal = useCallback(() => {
|
||||
setPageHistoryModalState(() => ({
|
||||
pageId: docId,
|
||||
open: true,
|
||||
}));
|
||||
}, [docId, setPageHistoryModalState]);
|
||||
|
||||
const openInfoModal = useCallback(() => {
|
||||
setInfoModalState(true);
|
||||
}, [setInfoModalState]);
|
||||
|
||||
const { duplicate } = useBlockSuiteMetaHelper();
|
||||
const exportHandler = useExportPage();
|
||||
const { setTrashModal } = useTrashModalHelper();
|
||||
const onClickDelete = useCallback(
|
||||
(title: string) => {
|
||||
setTrashModal({
|
||||
open: true,
|
||||
pageIds: [docId],
|
||||
pageTitles: [title],
|
||||
});
|
||||
},
|
||||
[docId, setTrashModal]
|
||||
);
|
||||
|
||||
const isCloudWorkspace = workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
|
||||
|
||||
useEffect(() => {
|
||||
const unsubs: Array<() => void> = [];
|
||||
const preconditionStrategy = () =>
|
||||
PreconditionStrategy.InPaperOrEdgeless && !trash;
|
||||
|
||||
// TODO(@Peng): add back when edgeless presentation is ready
|
||||
|
||||
// this is pretty hack and easy to break. need a better way to communicate with blocksuite editor
|
||||
// unsubs.push(
|
||||
// registerAffineCommand({
|
||||
// id: 'editor:edgeless-presentation-start',
|
||||
// preconditionStrategy: () => PreconditionStrategy.InEdgeless && !trash,
|
||||
// category: 'editor:edgeless',
|
||||
// icon: <EdgelessIcon />,
|
||||
// label: t['com.affine.cmdk.affine.editor.edgeless.presentation-start'](),
|
||||
// run() {
|
||||
// document
|
||||
// .querySelector<HTMLElement>('edgeless-toolbar')
|
||||
// ?.shadowRoot?.querySelector<HTMLElement>(
|
||||
// '.edgeless-toolbar-left-part > edgeless-tool-icon-button:last-child'
|
||||
// )
|
||||
// ?.click();
|
||||
// },
|
||||
// })
|
||||
// );
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-view-info`,
|
||||
preconditionStrategy: () =>
|
||||
PreconditionStrategy.InPaperOrEdgeless && !trash,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['com.affine.page-properties.page-info.view'](),
|
||||
run() {
|
||||
track.$.cmdk.docInfo.open();
|
||||
|
||||
openInfoModal();
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-${favorite ? 'remove-from' : 'add-to'}-favourites`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: favorite
|
||||
? t['com.affine.favoritePageOperation.remove']()
|
||||
: t['com.affine.favoritePageOperation.add'](),
|
||||
run() {
|
||||
favAdapter.toggle(docId, 'doc');
|
||||
track.$.cmdk.editor.toggleFavorite();
|
||||
|
||||
toast(
|
||||
favorite
|
||||
? t['com.affine.cmdk.affine.editor.remove-from-favourites']()
|
||||
: t['com.affine.cmdk.affine.editor.add-to-favourites']()
|
||||
);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-convert-to-${
|
||||
mode === 'page' ? 'edgeless' : 'page'
|
||||
}`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: `${t['Convert to ']()}${
|
||||
mode === 'page'
|
||||
? t['com.affine.pageMode.edgeless']()
|
||||
: t['com.affine.pageMode.page']()
|
||||
}`,
|
||||
run() {
|
||||
track.$.cmdk.editor.switchPageMode({
|
||||
mode: mode === 'page' ? 'edgeless' : 'page',
|
||||
});
|
||||
|
||||
editor.toggleMode();
|
||||
toast(
|
||||
mode === 'page'
|
||||
? t['com.affine.toastMessage.edgelessMode']()
|
||||
: t['com.affine.toastMessage.pageMode']()
|
||||
);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// TODO(@Peng): should not show duplicate for journal
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-duplicate`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['com.affine.header.option.duplicate'](),
|
||||
run() {
|
||||
duplicate(docId);
|
||||
track.$.cmdk.editor.createDoc({
|
||||
control: 'duplicate',
|
||||
});
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-export-to-pdf`,
|
||||
preconditionStrategy: () => mode === 'page' && !trash,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['Export to PDF'](),
|
||||
async run() {
|
||||
track.$.cmdk.editor.export({
|
||||
type: 'pdf',
|
||||
});
|
||||
|
||||
exportHandler('pdf');
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-export-to-html`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['Export to HTML'](),
|
||||
async run() {
|
||||
track.$.cmdk.editor.export({
|
||||
type: 'html',
|
||||
});
|
||||
|
||||
exportHandler('html');
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-export-to-png`,
|
||||
preconditionStrategy: () => mode === 'page' && !trash,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['Export to PNG'](),
|
||||
async run() {
|
||||
track.$.cmdk.editor.export({
|
||||
type: 'png',
|
||||
});
|
||||
|
||||
exportHandler('png');
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-export-to-markdown`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['Export to Markdown'](),
|
||||
async run() {
|
||||
track.$.cmdk.editor.export({
|
||||
type: 'markdown',
|
||||
});
|
||||
|
||||
exportHandler('markdown');
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-move-to-trash`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['com.affine.moveToTrash.title'](),
|
||||
run() {
|
||||
track.$.cmdk.editor.deleteDoc();
|
||||
|
||||
onClickDelete(doc.title$.value);
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-restore-from-trash`,
|
||||
preconditionStrategy: () =>
|
||||
PreconditionStrategy.InPaperOrEdgeless && trash,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['com.affine.cmdk.affine.editor.restore-from-trash'](),
|
||||
run() {
|
||||
track.$.cmdk.editor.restoreDoc();
|
||||
|
||||
doc.restoreFromTrash();
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
if (isCloudWorkspace) {
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-page-history`,
|
||||
category: `editor:${mode}`,
|
||||
icon: <HistoryIcon />,
|
||||
label: t['com.affine.cmdk.affine.editor.reveal-page-history-modal'](),
|
||||
run() {
|
||||
track.$.cmdk.docHistory.open();
|
||||
|
||||
openHistoryModal();
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: 'alert-ctrl-s',
|
||||
category: 'affine:general',
|
||||
preconditionStrategy: PreconditionStrategy.Never,
|
||||
keyBinding: {
|
||||
binding: '$mod+s',
|
||||
},
|
||||
label: '',
|
||||
icon: null,
|
||||
run() {
|
||||
toast(t['Save']());
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
return () => {
|
||||
unsubs.forEach(unsub => unsub());
|
||||
};
|
||||
}, [
|
||||
editor,
|
||||
favorite,
|
||||
mode,
|
||||
onClickDelete,
|
||||
exportHandler,
|
||||
t,
|
||||
trash,
|
||||
isCloudWorkspace,
|
||||
openHistoryModal,
|
||||
duplicate,
|
||||
favAdapter,
|
||||
docId,
|
||||
doc,
|
||||
openInfoModal,
|
||||
]);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user