mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
feat(core): sidebar template doc entrance (#9676)
close AF-2048, AF-2050, AF-2049
This commit is contained in:
@@ -46,6 +46,7 @@ import {
|
||||
workspaceWrapper,
|
||||
} from './index.css';
|
||||
import { AppSidebarJournalButton } from './journal-button';
|
||||
import { TemplateDocEntrance } from './template-doc-entrance';
|
||||
import { TrashButton } from './trash-button';
|
||||
import { UpdaterButton } from './updater-button';
|
||||
import { UserInfo } from './user-info';
|
||||
@@ -192,6 +193,7 @@ export const RootAppSidebar = memo((): ReactElement => {
|
||||
>
|
||||
<span data-testid="import-modal-trigger">{t['Import']()}</span>
|
||||
</MenuItem>
|
||||
<TemplateDocEntrance />
|
||||
<ExternalMenuLinkItem
|
||||
href="https://affine.pro/blog?tag=Release+Note"
|
||||
icon={<JournalIcon />}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { Menu, MenuItem, MenuSeparator } from '@affine/component';
|
||||
import { MenuItem as SidebarMenuItem } from '@affine/core/modules/app-sidebar/views';
|
||||
import { DocsService } from '@affine/core/modules/doc';
|
||||
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
|
||||
import { TemplateListMenuContentScrollable } from '@affine/core/modules/template-doc';
|
||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||
import { inferOpenMode } from '@affine/core/utils';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { TemplateIcon, TemplateOutlineIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { useAsyncCallback } from '../hooks/affine-async-hooks';
|
||||
|
||||
export const TemplateDocEntrance = () => {
|
||||
const t = useI18n();
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const docsService = useService(DocsService);
|
||||
const featureFlagService = useService(FeatureFlagService);
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
const enabled = useLiveData(featureFlagService.flags.enable_template_doc.$);
|
||||
|
||||
const toggleMenu = useCallback(() => {
|
||||
setMenuOpen(prev => !prev);
|
||||
}, []);
|
||||
|
||||
const createDocFromTemplate = useAsyncCallback(
|
||||
async (templateId: string) => {
|
||||
const docId = await docsService.duplicateFromTemplate(templateId);
|
||||
workbench.openDoc(docId);
|
||||
},
|
||||
[docsService, workbench]
|
||||
);
|
||||
|
||||
if (!enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarMenuItem icon={<TemplateOutlineIcon />} onClick={toggleMenu}>
|
||||
<Menu
|
||||
rootOptions={{ open: menuOpen, onOpenChange: setMenuOpen }}
|
||||
contentOptions={{
|
||||
side: 'right',
|
||||
align: 'end',
|
||||
alignOffset: -4,
|
||||
sideOffset: 16,
|
||||
}}
|
||||
items={
|
||||
<TemplateListMenuContentScrollable
|
||||
onSelect={createDocFromTemplate}
|
||||
suffixItems={
|
||||
<>
|
||||
<MenuSeparator />
|
||||
<CreateNewTemplateMenuItem />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span>{t['Template']()}</span>
|
||||
</Menu>
|
||||
</SidebarMenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
const CreateNewTemplateMenuItem = () => {
|
||||
const t = useI18n();
|
||||
const docsService = useService(DocsService);
|
||||
const workbench = useService(WorkbenchService).workbench;
|
||||
|
||||
const createNewTemplate = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
const record = docsService.createDoc({ isTemplate: true });
|
||||
workbench.openDoc(record.id, { at: inferOpenMode(e) });
|
||||
},
|
||||
[docsService, workbench]
|
||||
);
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
prefixIcon={<TemplateIcon />}
|
||||
onClick={createNewTemplate}
|
||||
onAuxClick={createNewTemplate}
|
||||
>
|
||||
{t['com.affine.template-list.create-new']()}
|
||||
</MenuItem>
|
||||
);
|
||||
};
|
||||
@@ -102,6 +102,7 @@ export class DocsService extends Service {
|
||||
options: {
|
||||
primaryMode?: DocMode;
|
||||
docProps?: DocProps;
|
||||
isTemplate?: boolean;
|
||||
} = {}
|
||||
) {
|
||||
const doc = this.store.createBlockSuiteDoc();
|
||||
@@ -114,6 +115,9 @@ export class DocsService extends Service {
|
||||
if (options.primaryMode) {
|
||||
docRecord.setPrimaryMode(options.primaryMode);
|
||||
}
|
||||
if (options.isTemplate) {
|
||||
docRecord.setProperty('isTemplate', true);
|
||||
}
|
||||
this.eventBus.emit(DocCreated, docRecord);
|
||||
return docRecord;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user