@@ -9,9 +9,14 @@ export class TemplateDocSetting extends Entity {
|
||||
|
||||
loading$ = this.store.watchIsLoading();
|
||||
setting$ = this.store.watchSetting();
|
||||
enablePageTemplate$ = this.store.watchSettingKey('enablePageTemplate');
|
||||
pageTemplateDocId$ = this.store.watchSettingKey('pageTemplateId');
|
||||
journalTemplateDocId$ = this.store.watchSettingKey('journalTemplateId');
|
||||
|
||||
togglePageTemplate(enable: boolean) {
|
||||
this.store.updateSetting('enablePageTemplate', enable);
|
||||
}
|
||||
|
||||
updatePageTemplateDocId(id?: string) {
|
||||
this.store.updateSetting('pageTemplateId', id);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ export class TemplateDocSettingStore extends Store {
|
||||
) {
|
||||
const db = this.dbService.userdataDB$.value;
|
||||
const prev = db.settings.find({ key: this.key })[0]?.value ?? {};
|
||||
db.settings.update(this.key, {
|
||||
db.settings.create({
|
||||
key: this.key,
|
||||
value: { ...prev, [key]: value },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export type TemplateDocSettings = {
|
||||
enablePageTemplate?: boolean;
|
||||
pageTemplateId?: string;
|
||||
journalTemplateId?: string;
|
||||
};
|
||||
|
||||
@@ -1,39 +1,13 @@
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const list = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 4,
|
||||
minWidth: 250,
|
||||
maxWidth: 355,
|
||||
});
|
||||
|
||||
export const item = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
padding: 4,
|
||||
});
|
||||
|
||||
export const itemIcon = style({
|
||||
fontSize: 20,
|
||||
lineHeight: 0,
|
||||
color: cssVarV2.icon.primary,
|
||||
});
|
||||
|
||||
export const itemText = style({
|
||||
width: 0,
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
lineHeight: '22px',
|
||||
color: cssVarV2.text.primary,
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
});
|
||||
|
||||
export const menuContent = style({
|
||||
width: 280,
|
||||
paddingRight: 0,
|
||||
});
|
||||
export const scrollableViewport = style({
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
import { Menu, MenuItem, type MenuProps, Scrollable } from '@affine/component';
|
||||
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { type PropsWithChildren, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { type DocRecord, DocsService } from '../../doc';
|
||||
import { type DocRecord } from '../../doc';
|
||||
import { DocDisplayMetaService } from '../../doc-display-meta';
|
||||
import { TemplateDocService } from '../services/template-doc';
|
||||
import * as styles from './styles.css';
|
||||
interface CommonProps {
|
||||
target?: string;
|
||||
onSelect?: (docId: string) => void;
|
||||
}
|
||||
|
||||
interface DocItemProps extends CommonProps {
|
||||
doc: DocRecord;
|
||||
}
|
||||
|
||||
const DocItem = ({ doc, target }: DocItemProps) => {
|
||||
const DocItem = ({ doc, onSelect }: DocItemProps) => {
|
||||
const docDisplayService = useService(DocDisplayMetaService);
|
||||
const Icon = useLiveData(docDisplayService.icon$(doc.id));
|
||||
const title = useLiveData(docDisplayService.title$(doc.id));
|
||||
const docsService = useService(DocsService);
|
||||
|
||||
const onClick = useAsyncCallback(async () => {
|
||||
await docsService.duplicateFromTemplate(doc.id, target);
|
||||
}, [doc.id, docsService, target]);
|
||||
onSelect?.(doc.id);
|
||||
}, [doc.id, onSelect]);
|
||||
|
||||
return (
|
||||
<MenuItem onClick={onClick} style={{ padding: 0 }}>
|
||||
<li className={styles.item}>
|
||||
<Icon className={styles.itemIcon} />
|
||||
<span className={styles.itemText}>{title}</span>
|
||||
</li>
|
||||
<MenuItem prefixIcon={<Icon />} onClick={onClick}>
|
||||
{title}
|
||||
</MenuItem>
|
||||
);
|
||||
};
|
||||
|
||||
export const TemplateListMenuContent = ({ target }: CommonProps) => {
|
||||
interface TemplateListMenuContentProps extends CommonProps {
|
||||
prefixItems?: React.ReactNode;
|
||||
suffixItems?: React.ReactNode;
|
||||
}
|
||||
export const TemplateListMenuContent = ({
|
||||
prefixItems,
|
||||
suffixItems,
|
||||
...props
|
||||
}: TemplateListMenuContentProps) => {
|
||||
const templateDocService = useService(TemplateDocService);
|
||||
const [templateDocs] = useState(() =>
|
||||
templateDocService.list.getTemplateDocs()
|
||||
@@ -43,33 +47,48 @@ export const TemplateListMenuContent = ({ target }: CommonProps) => {
|
||||
|
||||
return (
|
||||
<ul className={styles.list}>
|
||||
{prefixItems}
|
||||
{templateDocs.map(doc => (
|
||||
<DocItem key={doc.id} doc={doc} target={target} />
|
||||
<DocItem key={doc.id} doc={doc} {...props} />
|
||||
))}
|
||||
{suffixItems}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
export const TemplateListMenuContentScrollable = ({ target }: CommonProps) => {
|
||||
export const TemplateListMenuContentScrollable = (
|
||||
props: TemplateListMenuContentProps
|
||||
) => {
|
||||
return (
|
||||
<Scrollable.Root>
|
||||
<Scrollable.Scrollbar />
|
||||
<Scrollable.Viewport className={styles.scrollableViewport}>
|
||||
<TemplateListMenuContent target={target} />
|
||||
<TemplateListMenuContent {...props} />
|
||||
</Scrollable.Viewport>
|
||||
</Scrollable.Root>
|
||||
);
|
||||
};
|
||||
|
||||
interface TemplateListMenuProps
|
||||
extends TemplateListMenuContentProps,
|
||||
Omit<MenuProps, 'items'> {}
|
||||
export const TemplateListMenu = ({
|
||||
children,
|
||||
target,
|
||||
onSelect,
|
||||
prefixItems,
|
||||
suffixItems,
|
||||
contentOptions,
|
||||
...otherProps
|
||||
}: PropsWithChildren<CommonProps> & Omit<MenuProps, 'items'>) => {
|
||||
}: TemplateListMenuProps) => {
|
||||
return (
|
||||
<Menu
|
||||
items={<TemplateListMenuContentScrollable target={target} />}
|
||||
items={
|
||||
<TemplateListMenuContentScrollable
|
||||
onSelect={onSelect}
|
||||
prefixItems={prefixItems}
|
||||
suffixItems={suffixItems}
|
||||
/>
|
||||
}
|
||||
contentOptions={{
|
||||
...contentOptions,
|
||||
className: styles.menuContent,
|
||||
|
||||
Reference in New Issue
Block a user