From 6527bae7e46a14a6f4bc253e712e8917a4b977cd Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 30 Mar 2024 14:59:28 +0800 Subject: [PATCH 1/9] refactor: Transclusion -> Transclude --- .../language/en-GB/Translations.multids | 8 ++++---- .../language/zh-Hans/Translations.multids | 8 ++++---- .../tldraw/shapes/transclude/component.tsx | 16 ++++++++-------- .../tldraw/shapes/transclude/style.css | 8 ++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/tw-whiteboard/language/en-GB/Translations.multids b/src/tw-whiteboard/language/en-GB/Translations.multids index 99c2444..bfe601d 100644 --- a/src/tw-whiteboard/language/en-GB/Translations.multids +++ b/src/tw-whiteboard/language/en-GB/Translations.multids @@ -3,7 +3,7 @@ title: $:/plugins/linonetwo/tw-whiteboard/language/en-GB/ Name: Whiteboard Description: Tiny little drawing app in TW, based on tldraw. Providing diagram widget and whiteboard view. Configs/Description: These settings let you customise the behaviour of "Whiteboard" plugin. -Tools/Transclusion/PlaceHolder: Tiddler title transclude -Tools/Transclusion/NoTiddlerTitle: Tiddler title not filled -Tools/Transclusion/TiddlerMissing: Tiddler missing -Tools/Transclusion/NoTextOnField: No text on field \ No newline at end of file +Tools/Transclude/PlaceHolder: Tiddler title transclude +Tools/Transclude/NoTiddlerTitle: Tiddler title not filled +Tools/Transclude/TiddlerMissing: Tiddler missing +Tools/Transclude/NoTextOnField: No text on field \ No newline at end of file diff --git a/src/tw-whiteboard/language/zh-Hans/Translations.multids b/src/tw-whiteboard/language/zh-Hans/Translations.multids index ff33046..c74afd2 100644 --- a/src/tw-whiteboard/language/zh-Hans/Translations.multids +++ b/src/tw-whiteboard/language/zh-Hans/Translations.multids @@ -3,7 +3,7 @@ title: $:/plugins/linonetwo/tw-whiteboard/language/zh-Hans/ Name: 白板 Description: 太微白板应用,提供图表微件和白板视图,基于开源白板「TlDraw」 Configs/Description: 通过这些设置,您可以自定义「白板」插件的行为。 -Tools/Transclusion/PlaceHolder: 条目标题去嵌入 -Tools/Transclusion/NoTiddlerTitle: 未填条目标题 -Tools/Transclusion/TiddlerMissing: 条目不存在 -Tools/Transclusion/NoTextOnField: 条目此字段无文本内容 \ No newline at end of file +Tools/Transclude/PlaceHolder: 条目标题去嵌入 +Tools/Transclude/NoTiddlerTitle: 未填条目标题 +Tools/Transclude/TiddlerMissing: 条目不存在 +Tools/Transclude/NoTextOnField: 条目此字段无文本内容 \ No newline at end of file diff --git a/src/tw-whiteboard/tldraw/shapes/transclude/component.tsx b/src/tw-whiteboard/tldraw/shapes/transclude/component.tsx index a349fcf..259a682 100644 --- a/src/tw-whiteboard/tldraw/shapes/transclude/component.tsx +++ b/src/tw-whiteboard/tldraw/shapes/transclude/component.tsx @@ -19,11 +19,11 @@ export function TranscludeComponent({ shape, isDarkMode }: { isDarkMode: boolean const adjustedColor = shape.props.color === 'black' ? 'grey' : shape.props.color; const astNode = useMemo(() => { - if (!tiddlerTitle) return wrapTiddlerAst({ type: 'text', text: `${lingo('Tools/Transclusion/NoTiddlerTitle')}` }); + if (!tiddlerTitle) return wrapTiddlerAst({ type: 'text', text: `${lingo('Tools/Transclude/NoTiddlerTitle')}` }); const fields = $tw.wiki.getTiddler(tiddlerTitle)?.fields; - if (fields === undefined) return wrapTiddlerAst({ type: 'text', text: `${tiddlerTitle} ${lingo('Tools/Transclusion/TiddlerMissing')}` }); + if (fields === undefined) return wrapTiddlerAst({ type: 'text', text: `${tiddlerTitle} ${lingo('Tools/Transclude/TiddlerMissing')}` }); const text = fields?.[tiddlerField]; - if (!text) return wrapTiddlerAst({ type: 'text', text: `${tiddlerTitle} ${lingo('Tools/Transclusion/NoTextOnField')} ${tiddlerField}` }); + if (!text) return wrapTiddlerAst({ type: 'text', text: `${tiddlerTitle} ${lingo('Tools/Transclude/NoTextOnField')} ${tiddlerField}` }); const childTree = $tw.wiki.parseText(fields.type || 'text/vnd.tiddlywiki', String(text)).tree; return { type: 'tiddler', children: childTree }; }, [tiddlerField, tiddlerTitle]); @@ -50,9 +50,9 @@ export function TranscludeComponent({ shape, isDarkMode }: { isDarkMode: boolean }; return ( -
+
-
+

{tiddlerTitle}

-
Transclusion loading...
+
Transclude loading...
); diff --git a/src/tw-whiteboard/tldraw/shapes/transclude/style.css b/src/tw-whiteboard/tldraw/shapes/transclude/style.css index 9a70c01..dad85cf 100644 --- a/src/tw-whiteboard/tldraw/shapes/transclude/style.css +++ b/src/tw-whiteboard/tldraw/shapes/transclude/style.css @@ -1,8 +1,8 @@ -.transclusion-shape-component-outer { +.transclude-shape-component-outer { width: 100%; height: 100%; } -.transclusion-shape-component-inner { +.transclude-shape-component-inner { width: 100%; height: 100%; border: 1px solid rgba(0, 0, 0, 0.1); @@ -12,12 +12,12 @@ padding: 1em; overflow-y: auto; } -.transclusion-shape-component-inner.transclusion-shape-edit-mode { +.transclude-shape-component-inner.transclude-shape-edit-mode { display: flex; justify-content: center; align-items: center; } -.transclusion-shape-component-inner.transclusion-shape-edit-mode > input { +.transclude-shape-component-inner.transclude-shape-edit-mode > input { background: transparent; border: none; overflow-wrap: break-word; From 16e4a871bf4ea485573d657004c3e1abf6f36db7 Mon Sep 17 00:00:00 2001 From: lin onetwo Date: Sat, 30 Mar 2024 15:32:18 +0800 Subject: [PATCH 2/9] feat: simple wikitext note tool --- src/tw-whiteboard/components/App.tsx | 6 +- .../language/en-GB/Translations.multids | 4 +- .../language/zh-Hans/Translations.multids | 4 +- src/tw-whiteboard/tldraw/overrides.tsx | 13 +++- .../tldraw/shapes/note/component.tsx | 68 +++++++++++++++++++ .../tldraw/shapes/note/style.css | 27 ++++++++ src/tw-whiteboard/tldraw/shapes/note/tool.ts | 7 ++ src/tw-whiteboard/tldraw/shapes/note/type.ts | 3 + src/tw-whiteboard/tldraw/shapes/note/util.tsx | 46 +++++++++++++ .../tldraw/shapes/transclude/component.tsx | 6 +- .../tldraw/shapes/transclude/style.css | 1 + src/tw-whiteboard/utils/wrapTiddlerAst.ts | 5 +- 12 files changed, 181 insertions(+), 9 deletions(-) create mode 100644 src/tw-whiteboard/tldraw/shapes/note/component.tsx create mode 100644 src/tw-whiteboard/tldraw/shapes/note/style.css create mode 100644 src/tw-whiteboard/tldraw/shapes/note/tool.ts create mode 100644 src/tw-whiteboard/tldraw/shapes/note/type.ts create mode 100644 src/tw-whiteboard/tldraw/shapes/note/util.tsx diff --git a/src/tw-whiteboard/components/App.tsx b/src/tw-whiteboard/components/App.tsx index 81c211a..3427934 100644 --- a/src/tw-whiteboard/components/App.tsx +++ b/src/tw-whiteboard/components/App.tsx @@ -12,6 +12,8 @@ import './App.css'; import '@tldraw/tldraw/tldraw.css'; import { assetUrls } from '../tldraw/assets/formatedAssets'; import { overrides } from '../tldraw/overrides'; +import { NoteTool } from '../tldraw/shapes/note/tool'; +import { NoteShapeUtil } from '../tldraw/shapes/note/util'; import { TranscludeTool } from '../tldraw/shapes/transclude/tool'; import { TranscludeShapeUtil } from '../tldraw/shapes/transclude/util'; @@ -46,8 +48,8 @@ export interface TDExportJSON { updatedCount?: number; } -const extraShapeUtils: TLAnyShapeUtilConstructor[] = [TranscludeShapeUtil]; -const extraTools: TLStateNodeConstructor[] = [TranscludeTool]; +const extraTools: TLStateNodeConstructor[] = [NoteTool, TranscludeTool]; +const extraShapeUtils: TLAnyShapeUtilConstructor[] = [NoteShapeUtil, TranscludeShapeUtil]; export function App(props: IAppProps & IDefaultWidgetProps): JSX.Element { const { diff --git a/src/tw-whiteboard/language/en-GB/Translations.multids b/src/tw-whiteboard/language/en-GB/Translations.multids index bfe601d..26f101a 100644 --- a/src/tw-whiteboard/language/en-GB/Translations.multids +++ b/src/tw-whiteboard/language/en-GB/Translations.multids @@ -6,4 +6,6 @@ Configs/Description: These settings let you customise the behaviour of "Whiteboa Tools/Transclude/PlaceHolder: Tiddler title transclude Tools/Transclude/NoTiddlerTitle: Tiddler title not filled Tools/Transclude/TiddlerMissing: Tiddler missing -Tools/Transclude/NoTextOnField: No text on field \ No newline at end of file +Tools/Transclude/NoTextOnField: No text on field +Tools/Note/DbClickEdit: Double click to edit +Tools/Note/PlaceHolder: Input wikitext here... \ No newline at end of file diff --git a/src/tw-whiteboard/language/zh-Hans/Translations.multids b/src/tw-whiteboard/language/zh-Hans/Translations.multids index c74afd2..22ec4f6 100644 --- a/src/tw-whiteboard/language/zh-Hans/Translations.multids +++ b/src/tw-whiteboard/language/zh-Hans/Translations.multids @@ -6,4 +6,6 @@ Configs/Description: 通过这些设置,您可以自定义「白板」插件 Tools/Transclude/PlaceHolder: 条目标题去嵌入 Tools/Transclude/NoTiddlerTitle: 未填条目标题 Tools/Transclude/TiddlerMissing: 条目不存在 -Tools/Transclude/NoTextOnField: 条目此字段无文本内容 \ No newline at end of file +Tools/Transclude/NoTextOnField: 条目此字段无文本内容 +Tools/Note/DbClickEdit: 双击以编辑 +Tools/Note/PlaceHolder: 输入维基文本… \ No newline at end of file diff --git a/src/tw-whiteboard/tldraw/overrides.tsx b/src/tw-whiteboard/tldraw/overrides.tsx index 7fa831f..b5778a2 100644 --- a/src/tw-whiteboard/tldraw/overrides.tsx +++ b/src/tw-whiteboard/tldraw/overrides.tsx @@ -1,4 +1,5 @@ import { DefaultKeyboardShortcutsDialog, DefaultKeyboardShortcutsDialogContent, TLComponents, TldrawUiMenuItem, TLUiOverrides, toolbarItem, useTools } from '@tldraw/tldraw'; +import { NoteTool } from './shapes/note/tool'; import { TranscludeTool } from './shapes/transclude/tool'; // There's a guide at the bottom of this file! @@ -15,10 +16,20 @@ export const overrides: TLUiOverrides = { editor.setCurrentTool(TranscludeTool.id); }, }; + tools.note = { + id: NoteTool.id, + label: 'tool.note', + readonlyOk: false, + icon: 'tool-note', + kbd: 'n', + onSelect(_source) { + editor.setCurrentTool(NoteTool.id); + }, + }; return tools; }, toolbar(_app, toolbar, { tools }) { - toolbar.splice(4, 0, toolbarItem(tools[TranscludeTool.id])); + toolbar.splice(6, 0, toolbarItem(tools[TranscludeTool.id])); return toolbar; }, translations: { diff --git a/src/tw-whiteboard/tldraw/shapes/note/component.tsx b/src/tw-whiteboard/tldraw/shapes/note/component.tsx new file mode 100644 index 0000000..f988ec4 --- /dev/null +++ b/src/tw-whiteboard/tldraw/shapes/note/component.tsx @@ -0,0 +1,68 @@ +/* eslint-disable @typescript-eslint/strict-boolean-expressions */ +import { useWidget } from '$:/plugins/linonetwo/tw-react/index.js'; +import { getDefaultColorTheme, useEditor, useIsEditing } from '@tldraw/editor'; +import useDebouncedCallback from 'beautiful-react-hooks/useDebouncedCallback'; +import { ChangeEvent, CSSProperties, useCallback, useMemo, useRef } from 'react'; +import { IParseTreeNode } from 'tiddlywiki'; + +import { NoteShape } from './type'; +import './style.css'; +import { lingo } from 'src/tw-whiteboard/utils/lingo'; +import { wrapTiddlerAst } from 'src/tw-whiteboard/utils/wrapTiddlerAst'; + +export function NoteComponent({ shape, isDarkMode }: { isDarkMode: boolean; shape: NoteShape }) { + const editor = useEditor(); + const theme = getDefaultColorTheme({ isDarkMode }); + const isEditing = useIsEditing(shape.id); + const tiddlerText = shape.props.text ?? ''; + const adjustedColor = shape.props.color === 'black' ? 'yellow' : shape.props.color; + + const astNode = useMemo(() => { + if (!tiddlerText) return wrapTiddlerAst({ type: 'text', text: `${lingo('Tools/Note/DbClickEdit')}` }); + return wrapTiddlerAst($tw.wiki.parseText('text/vnd.tiddlywiki', tiddlerText).tree); + }, [tiddlerText]); + const noteRenderContainerReference = useRef(null); + useWidget(astNode, noteRenderContainerReference, { skip: isEditing }); + + const editTitleInputReference = useRef(null); + const onTextInputChange = useDebouncedCallback((event: ChangeEvent) => { + editor?.store.update(shape.id, (record) => ({ + ...record, + props: { + ...record.props, + text: event.target.value, + }, + })); + }, []); + const editTitleContainerOnClick = useCallback(() => { + editTitleInputReference.current?.focus?.(); + }, []); + + const sharedStyle: CSSProperties = { + backgroundColor: theme[adjustedColor].solid, + color: theme.black.solid, + }; + + return ( +
+
+