diff --git a/packages/frontend/core/src/components/root-app-sidebar/index.tsx b/packages/frontend/core/src/components/root-app-sidebar/index.tsx index 593ffab8c958c..77ad4a406e4fb 100644 --- a/packages/frontend/core/src/components/root-app-sidebar/index.tsx +++ b/packages/frontend/core/src/components/root-app-sidebar/index.tsx @@ -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 => { > {t['Import']()} + } diff --git a/packages/frontend/core/src/components/root-app-sidebar/template-doc-entrance.tsx b/packages/frontend/core/src/components/root-app-sidebar/template-doc-entrance.tsx new file mode 100644 index 0000000000000..c2204a853e8df --- /dev/null +++ b/packages/frontend/core/src/components/root-app-sidebar/template-doc-entrance.tsx @@ -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 ( + } onClick={toggleMenu}> + + + + + } + /> + } + > + {t['Template']()} + + + ); +}; + +const CreateNewTemplateMenuItem = () => { + const t = useI18n(); + const docsService = useService(DocsService); + const workbench = useService(WorkbenchService).workbench; + + const createNewTemplate = useCallback( + (e: React.MouseEvent) => { + const record = docsService.createDoc({ isTemplate: true }); + workbench.openDoc(record.id, { at: inferOpenMode(e) }); + }, + [docsService, workbench] + ); + + return ( + } + onClick={createNewTemplate} + onAuxClick={createNewTemplate} + > + {t['com.affine.template-list.create-new']()} + + ); +}; diff --git a/packages/frontend/core/src/modules/doc/services/docs.ts b/packages/frontend/core/src/modules/doc/services/docs.ts index 202657a0b2f97..d4d45d82cc8e1 100644 --- a/packages/frontend/core/src/modules/doc/services/docs.ts +++ b/packages/frontend/core/src/modules/doc/services/docs.ts @@ -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; } diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index 2e0ed059db37d..4328b43249313 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -1631,6 +1631,7 @@ "com.affine.page-starter-bar.edgeless": "Edgeless", "Template": "Template", "com.affine.template-list.empty": "No template", + "com.affine.template-list.create-new": "Create new template", "com.affine.settings.workspace.template.title": "My Templates", "com.affine.settings.workspace.template.journal": "Template for journal", "com.affine.settings.workspace.template.journal-desc": "Select a template for your journal",