mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-22 20:46:38 +08:00
chore(core): remove snapshot import export feature flag (#8865)
This commit is contained in:
@@ -11,11 +11,7 @@ import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/us
|
||||
import { useEnableCloud } from '@affine/core/components/hooks/affine/use-enable-cloud';
|
||||
import { useExportPage } from '@affine/core/components/hooks/affine/use-export-page';
|
||||
import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-page-meta';
|
||||
import {
|
||||
Export,
|
||||
MoveToTrash,
|
||||
Snapshot,
|
||||
} from '@affine/core/components/page-list';
|
||||
import { Export, MoveToTrash } from '@affine/core/components/page-list';
|
||||
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
|
||||
import { useDetailPageHeaderResponsive } from '@affine/core/desktop/pages/workspace/detail-page/use-header-responsive';
|
||||
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
|
||||
@@ -44,7 +40,6 @@ import {
|
||||
TocIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import {
|
||||
FeatureFlagService,
|
||||
useLiveData,
|
||||
useService,
|
||||
useServiceOptional,
|
||||
@@ -84,10 +79,6 @@ export const PageHeaderMenuButton = ({
|
||||
const primaryMode = useLiveData(editorService.editor.doc.primaryMode$);
|
||||
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const featureFlagService = useService(FeatureFlagService);
|
||||
const enableSnapshotImportExport = useLiveData(
|
||||
featureFlagService.flags.enable_snapshot_import_export.$
|
||||
);
|
||||
const openInAppService = useServiceOptional(OpenInAppService);
|
||||
|
||||
const { favorite, toggleFavorite } = useFavorite(pageId);
|
||||
@@ -402,7 +393,6 @@ export const PageHeaderMenuButton = ({
|
||||
{t['Import']()}
|
||||
</MenuItem>
|
||||
<Export exportHandler={exportHandler} pageMode={currentMode} />
|
||||
{enableSnapshotImportExport && <Snapshot />}
|
||||
<MenuSeparator />
|
||||
<MoveToTrash
|
||||
data-testid="editor-option-menu-delete"
|
||||
|
||||
+17
@@ -260,6 +260,23 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-export-to-snapshot`,
|
||||
preconditionStrategy,
|
||||
category: `editor:${mode}`,
|
||||
icon: mode === 'page' ? <PageIcon /> : <EdgelessIcon />,
|
||||
label: t['Export to Snapshot'](),
|
||||
async run() {
|
||||
track.$.cmdk.editor.export({
|
||||
type: 'snapshot',
|
||||
});
|
||||
|
||||
exportHandler('snapshot');
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-move-to-trash`,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
ExportToHtmlIcon,
|
||||
ExportToMarkdownIcon,
|
||||
ExportToPngIcon,
|
||||
PageIcon,
|
||||
PrinterIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import type { ReactNode } from 'react';
|
||||
@@ -22,7 +23,9 @@ interface ExportMenuItemProps<T> {
|
||||
}
|
||||
|
||||
interface ExportProps {
|
||||
exportHandler: (type: 'pdf' | 'html' | 'png' | 'markdown') => void;
|
||||
exportHandler: (
|
||||
type: 'pdf' | 'html' | 'png' | 'markdown' | 'snapshot'
|
||||
) => void;
|
||||
pageMode?: 'page' | 'edgeless';
|
||||
className?: string;
|
||||
}
|
||||
@@ -94,6 +97,13 @@ export const ExportMenuItems = ({
|
||||
icon={<ExportToMarkdownIcon />}
|
||||
label={t['Export to Markdown']()}
|
||||
/>
|
||||
<ExportMenuItem
|
||||
onSelect={() => exportHandler('snapshot')}
|
||||
className={className}
|
||||
type="snapshot"
|
||||
icon={<PageIcon />}
|
||||
label={t['Export to Snapshot']()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,4 +2,3 @@ export * from './disable-public-sharing';
|
||||
export * from './export';
|
||||
// export * from './MoveTo';
|
||||
export * from './move-to-trash';
|
||||
export * from './snapshot';
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
import { MenuItem, MenuSeparator, MenuSub, notify } from '@affine/component';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import track from '@affine/track';
|
||||
import { openFileOrFiles, ZipTransformer } from '@blocksuite/affine/blocks';
|
||||
import type { Doc } from '@blocksuite/affine/store';
|
||||
import { ExportIcon, ImportIcon, ToneIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
FeatureFlagService,
|
||||
useService,
|
||||
WorkspaceService,
|
||||
} from '@toeverything/infra';
|
||||
import { type ReactNode, useCallback } from 'react';
|
||||
|
||||
import { useExportPage } from '../../hooks/affine/use-export-page';
|
||||
import { useAsyncCallback } from '../../hooks/affine-async-hooks';
|
||||
import { transitionStyle } from './index.css';
|
||||
|
||||
interface SnapshotMenuItemsProps {
|
||||
snapshotActionHandler: (action: 'import' | 'export' | 'disable') => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface SnapshotMenuItemProps<T> {
|
||||
onSelect: () => void;
|
||||
className?: string;
|
||||
type: T;
|
||||
icon: ReactNode;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface SnapshotProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function SnapshotMenuItem<T>({
|
||||
onSelect,
|
||||
className,
|
||||
type,
|
||||
icon,
|
||||
label,
|
||||
}: SnapshotMenuItemProps<T>) {
|
||||
return (
|
||||
<MenuItem
|
||||
className={className}
|
||||
data-testid={`snapshot-${type}`}
|
||||
onSelect={onSelect}
|
||||
block
|
||||
prefixIcon={icon}
|
||||
>
|
||||
{label}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
export const DisableSnapshotMenuItems = ({
|
||||
snapshotActionHandler,
|
||||
className = transitionStyle,
|
||||
}: SnapshotMenuItemsProps) => {
|
||||
const t = useI18n();
|
||||
return (
|
||||
<SnapshotMenuItem
|
||||
onSelect={() => snapshotActionHandler('disable')}
|
||||
className={className}
|
||||
type="disable"
|
||||
icon={<ToneIcon />}
|
||||
label={t['Disable Snapshot']()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const SnapshotMenuItems = ({
|
||||
snapshotActionHandler,
|
||||
className = transitionStyle,
|
||||
}: SnapshotMenuItemsProps) => {
|
||||
const t = useI18n();
|
||||
return (
|
||||
<>
|
||||
<SnapshotMenuItem
|
||||
onSelect={() => snapshotActionHandler('import')}
|
||||
className={className}
|
||||
type="import"
|
||||
icon={<ImportIcon />}
|
||||
label={t['Import']()}
|
||||
/>
|
||||
<SnapshotMenuItem
|
||||
onSelect={() => snapshotActionHandler('export')}
|
||||
className={className}
|
||||
type="export"
|
||||
icon={<ExportIcon />}
|
||||
label={t['Export']()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Snapshot = ({ className }: SnapshotProps) => {
|
||||
const t = useI18n();
|
||||
const workspace = useService(WorkspaceService).workspace;
|
||||
const docCollection = workspace.docCollection;
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const exportHandler = useExportPage();
|
||||
const featureFlagService = useService(FeatureFlagService);
|
||||
|
||||
const importSnapshot = useCallback(async () => {
|
||||
try {
|
||||
const file = await openFileOrFiles({ acceptType: 'Zip' });
|
||||
if (!file) return null;
|
||||
|
||||
track.$.header.snapshot.import({
|
||||
type: 'snapshot',
|
||||
status: 'importing',
|
||||
});
|
||||
|
||||
const importedDocs = (
|
||||
await ZipTransformer.importDocs(docCollection, file)
|
||||
).filter(doc => doc !== undefined);
|
||||
if (importedDocs.length === 0) {
|
||||
notify.error({
|
||||
title: 'Import Snapshot Failed',
|
||||
message: 'No valid documents found in the imported file.',
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
notify.success({
|
||||
title: 'Imported Snapshot Successfully',
|
||||
message: `Imported ${importedDocs.length} doc(s)`,
|
||||
});
|
||||
track.$.header.snapshot.import({
|
||||
type: 'snapshot',
|
||||
status: 'success',
|
||||
result: {
|
||||
docCount: importedDocs.length,
|
||||
},
|
||||
});
|
||||
return importedDocs;
|
||||
} catch (error) {
|
||||
console.error('Error importing snapshot:', error);
|
||||
notify.error({
|
||||
title: 'Import Snapshot Failed',
|
||||
message: 'Failed to import snapshot. Please try again.',
|
||||
});
|
||||
track.$.header.snapshot.import({
|
||||
type: 'snapshot',
|
||||
status: 'failed',
|
||||
error: error instanceof Error ? error.message : undefined,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}, [docCollection]);
|
||||
|
||||
const openImportedDocs = useCallback(
|
||||
(importedDocs: Doc[]) => {
|
||||
if (importedDocs.length > 1) {
|
||||
workbench.openAll();
|
||||
} else if (importedDocs[0]?.id) {
|
||||
workbench.openDoc(importedDocs[0].id);
|
||||
}
|
||||
},
|
||||
[workbench]
|
||||
);
|
||||
|
||||
const handleImportSnapshot = useAsyncCallback(async () => {
|
||||
const importedDocs = await importSnapshot();
|
||||
if (importedDocs) {
|
||||
openImportedDocs(importedDocs);
|
||||
track.$.header.docOptions.import();
|
||||
track.$.header.actions.createDoc({
|
||||
control: 'import',
|
||||
});
|
||||
}
|
||||
}, [importSnapshot, openImportedDocs]);
|
||||
|
||||
const disableSnapshotActionOption = useCallback(() => {
|
||||
featureFlagService.flags.enable_snapshot_import_export.set(false);
|
||||
}, [featureFlagService]);
|
||||
|
||||
const snapshotActionHandler = useCallback(
|
||||
(action: 'import' | 'export' | 'disable') => {
|
||||
switch (action) {
|
||||
case 'import':
|
||||
return handleImportSnapshot();
|
||||
case 'export':
|
||||
track.$.header.snapshot.export({
|
||||
type: 'snapshot',
|
||||
});
|
||||
return exportHandler('snapshot');
|
||||
case 'disable':
|
||||
return disableSnapshotActionOption();
|
||||
}
|
||||
},
|
||||
[handleImportSnapshot, exportHandler, disableSnapshotActionOption]
|
||||
);
|
||||
|
||||
const items = (
|
||||
<>
|
||||
<SnapshotMenuItems
|
||||
snapshotActionHandler={snapshotActionHandler}
|
||||
className={className}
|
||||
/>
|
||||
<MenuSeparator />
|
||||
<DisableSnapshotMenuItems
|
||||
snapshotActionHandler={snapshotActionHandler}
|
||||
className={className}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<MenuSub
|
||||
items={items}
|
||||
triggerOptions={{
|
||||
className: transitionStyle,
|
||||
prefixIcon: <ToneIcon />,
|
||||
'data-testid': 'snapshot-menu',
|
||||
}}
|
||||
subOptions={{}}
|
||||
>
|
||||
{t['Snapshot']()}
|
||||
</MenuSub>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user