mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-20 19:46:32 +08:00
init: the first public commit for AFFiNE
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { FC, useRef, useEffect, useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
|
||||
import { BackLink, TextProps } from '@toeverything/components/common';
|
||||
import {
|
||||
RenderBlockChildren,
|
||||
BlockPendantProvider,
|
||||
} from '@toeverything/components/editor-core';
|
||||
import { ContentColumnValue } from '@toeverything/datasource/db-service';
|
||||
import { CreateView } from '@toeverything/framework/virgo';
|
||||
import { Theme, styled } from '@toeverything/components/ui';
|
||||
|
||||
import {
|
||||
TextManage,
|
||||
type ExtendedTextUtils,
|
||||
} from '../../components/text-manage';
|
||||
|
||||
export const PageView: FC<CreateView> = ({ block, editor }) => {
|
||||
const { workspace_id } = useParams();
|
||||
const textRef = useRef<ExtendedTextUtils>(null);
|
||||
const [backLinks, setBackLinks] =
|
||||
useState<Awaited<ReturnType<typeof editor.search>>>();
|
||||
|
||||
const properties = useMemo(() => block.getProperties(), [block]);
|
||||
const onTextEnter: TextProps['handleEnter'] = async props => {
|
||||
const { splitContents } = props;
|
||||
if (!splitContents) {
|
||||
return false;
|
||||
}
|
||||
const { contentBeforeSelection, contentAfterSelection } = splitContents;
|
||||
const before = [...contentBeforeSelection.content];
|
||||
const after = [...contentAfterSelection.content];
|
||||
|
||||
const firstChild = await block.firstChild();
|
||||
const maybeGroupBlock =
|
||||
firstChild && firstChild.type === 'group' ? firstChild : null;
|
||||
const groupBlock =
|
||||
maybeGroupBlock ?? (await editor.createBlock('group', block.id));
|
||||
if (!groupBlock) {
|
||||
throw new Error('Failed to create group block');
|
||||
}
|
||||
|
||||
const childBlock = await editor.createBlock('text', groupBlock.id);
|
||||
if (!childBlock) {
|
||||
throw new Error('Failed to create text block');
|
||||
}
|
||||
await childBlock.setProperties({
|
||||
text: { value: after } as ContentColumnValue,
|
||||
});
|
||||
|
||||
await block.setProperties({
|
||||
text: { value: before } as ContentColumnValue,
|
||||
});
|
||||
await groupBlock.prepend(childBlock);
|
||||
editor.selectionManager.activeNodeByNodeId(childBlock.id);
|
||||
return true;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// const title = properties['text']?.value?.[0]?.text;
|
||||
// if (!title || !title.trim()) {
|
||||
// try {
|
||||
// const startSelection = text_ref.current.getStartSelection();
|
||||
// text_ref.current.setSelection(startSelection);
|
||||
// } catch (error) {
|
||||
// console.error(error);
|
||||
// }
|
||||
// }
|
||||
}, [properties]);
|
||||
|
||||
useEffect(() => {
|
||||
editor
|
||||
.search({ tag: `reference:${block.id}` })
|
||||
.then(blocks => setBackLinks(blocks));
|
||||
}, [block.id, editor]);
|
||||
|
||||
useEffect(() => {
|
||||
// auto focus page title by default
|
||||
editor.selectionManager.activeNodeByNodeId(block.id, 'end');
|
||||
}, [block.id, editor]);
|
||||
|
||||
return (
|
||||
<PageTitleBlock>
|
||||
<BlockPendantProvider block={block}>
|
||||
<TextManage
|
||||
alwaysShowPlaceholder
|
||||
ref={textRef}
|
||||
className={'title'}
|
||||
supportMarkdown={true}
|
||||
handleEnter={onTextEnter}
|
||||
placeholder={'Untitled'}
|
||||
block={block}
|
||||
editor={editor}
|
||||
/>
|
||||
</BlockPendantProvider>
|
||||
|
||||
{/* TODO: add back multi block select */}
|
||||
{/* <div
|
||||
contentEditable
|
||||
className={style9(styles.content)}
|
||||
suppressContentEditableWarning
|
||||
> */}
|
||||
<BackLink blocks={backLinks} workspaceId={workspace_id} />
|
||||
{/*{block.childrenIds.map(childId => (*/}
|
||||
{/* <RenderBlock key={childId} blockId={childId} />*/}
|
||||
{/*))}*/}
|
||||
<RenderBlockChildren block={block} />
|
||||
</PageTitleBlock>
|
||||
);
|
||||
};
|
||||
|
||||
const PageTitleBlock = styled('div')({
|
||||
'.title': {
|
||||
fontSize: Theme.typography.page.fontSize,
|
||||
lineHeight: Theme.typography.page.lineHeight,
|
||||
},
|
||||
'.content': {
|
||||
outline: 'none',
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,55 @@
|
||||
import { withRecastTable } from '@toeverything/components/editor-core';
|
||||
import {
|
||||
Protocol,
|
||||
DefaultColumnsValue,
|
||||
} from '@toeverything/datasource/db-service';
|
||||
import {
|
||||
AsyncBlock,
|
||||
BaseView,
|
||||
ChildrenView,
|
||||
getTextHtml,
|
||||
getTextProperties,
|
||||
SelectBlock,
|
||||
} from '@toeverything/framework/virgo';
|
||||
|
||||
import { PageView } from './PageView';
|
||||
import { ComponentType, FC } from 'react';
|
||||
|
||||
export const PageChildrenView: FC<ChildrenView> = props => props.children;
|
||||
|
||||
export class PageBlock extends BaseView {
|
||||
type = Protocol.Block.Type.page;
|
||||
View = withRecastTable(PageView);
|
||||
// override ChildrenView = withRecastTable(PageChildrenView);
|
||||
public override allowPendant = false;
|
||||
override async onCreate(block: AsyncBlock): Promise<AsyncBlock> {
|
||||
if (!block.getProperty('text')) {
|
||||
await block.setProperty('text', {
|
||||
value: [{ text: '' }],
|
||||
});
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
override onExport(content: any): string {
|
||||
return this.get_decoration<any>(content, 'text')?.value?.[0].text;
|
||||
}
|
||||
|
||||
override getSelProperties(
|
||||
block: AsyncBlock,
|
||||
selectInfo: any
|
||||
): DefaultColumnsValue {
|
||||
const properties = super.getSelProperties(block, selectInfo);
|
||||
return getTextProperties(properties, selectInfo);
|
||||
}
|
||||
|
||||
override async block2html(
|
||||
block: AsyncBlock,
|
||||
children: SelectBlock[],
|
||||
generateHtml: (el: any[]) => Promise<string>
|
||||
): Promise<string> {
|
||||
const content = getTextHtml(block);
|
||||
const childrenContent = await generateHtml(children);
|
||||
return `<h1>${content}</h1> ${childrenContent}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { CustomText } from '@toeverything/components/common';
|
||||
export interface PageProperties {
|
||||
text: CustomText[];
|
||||
}
|
||||
Reference in New Issue
Block a user