From 3d5cf24ee509c0d18f5c225755c882d738b376d8 Mon Sep 17 00:00:00 2001 From: fantasticit Date: Sun, 29 May 2022 22:53:42 +0800 Subject: [PATCH] client: improve tocs layout --- .../src/components/document/editor/editor.tsx | 6 +- .../document/editor/index.module.scss | 31 ------- .../src/components/document/editor/index.tsx | 15 +--- .../document/reader/index.module.scss | 27 ------ .../src/components/document/reader/index.tsx | 89 ++++++++----------- .../document/reader/public/index.module.scss | 23 +---- .../document/reader/public/index.tsx | 19 +--- .../collaboration/collaboration/editor.tsx | 46 ++++++++-- .../collaboration/index.module.scss | 26 +++++- .../collaboration/collaboration/index.tsx | 5 +- .../collaboration/collaboration/type.ts | 5 ++ .../src/tiptap/editor/tocs/index.module.scss | 17 ++-- .../client/src/tiptap/editor/tocs/index.tsx | 30 +++++-- 13 files changed, 147 insertions(+), 192 deletions(-) diff --git a/packages/client/src/components/document/editor/editor.tsx b/packages/client/src/components/document/editor/editor.tsx index 05ff0a12..35ba6a67 100644 --- a/packages/client/src/components/document/editor/editor.tsx +++ b/packages/client/src/components/document/editor/editor.tsx @@ -16,11 +16,9 @@ interface IProps { user: ILoginUser; documentId: string; authority: IAuthority; - className: string; - style: React.CSSProperties; } -export const Editor: React.FC = ({ user: currentUser, documentId, authority, className, style }) => { +export const Editor: React.FC = ({ user: currentUser, documentId, authority }) => { const $hasShowUserSettingModal = useRef(false); const $editor = useRef(); const mounted = useMount(); @@ -92,7 +90,7 @@ export const Editor: React.FC = ({ user: currentUser, documentId, author }, [users, currentUser, toggleMentionUsersSettingVisible]); return ( -
+
{mounted && ( div { - > main { - padding: 24px 24px 96px; - } - } - - &.isStandardWidth { - > div { - > main { - > div:first-of-type { - width: 96%; - max-width: 750px; - margin: 0 auto; - } - } - } - } - - &.isFullWidth { - width: 100%; - margin: 0 auto; - - > div { - > header { - justify-content: flex-start; - } - } - } } diff --git a/packages/client/src/components/document/editor/index.tsx b/packages/client/src/components/document/editor/index.tsx index 10a1892f..0c1d0451 100644 --- a/packages/client/src/components/document/editor/index.tsx +++ b/packages/client/src/components/document/editor/index.tsx @@ -1,5 +1,5 @@ import { IconChevronLeft } from '@douyinfe/semi-icons'; -import { Button, Nav, Skeleton, Space, Spin, Tooltip, Typography } from '@douyinfe/semi-ui'; +import { Button, Nav, Skeleton, Space, Tooltip, Typography } from '@douyinfe/semi-ui'; import { DataRender } from 'components/data-render'; import { Divider } from 'components/divider'; import { DocumentCollaboration } from 'components/document/collaboration'; @@ -14,7 +14,6 @@ import { useDocumentDetail } from 'data/document'; import { useUser } from 'data/user'; import { CHANGE_DOCUMENT_TITLE, event, triggerUseDocumentVersion } from 'event'; import { triggerRefreshTocs } from 'event'; -import { useDocumentStyle } from 'hooks/use-document-style'; import { IsOnMobile } from 'hooks/use-on-mobile'; import { useWindowSize } from 'hooks/use-window-size'; import { SecureDocumentIllustration } from 'illustrations/secure-document'; @@ -33,10 +32,6 @@ interface IProps { export const DocumentEditor: React.FC = ({ documentId }) => { const { isMobile } = IsOnMobile.useHook(); const { width: windowWith } = useWindowSize(); - const { width, fontSize } = useDocumentStyle(); - const editorWrapClassNames = useMemo(() => { - return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth; - }, [width]); const [title, setTitle] = useState(''); const { user } = useUser(); const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId); @@ -125,13 +120,7 @@ export const DocumentEditor: React.FC = ({ documentId }) => {
)} {document && } - +
); diff --git a/packages/client/src/components/document/reader/index.module.scss b/packages/client/src/components/document/reader/index.module.scss index 598280d5..d9d6e90a 100644 --- a/packages/client/src/components/document/reader/index.module.scss +++ b/packages/client/src/components/document/reader/index.module.scss @@ -9,34 +9,7 @@ } .contentWrap { - flex: 1; overflow: hidden; - - > div { - height: 100%; - padding: 24px 16px 48px; - overflow: auto; - } - - .editorWrap { - min-height: 100%; - padding-bottom: 24px; - margin: 0 auto; - - &.isStandardWidth { - width: 96%; - max-width: 750px; - } - - &.isFullWidth { - width: 100%; - } - } - - .commentWrap { - padding: 16px 0 32px; - border-top: 1px solid var(--semi-color-border); - } } .mobileToolbar { diff --git a/packages/client/src/components/document/reader/index.tsx b/packages/client/src/components/document/reader/index.tsx index 71e61750..284e900b 100644 --- a/packages/client/src/components/document/reader/index.tsx +++ b/packages/client/src/components/document/reader/index.tsx @@ -132,58 +132,45 @@ export const DocumentReader: React.FC = ({ documentId }) => { > -
-
-
- - -
- } - error={docAuthError} - normalContent={() => ( - <> - - {mounted && ( - - -
- } - /> - )} - {!isMobile && authority && authority.editable && container && ( - container} visibilityHeight={200}> - - - )} - - {container && ( - container} /> - )} - - )} - /> + +
- - + } + error={docAuthError} + normalContent={() => ( + <> + + {mounted && ( + + )} + {/* {!isMobile && authority && authority.editable && container && ( + container} visibilityHeight={200}> + + + )} + + {container && container} />} */} + + )} + />
{isMobile &&
{actions}
} diff --git a/packages/client/src/components/document/reader/public/index.module.scss b/packages/client/src/components/document/reader/public/index.module.scss index 66da6aba..8e9e9891 100644 --- a/packages/client/src/components/document/reader/public/index.module.scss +++ b/packages/client/src/components/document/reader/public/index.module.scss @@ -9,28 +9,7 @@ } .contentWrap { - position: relative; - z-index: 1; flex: 1; - padding: 24px 24px 48px; - overflow: auto; - - .editorWrap { - min-height: 100%; - padding-bottom: 24px; - - &.isStandardWidth { - width: 96%; - max-width: 750px; - margin: 0 auto; - overflow: auto; - } - - &.isFullWidth { - width: 100%; - margin: 0 auto; - overflow: auto; - } - } + overflow: hidden; } } diff --git a/packages/client/src/components/document/reader/public/index.tsx b/packages/client/src/components/document/reader/public/index.tsx index ae46718c..47d60bd6 100644 --- a/packages/client/src/components/document/reader/public/index.tsx +++ b/packages/client/src/components/document/reader/public/index.tsx @@ -1,5 +1,4 @@ import { - BackTop, Breadcrumb, Button, Form, @@ -10,10 +9,8 @@ import { Typography, } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; -import cls from 'classnames'; import { DataRender } from 'components/data-render'; import { DocumentStyle } from 'components/document/style'; -import { ImageViewer } from 'components/image-viewer'; import { LogoImage, LogoText } from 'components/logo'; import { Seo } from 'components/seo'; import { Theme } from 'components/theme'; @@ -30,7 +27,7 @@ import { CollaborationEditor } from 'tiptap/editor'; import { Author } from '../author'; import styles from './index.module.scss'; -const { Header, Content } = Layout; +const { Header } = Layout; const { Text } = Typography; interface IProps { @@ -99,11 +96,7 @@ export const DocumentPublicReader: React.FC = ({ documentId, hideLogo = } return ( -
+ <> {data && } {mounted && = ({ documentId, hideLogo = user={null} id={documentId} type="document" + hideComment renderInEditorPortal={renderAuthor} />} - - document.querySelector('#js-share-document-editor-container').parentNode} - /> -
+ ) }, [error, data, mounted, editorWrapClassNames, fontSize]) diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx b/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx index 4e405d2c..96a68ada 100644 --- a/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/editor.tsx @@ -2,9 +2,11 @@ import { BackTop, Toast } from '@douyinfe/semi-ui'; import { HocuspocusProvider } from '@hocuspocus/provider'; import cls from 'classnames'; import { Banner } from 'components/banner'; +import { CommentEditor } from 'components/document/comments'; import { LogoName } from 'components/logo'; import { getRandomColor } from 'helpers/color'; import { isAndroid, isIOS } from 'helpers/env'; +import { useDocumentStyle } from 'hooks/use-document-style'; import { useNetwork } from 'hooks/use-network'; import { IsOnMobile } from 'hooks/use-on-mobile'; import { useToggle } from 'hooks/use-toggle'; @@ -21,14 +23,25 @@ import { ICollaborationEditorProps, ProviderStatus } from './type'; type IProps = Pick< ICollaborationEditorProps, - 'editable' | 'user' | 'onTitleUpdate' | 'menubar' | 'renderInEditorPortal' + 'editable' | 'user' | 'onTitleUpdate' | 'menubar' | 'renderInEditorPortal' | 'hideComment' > & { hocuspocusProvider: HocuspocusProvider; status: ProviderStatus; + documentId: string; }; export const EditorInstance = forwardRef((props: IProps, ref) => { - const { hocuspocusProvider, editable, user, onTitleUpdate, status, menubar, renderInEditorPortal } = props; + const { + hocuspocusProvider, + documentId, + editable, + user, + hideComment, + status, + menubar, + renderInEditorPortal, + onTitleUpdate, + } = props; const $headerContainer = useRef(); const $mainContainer = useRef(); const { isMobile } = IsOnMobile.useHook(); @@ -72,6 +85,10 @@ export const EditorInstance = forwardRef((props: IProps, ref) => { [editable, user, onTitleUpdate, hocuspocusProvider] ); const [headings, setHeadings] = useState([]); + const { width, fontSize } = useDocumentStyle(); + const editorWrapClassNames = useMemo(() => { + return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth; + }, [width]); useImperativeHandle(ref, () => editor); @@ -175,9 +192,28 @@ export const EditorInstance = forwardRef((props: IProps, ref) => { )} -
- - {!isMobile && editor && headings.length ? : null} +
+
+
+ +
+ {!editable && !hideComment && ( +
+ +
+ )} +
+ {!isMobile && editor && headings.length ? ( +
+ +
+ ) : null} {protals}
diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss b/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss index 19bd3b7e..3eceee6b 100644 --- a/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/index.module.scss @@ -7,7 +7,6 @@ flex-direction: column; > header { - position: relative; z-index: 110; display: flex; justify-content: center; @@ -43,13 +42,32 @@ } > main { + position: relative; display: flex; - flex: 1; overflow: auto; + flex: 1; + justify-content: center; + flex-wrap: nowrap; - > div:first-of-type { - flex: 1; + .contentWrap { width: 100%; + + &.isStandardWidth { + max-width: 750px; + } + + &.isFullWidth { + max-width: 100%; + } + + .commentWrap { + padding: 16px 0 32px; + border-top: 1px solid var(--semi-color-border); + } + } + + .tocsWrap { + position: relative; } } } diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx b/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx index 3c237537..4140a1ba 100644 --- a/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/index.tsx @@ -26,7 +26,7 @@ export const CollaborationEditor = forwardRef((props: ICollaborationEditorProps, onTitleUpdate, user, menubar, - renderOnMount, + hideComment, renderInEditorPortal, onAwarenessUpdate, } = props; @@ -124,18 +124,19 @@ export const CollaborationEditor = forwardRef((props: ICollaborationEditorProps, normalContent={() => ( )} /> - {loading || !!error ? null : renderOnMount} ); }); diff --git a/packages/client/src/tiptap/editor/collaboration/collaboration/type.ts b/packages/client/src/tiptap/editor/collaboration/collaboration/type.ts index d86a7085..148bda75 100644 --- a/packages/client/src/tiptap/editor/collaboration/collaboration/type.ts +++ b/packages/client/src/tiptap/editor/collaboration/collaboration/type.ts @@ -28,6 +28,11 @@ export interface ICollaborationEditorProps { */ user: ILoginUser | null; + /** + * 是否需要评论 + */ + hideComment?: boolean; + /** * 文档标题变动 */ diff --git a/packages/client/src/tiptap/editor/tocs/index.module.scss b/packages/client/src/tiptap/editor/tocs/index.module.scss index 27153392..1a6b2514 100644 --- a/packages/client/src/tiptap/editor/tocs/index.module.scss +++ b/packages/client/src/tiptap/editor/tocs/index.module.scss @@ -1,7 +1,8 @@ .wrapper { position: fixed; - right: 0; - background-color: var(--semi-color-nav-bg); + padding-top: 1rem; + padding-right: 1rem; + padding-left: 2rem; > header { margin-bottom: 12px; @@ -18,15 +19,9 @@ .collapsedItem { position: relative; - height: 2px; + width: 10px; + height: 10px; background-color: #d8d8d8; - } - - :global { - .semi-anchor-link-title-active { - .collapsedItem { - background-color: var(--semi-color-primary); - } - } + border-radius: 50%; } } diff --git a/packages/client/src/tiptap/editor/tocs/index.tsx b/packages/client/src/tiptap/editor/tocs/index.tsx index f2f06d38..91076b43 100644 --- a/packages/client/src/tiptap/editor/tocs/index.tsx +++ b/packages/client/src/tiptap/editor/tocs/index.tsx @@ -1,6 +1,7 @@ import { IconDoubleChevronLeft, IconDoubleChevronRight } from '@douyinfe/semi-icons'; -import { Anchor, Button } from '@douyinfe/semi-ui'; +import { Anchor, Button, Tooltip } from '@douyinfe/semi-ui'; import { Editor } from '@tiptap/core'; +import { throttle } from 'helpers/throttle'; import { useDocumentStyle, Width } from 'hooks/use-document-style'; import { useToggle } from 'hooks/use-toggle'; import React, { useCallback, useEffect } from 'react'; @@ -15,19 +16,20 @@ interface IToc { text: string; } -const MAX_LEVEL = 6; - const Toc = ({ toc, collapsed }) => { return ( + +
+
) : ( toc.text ) } + style={{ paddingLeft: collapsed ? 16 : 8 }} > {toc.children && toc.children.length ? toc.children.map((toc) => ) @@ -36,10 +38,12 @@ const Toc = ({ toc, collapsed }) => { ); }; +const FULL_WIDTH = 1200; + export const Tocs: React.FC<{ tocs: Array; editor: Editor }> = ({ tocs = [], editor }) => { const [hasToc, toggleHasToc] = useToggle(false); - const { width } = useDocumentStyle(); const [collapsed, toggleCollapsed] = useToggle(true); + const { width } = useDocumentStyle(); const getContainer = useCallback(() => { return document.querySelector(`#js-tocs-container`); @@ -57,7 +61,6 @@ export const Tocs: React.FC<{ tocs: Array; editor: Editor }> = ({ tocs = [ const listener = () => { const nodes = findNode(editor, TableOfContents.name); const hasTocNow = !!(nodes && nodes.length); - if (hasTocNow !== hasToc) { toggleHasToc(hasTocNow); } @@ -70,6 +73,19 @@ export const Tocs: React.FC<{ tocs: Array; editor: Editor }> = ({ tocs = [ }; }, [editor, hasToc, toggleHasToc]); + useEffect(() => { + const el = document.querySelector(`#js-tocs-container`) as HTMLDivElement; + const handler = throttle(() => { + toggleCollapsed(el.offsetWidth <= FULL_WIDTH); + }, 200); + + window.addEventListener('resize', handler); + + return () => { + window.removeEventListener('resize', handler); + }; + }, [toggleCollapsed]); + return (
@@ -82,7 +98,7 @@ export const Tocs: React.FC<{ tocs: Array; editor: Editor }> = ({ tocs = [