From e3496ac1a24de06aa74715efa77b719540970d0d Mon Sep 17 00:00:00 2001 From: boojack Date: Wed, 3 May 2023 19:13:37 +0800 Subject: [PATCH] refactor: memo editor components (#1625) --- web/src/App.tsx | 2 +- .../ActionButton/MemoVisibilitySelector.tsx | 45 +++++++ .../ActionButton/ResourceSelector.tsx | 41 ++++++ .../MemoEditor/ActionButton/TagSelector.tsx | 39 ++++++ .../Editor/index.tsx} | 0 .../MemoEditor/ResourceListView.tsx | 35 +++++ .../{MemoEditor.tsx => MemoEditor/index.tsx} | 127 +++--------------- web/src/components/UpgradeVersionBanner.tsx | 2 +- web/src/helpers/storage.ts | 69 +++++----- web/src/less/memo-editor.less | 44 ------ web/src/store/module/global.ts | 2 +- web/src/store/module/user.ts | 2 +- 12 files changed, 217 insertions(+), 191 deletions(-) create mode 100644 web/src/components/MemoEditor/ActionButton/MemoVisibilitySelector.tsx create mode 100644 web/src/components/MemoEditor/ActionButton/ResourceSelector.tsx create mode 100644 web/src/components/MemoEditor/ActionButton/TagSelector.tsx rename web/src/components/{Editor/Editor.tsx => MemoEditor/Editor/index.tsx} (100%) create mode 100644 web/src/components/MemoEditor/ResourceListView.tsx rename web/src/components/{MemoEditor.tsx => MemoEditor/index.tsx} (72%) diff --git a/web/src/App.tsx b/web/src/App.tsx index 457456bb..4a6e30d9 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next"; import { RouterProvider } from "react-router-dom"; import router from "./router"; import { useGlobalStore } from "./store/module"; -import * as storage from "./helpers/storage"; +import storage from "./helpers/storage"; import { getSystemColorScheme } from "./helpers/utils"; import Loading from "./pages/Loading"; diff --git a/web/src/components/MemoEditor/ActionButton/MemoVisibilitySelector.tsx b/web/src/components/MemoEditor/ActionButton/MemoVisibilitySelector.tsx new file mode 100644 index 00000000..695248d5 --- /dev/null +++ b/web/src/components/MemoEditor/ActionButton/MemoVisibilitySelector.tsx @@ -0,0 +1,45 @@ +import { toLower } from "lodash-es"; +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts"; +import { useEditorStore, useGlobalStore } from "@/store/module"; +import Selector from "@/components/kit/Selector"; + +const MemoVisibilitySelector = () => { + const { t } = useTranslation(); + const editorStore = useEditorStore(); + const { + state: { systemStatus }, + } = useGlobalStore(); + const editorState = editorStore.state; + const memoVisibilityOptionSelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => { + return { + value: item.value, + text: t(`memo.visibility.${toLower(item.value)}`), + }; + }); + + useEffect(() => { + if (systemStatus.disablePublicMemos) { + editorStore.setMemoVisibility("PRIVATE"); + } + }, [systemStatus.disablePublicMemos]); + + const handleMemoVisibilityOptionChanged = async (value: string) => { + const visibilityValue = value as Visibility; + editorStore.setMemoVisibility(visibilityValue); + }; + + return ( + + ); +}; + +export default MemoVisibilitySelector; diff --git a/web/src/components/MemoEditor/ActionButton/ResourceSelector.tsx b/web/src/components/MemoEditor/ActionButton/ResourceSelector.tsx new file mode 100644 index 00000000..62ea6db5 --- /dev/null +++ b/web/src/components/MemoEditor/ActionButton/ResourceSelector.tsx @@ -0,0 +1,41 @@ +import { useTranslation } from "react-i18next"; +import { useEditorStore } from "@/store/module"; +import Icon from "@/components/Icon"; +import showCreateResourceDialog from "@/components/CreateResourceDialog"; +import showResourcesSelectorDialog from "@/components/ResourcesSelectorDialog"; + +const ResourceSelector = () => { + const { t } = useTranslation(); + const editorStore = useEditorStore(); + + const handleUploadFileBtnClick = () => { + showCreateResourceDialog({ + onConfirm: (resourceList) => { + editorStore.setResourceList([...editorStore.state.resourceList, ...resourceList]); + }, + }); + }; + + return ( +
+ +
+
+ + {t("common.create")} +
+
+ + {t("editor.resources")} +
+
+
+ ); +}; +export default ResourceSelector; diff --git a/web/src/components/MemoEditor/ActionButton/TagSelector.tsx b/web/src/components/MemoEditor/ActionButton/TagSelector.tsx new file mode 100644 index 00000000..38e4d48f --- /dev/null +++ b/web/src/components/MemoEditor/ActionButton/TagSelector.tsx @@ -0,0 +1,39 @@ +import { useTagStore } from "@/store/module"; +import Icon from "@/components/Icon"; + +interface Props { + onTagSelectorClick: (tag: string) => void; +} + +const TagSelector = (props: Props) => { + const { onTagSelectorClick } = props; + const tagStore = useTagStore(); + const tags = tagStore.state.tags; + + return ( +
+ +
+ {tags.length > 0 ? ( + tags.map((tag) => { + return ( + onTagSelectorClick(tag)} + key={tag} + > + #{tag} + + ); + }) + ) : ( +

e.stopPropagation()}> + No tags found +

+ )} +
+
+ ); +}; + +export default TagSelector; diff --git a/web/src/components/Editor/Editor.tsx b/web/src/components/MemoEditor/Editor/index.tsx similarity index 100% rename from web/src/components/Editor/Editor.tsx rename to web/src/components/MemoEditor/Editor/index.tsx diff --git a/web/src/components/MemoEditor/ResourceListView.tsx b/web/src/components/MemoEditor/ResourceListView.tsx new file mode 100644 index 00000000..5b9002a7 --- /dev/null +++ b/web/src/components/MemoEditor/ResourceListView.tsx @@ -0,0 +1,35 @@ +import { useEditorStore } from "@/store/module"; +import { deleteMemoResource } from "@/helpers/api"; +import Icon from "../Icon"; +import ResourceIcon from "../ResourceIcon"; + +const ResourceListView = () => { + const editorStore = useEditorStore(); + const editorState = editorStore.state; + + const handleDeleteResource = async (resourceId: ResourceId) => { + editorStore.setResourceList(editorState.resourceList.filter((resource) => resource.id !== resourceId)); + if (editorState.editMemoId) { + await deleteMemoResource(editorState.editMemoId, resourceId); + } + }; + + return ( + <> + {editorState.resourceList && editorState.resourceList.length > 0 && ( +
+ {editorState.resourceList.map((resource) => { + return ( +
+ + {resource.filename} + handleDeleteResource(resource.id)} /> +
+ ); + })} +
+ )} + + ); +}; +export default ResourceListView; diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor/index.tsx similarity index 72% rename from web/src/components/MemoEditor.tsx rename to web/src/components/MemoEditor/index.tsx index 65b03ad0..5a087e5f 100644 --- a/web/src/components/MemoEditor.tsx +++ b/web/src/components/MemoEditor/index.tsx @@ -1,30 +1,26 @@ -import { isNumber, last, toLower, uniq } from "lodash-es"; +import { isNumber, last, uniq } from "lodash-es"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { toast } from "react-hot-toast"; import { useTranslation } from "react-i18next"; import { getMatchedNodes } from "@/labs/marked"; -import { deleteMemoResource, upsertMemoResource } from "@/helpers/api"; -import { TAB_SPACE_WIDTH, UNKNOWN_ID, VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts"; -import { useEditorStore, useGlobalStore, useFilterStore, useMemoStore, useResourceStore, useTagStore, useUserStore } from "@/store/module"; -import * as storage from "@/helpers/storage"; -import Icon from "./Icon"; -import Selector from "./kit/Selector"; -import Editor, { EditorRefActions } from "./Editor/Editor"; -import ResourceIcon from "./ResourceIcon"; -import showResourcesSelectorDialog from "./ResourcesSelectorDialog"; -import showCreateResourceDialog from "./CreateResourceDialog"; -import "@/less/memo-editor.less"; +import { upsertMemoResource } from "@/helpers/api"; +import { TAB_SPACE_WIDTH, UNKNOWN_ID } from "@/helpers/consts"; +import { useEditorStore, useFilterStore, useMemoStore, useResourceStore, useTagStore, useUserStore } from "@/store/module"; +import storage from "@/helpers/storage"; import { clearContentQueryParam, getContentQueryParam } from "@/helpers/utils"; +import Icon from "../Icon"; +import Editor, { EditorRefActions } from "./Editor"; +import TagSelector from "./ActionButton/TagSelector"; +import ResourceSelector from "./ActionButton/ResourceSelector"; +import MemoVisibilitySelector from "./ActionButton/MemoVisibilitySelector"; +import "@/less/memo-editor.less"; +import ResourceListView from "./ResourceListView"; const listItemSymbolList = ["- [ ] ", "- [x] ", "- [X] ", "* ", "- "]; const emptyOlReg = /^(\d+)\. $/; -const getEditorContentCache = (): string => { - return storage.get(["editorContentCache"]).editorContentCache ?? ""; -}; - const getInitialContent = (): string => { - return getContentQueryParam() ?? getEditorContentCache(); + return getContentQueryParam() ?? storage.get(["editorContentCache"]).editorContentCache ?? ""; }; const setEditorContentCache = (content: string) => { @@ -47,9 +43,6 @@ const MemoEditor = () => { const memoStore = useMemoStore(); const tagStore = useTagStore(); const resourceStore = useResourceStore(); - const { - state: { systemStatus }, - } = useGlobalStore(); const [state, setState] = useState({ fullscreen: false, @@ -61,22 +54,8 @@ const MemoEditor = () => { const editorState = editorStore.state; const prevEditorStateRef = useRef(editorState); const editorRef = useRef(null); - const tagSelectorRef = useRef(null); const user = userStore.state.user as User; const setting = user.setting; - const tags = tagStore.state.tags; - const memoVisibilityOptionSelectorItems = VISIBILITY_SELECTOR_ITEMS.map((item) => { - return { - value: item.value, - text: t(`memo.visibility.${toLower(item.value)}`), - }; - }); - - useEffect(() => { - if (systemStatus.disablePublicMemos) { - editorStore.setMemoVisibility("PRIVATE"); - } - }, [systemStatus.disablePublicMemos]); useEffect(() => { const { editingMemoIdCache } = storage.get(["editingMemoIdCache"]); @@ -338,39 +317,19 @@ const MemoEditor = () => { editorRef.current?.scrollToCursor(); }; - const handleUploadFileBtnClick = () => { - showCreateResourceDialog({ - onConfirm: (resourceList) => { - editorStore.setResourceList([...editorState.resourceList, ...resourceList]); - }, - }); - }; - - const handleFullscreenBtnClick = () => { + const handleFullscreenBtnClick = useCallback(() => { setState((state) => { return { ...state, fullscreen: !state.fullscreen, }; }); - }; + }, []); const handleTagSelectorClick = useCallback((tag: string) => { editorRef.current?.insertText(`#${tag} `); }, []); - const handleDeleteResource = async (resourceId: ResourceId) => { - editorStore.setResourceList(editorState.resourceList.filter((resource) => resource.id !== resourceId)); - if (editorState.editMemoId) { - await deleteMemoResource(editorState.editMemoId, resourceId); - } - }; - - const handleMemoVisibilityOptionChanged = async (value: string) => { - const visibilityValue = value as Visibility; - editorStore.setMemoVisibility(visibilityValue); - }; - const handleEditorFocus = () => { editorRef.current?.focus(); }; @@ -407,70 +366,22 @@ const MemoEditor = () => {
-
- -
- {tags.length > 0 ? ( - tags.map((tag) => { - return ( - handleTagSelectorClick(tag)} key={tag}> - #{tag} - - ); - }) - ) : ( -

e.stopPropagation()}> - No tags found -

- )} -
-
+ handleTagSelectorClick(tag)} /> -
- -
-
- - {t("common.create")} -
-
- - {t("editor.resources")} -
-
-
+
- {editorState.resourceList && editorState.resourceList.length > 0 && ( -
- {editorState.resourceList.map((resource) => { - return ( -
- - {resource.filename} - handleDeleteResource(resource.id)} /> -
- ); - })} -
- )} +
- +