diff --git a/packages/client/package.json b/packages/client/package.json index 6035a2a..b1c5337 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -89,6 +89,7 @@ "react": "17.0.2", "react-countdown": "^2.3.2", "react-dom": "17.0.2", + "react-full-screen": "^1.1.1", "react-helmet": "^6.1.0", "react-lazy-load-image-component": "^1.5.4", "react-pdf": "^5.7.2", diff --git a/packages/client/src/components/document/fullscreen/index.module.scss b/packages/client/src/components/document/fullscreen/index.module.scss new file mode 100644 index 0000000..7ff86b1 --- /dev/null +++ b/packages/client/src/components/document/fullscreen/index.module.scss @@ -0,0 +1,123 @@ +.wrap { + width: 100vw; + height: 100vh; + overflow: auto; + background-color: var(--semi-color-bg-0); +} + +.fullscreenContainer { + position: fixed; + background: var(--semi-color-bg-0); + + .show { + z-index: 2; + opacity: 1; + } + + .hidden { + z-index: -1; + opacity: 0; + } + + .fullscreenContent { + position: relative; + min-width: 100%; + min-height: 100%; + + .header { + position: fixed; + z-index: 2; + display: flex; + width: 100%; + height: 60px; + padding: 0 24px; + background-color: var(--semi-color-bg-0); + opacity: 0.9; + align-items: center; + } + + .content { + position: relative; + z-index: 1; + width: auto; + height: 100vh; + min-height: 680px; + padding: 0 120px; + margin: 0 auto; + overflow: auto; + letter-spacing: 0.05em; + background: var(--semi-color-bg-1); + transition: width 0.3s linear, padding 0.3s linear; + + .title { + display: table-cell; + height: 100vh; + font-size: 4rem; + line-height: 4.6rem; + color: var(--semi-color-text-0); + text-align: left; + word-wrap: break-word; + vertical-align: middle; + overflow-wrap: break-word; + } + + .node-title.is-empty { + display: none !important; + } + } + } +} + +.fullScreenToolbar { + position: fixed; + bottom: 40px; + left: 50%; + z-index: 2; + padding: 12px; + background-color: rgb(var(--semi-grey-9)); + border-radius: var(--semi-border-radius-medium); + opacity: 0; + transform: translateX(-50%); + transition: opacity 0.3s ease-in-out; + + &:hover { + opacity: 1; + transition: opacity 0.3s ease-in-out; + } + + .selected { + background-color: rgb(var(--semi-grey-8)) !important; + } + + .customButton { + display: flex; + height: 32px; + min-width: 32px; + padding: 0 8px; + font-size: 14px; + color: rgb(var(--semi-grey-0)); + cursor: pointer; + background: none; + border: none; + border-radius: 2px; + outline: none; + align-items: center; + + &:hover { + background-color: rgb(var(--semi-grey-8)); + } + } + + .divider { + width: 1px; + height: 1em; + background: rgb(var(--semi-grey-0)); + } +} + +.drawingCursor { + position: fixed; + top: 0; + left: 0; + z-index: 999999; +} diff --git a/packages/client/src/components/document/fullscreen/index.tsx b/packages/client/src/components/document/fullscreen/index.tsx new file mode 100644 index 0000000..c14eb2d --- /dev/null +++ b/packages/client/src/components/document/fullscreen/index.tsx @@ -0,0 +1,122 @@ +import { IconShrinkScreenStroked } from '@douyinfe/semi-icons'; +import { Button, Space, Tooltip, Typography } from '@douyinfe/semi-ui'; +import { EditorContent, useEditor } from '@tiptap/react'; +import cls from 'classnames'; +import { IconFullscreen } from 'components/icons/IconFullscreen'; +import { IconPencil } from 'components/icons/IconPencil'; +import { safeJSONParse } from 'helpers/json'; +import { useDrawingCursor } from 'hooks/use-cursor'; +import { useToggle } from 'hooks/use-toggle'; +import React, { useCallback, useEffect } from 'react'; +import { FullScreen, useFullScreenHandle } from 'react-full-screen'; +import { CollaborationKit } from 'tiptap/editor'; + +import styles from './index.module.scss'; + +// 控制器 +const FullscreenController = ({ handle: fullscreenHandler, isDrawing, toggleDrawing }) => { + const startDrawing = useCallback(() => { + toggleDrawing(!isDrawing); + }, [isDrawing, toggleDrawing]); + + const close = useCallback(() => { + fullscreenHandler.exit(); + toggleDrawing(false); + }, [fullscreenHandler, toggleDrawing]); + return ( +
+ + +
+ +
+
+ ); +}; + +// 画笔 +const DrawingCursor = ({ isDrawing }) => { + useDrawingCursor(isDrawing); + return isDrawing &&
; +}; + +interface IProps { + data?: any; +} + +// 全屏按钮 +export const DocumentFullscreen: React.FC = ({ data }) => { + const fullscreenHandler = useFullScreenHandle(); + const [visible, toggleVisible] = useToggle(false); + const [isDrawing, toggleDrawing] = useToggle(false); + + const editor = useEditor({ + editable: false, + extensions: CollaborationKit, + content: { type: 'doc', content: [] }, + }); + + const startPowerpoint = () => { + toggleVisible(true); + fullscreenHandler.enter(); + }; + + const fullscreenChange = useCallback( + (state) => { + if (!state) { + toggleVisible(false); + toggleDrawing(false); + } + }, + [toggleVisible, toggleDrawing] + ); + + useEffect(() => { + if (!editor) return; + const docJSON = safeJSONParse(data.content, { default: {} }).default; + docJSON.content = docJSON.content.filter((item) => item.type !== 'title'); + editor.commands.setContent(docJSON); + }, [editor, data]); + + const { Title } = Typography; + return ( + +