From bb3703714e56e97b2c0bf63898d99f42490b2196 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 18 Oct 2021 17:45:30 +0800 Subject: [PATCH 01/20] refactor(comment-editor): wip --- package-lock.json | 14 +-- package.json | 2 +- .../ContentSourceCard/DesktopView.js | 69 -------------- .../ContentSourceCard/MobileView.js | 91 ------------------- src/components/ContentSourceCard/TagList.js | 21 ----- src/components/ContentSourceCard/UserList.js | 22 ----- src/components/ContentSourceCard/index.js | 65 ------------- .../ContentSourceCard/styles/desktop_view.ts | 30 ------ .../ContentSourceCard/styles/mobile_view.ts | 37 -------- .../ContentSourceCard/styles/tag_list.ts | 22 ----- .../ContentSourceCard/styles/user_list.ts | 19 ---- .../ContentSourceCard/tests/index.test.ts | 10 -- src/components/WordsCounter/styles/index.ts | 1 + .../editor/RichEditor/Options/index.tsx | 4 + .../editor/RichEditor/RealEditor.tsx | 7 +- .../editor/RichEditor/styles/index.ts | 13 ++- .../editor/RichEditor/styles/metric.ts | 21 +++++ .../unit/Comments/CommentBodyEditor.tsx | 36 ++------ .../unit/Comments/CommentEditor.tsx | 37 +------- .../unit/Comments/CommentReplyEditor.tsx | 45 +++------ src/containers/unit/Comments/EditorFooter.tsx | 86 +++--------------- src/containers/unit/Comments/EditorHeader.tsx | 22 +---- .../unit/Comments/ReplyEditorHeader.tsx | 16 +--- src/containers/unit/Comments/WordsCounter.tsx | 25 ----- src/containers/unit/Comments/index.tsx | 15 ++- src/containers/unit/Comments/logic.ts | 30 +----- src/containers/unit/Comments/store.ts | 3 +- .../unit/Comments/styles/comment_editor.ts | 22 ++--- .../unit/Comments/styles/editor_footer.ts | 53 ++--------- .../unit/Comments/styles/editor_header.ts | 3 + utils/constant/event.ts | 3 - 31 files changed, 117 insertions(+), 727 deletions(-) delete mode 100644 src/components/ContentSourceCard/DesktopView.js delete mode 100644 src/components/ContentSourceCard/MobileView.js delete mode 100755 src/components/ContentSourceCard/TagList.js delete mode 100755 src/components/ContentSourceCard/UserList.js delete mode 100755 src/components/ContentSourceCard/index.js delete mode 100644 src/components/ContentSourceCard/styles/desktop_view.ts delete mode 100644 src/components/ContentSourceCard/styles/mobile_view.ts delete mode 100755 src/components/ContentSourceCard/styles/tag_list.ts delete mode 100755 src/components/ContentSourceCard/styles/user_list.ts delete mode 100755 src/components/ContentSourceCard/tests/index.test.ts create mode 100644 src/containers/editor/RichEditor/styles/metric.ts delete mode 100755 src/containers/unit/Comments/WordsCounter.tsx diff --git a/package-lock.json b/package-lock.json index e07dd663f..49203756b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "license": "Apache License 2.0", "dependencies": { "@babel/core": "^7.13.14", - "@groupher/react-editor": "^1.1.28", + "@groupher/react-editor": "^1.1.29", "@next/bundle-analyzer": "^9.4.4", "@sentry/browser": "5.17.0", "@sentry/node": "5.17.0", @@ -1537,9 +1537,9 @@ } }, "node_modules/@groupher/react-editor": { - "version": "1.1.28", - "resolved": "https://registry.npmjs.org/@groupher/react-editor/-/react-editor-1.1.28.tgz", - "integrity": "sha512-xKc7lxRELIZ6+Nsv1ktX/c5L14Bl2Nq9hcR237z9zz+I9uCOT2JnIUKvR9qzlE7infJrHG9Vcgpm2x1DuEUf1w==", + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/@groupher/react-editor/-/react-editor-1.1.29.tgz", + "integrity": "sha512-j5a2J/aTulaNwnThzU0p9Bwgs4fGXBGQF4vMJB5j0wqWVSU3a5I75qd+kDQtjtHd9KFNf68jYBFuPdca63qLdw==", "dependencies": { "@groupher/editor-alert": "^1.0.27", "@groupher/editor-code": "^1.0.30", @@ -23610,9 +23610,9 @@ } }, "@groupher/react-editor": { - "version": "1.1.28", - "resolved": "https://registry.npmjs.org/@groupher/react-editor/-/react-editor-1.1.28.tgz", - "integrity": "sha512-xKc7lxRELIZ6+Nsv1ktX/c5L14Bl2Nq9hcR237z9zz+I9uCOT2JnIUKvR9qzlE7infJrHG9Vcgpm2x1DuEUf1w==", + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/@groupher/react-editor/-/react-editor-1.1.29.tgz", + "integrity": "sha512-j5a2J/aTulaNwnThzU0p9Bwgs4fGXBGQF4vMJB5j0wqWVSU3a5I75qd+kDQtjtHd9KFNf68jYBFuPdca63qLdw==", "requires": { "@groupher/editor-alert": "^1.0.27", "@groupher/editor-code": "^1.0.30", diff --git a/package.json b/package.json index 74c606bbe..4323ea964 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "dependencies": { "@babel/core": "^7.13.14", - "@groupher/react-editor": "^1.1.28", + "@groupher/react-editor": "^1.1.29", "@next/bundle-analyzer": "^9.4.4", "@sentry/browser": "5.17.0", "@sentry/node": "5.17.0", diff --git a/src/components/ContentSourceCard/DesktopView.js b/src/components/ContentSourceCard/DesktopView.js deleted file mode 100644 index 84e0f8668..000000000 --- a/src/components/ContentSourceCard/DesktopView.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * DesktopView - * - */ - -import React from 'react' -import T from 'prop-types' - -import { buildLog } from '@/utils/logger' - -import UserList from './UserList' -import { Wrapper, Title, Desc } from './styles/desktop_view' - -/* eslint-disable-next-line */ -const log = buildLog('c:DesktopView:index') - -const DesktopView = ({ data: { pagedCommentsParticipators: users } }) => { - return ( - - {users.totalCount !== 0 && ( - <> - 参与讨论 ({users.totalCount}) - - - - - )} - - ) -} - -DesktopView.propTypes = { - data: T.shape({ - communities: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - logo: T.string, - raw: T.string, - }), - ), - pagedCommentsParticipators: T.shape({ - entries: T.array, - totalCount: T.number, - }), - tags: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - color: T.string, - raw: T.string, - }), - ), - }), -} - -DesktopView.defaultProps = { - data: { - communities: [], - tags: [], - pagedCommentsParticipators: { - entries: [], - totalCount: 0, - }, - }, -} - -export default React.memo(DesktopView) diff --git a/src/components/ContentSourceCard/MobileView.js b/src/components/ContentSourceCard/MobileView.js deleted file mode 100644 index c8f05e9ff..000000000 --- a/src/components/ContentSourceCard/MobileView.js +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * MobileView - * - */ - -import React from 'react' -import T from 'prop-types' - -import { buildLog } from '@/utils/logger' -import CommunityList from '@/components/CommunityList' - -import UserList from './UserList' -import { - Wrapper, - Block, - Divider, - Title, - Desc, - NoMoreDesc, -} from './styles/mobile_view' - -/* eslint-disable-next-line */ -const log = buildLog('c:MobileView:index') - -const MobileView = ({ - data: { communities, pagedCommentsParticipators: users }, -}) => { - return ( - - - {users.totalCount !== 0 && ( - <> - 参与讨论 ({users.totalCount}) - - - - - )} - - - - 所属社区 - - 不属于任何社区} - /> - - - - ) -} - -MobileView.propTypes = { - data: T.shape({ - communities: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - logo: T.string, - raw: T.string, - }), - ), - pagedCommentsParticipators: T.shape({ - entries: T.array, - totalCount: T.number, - }), - tags: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - color: T.string, - raw: T.string, - }), - ), - }), -} - -MobileView.defaultProps = { - data: { - communities: [], - tags: [], - pagedCommentsParticipators: { - entries: [], - totalCount: 0, - }, - }, -} - -export default React.memo(MobileView) diff --git a/src/components/ContentSourceCard/TagList.js b/src/components/ContentSourceCard/TagList.js deleted file mode 100755 index 09c19a9d9..000000000 --- a/src/components/ContentSourceCard/TagList.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' -import { isEmpty } from 'ramda' - -import { Wrapper, TagDot, TagTitle, NoMoreDesc } from './styles/tag_list' - -const TagList = ({ items }) => { - if (isEmpty(items)) return 无标签 - - return ( - <> - {items.map((t) => ( - - - {t.title} - - ))} - - ) -} - -export default React.memo(TagList) diff --git a/src/components/ContentSourceCard/UserList.js b/src/components/ContentSourceCard/UserList.js deleted file mode 100755 index fa2fedc7f..000000000 --- a/src/components/ContentSourceCard/UserList.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react' - -import Tooltip from '@/components/Tooltip' -import { Wrapper, Avatar, PopInfo } from './styles/user_list' - -const UserList = ({ items }) => ( - - {items.map((user) => ( - {user.nickname}} - > -
- -
-
- ))} -
-) - -export default React.memo(UserList) diff --git a/src/components/ContentSourceCard/index.js b/src/components/ContentSourceCard/index.js deleted file mode 100755 index 07da87eba..000000000 --- a/src/components/ContentSourceCard/index.js +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * ContentSourceCard - * - */ - -import React from 'react' -import T from 'prop-types' - -import usePlatform from '@/hooks/usePlatform' -import { buildLog } from '@/utils/logger' - -import DesktopView from './DesktopView' -import MobileView from './MobileView' - -/* eslint-disable-next-line */ -const log = buildLog('c:ContentSourceCard:index') - -const ContentSourceCard = (props) => { - const { isMobile } = usePlatform() - - return ( - - {!isMobile ? : } - - ) -} - -ContentSourceCard.propTypes = { - data: T.shape({ - communities: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - logo: T.string, - raw: T.string, - }), - ), - pagedCommentsParticipators: T.shape({ - entries: T.array, - totalCount: T.number, - }), - tags: T.arrayOf( - T.shape({ - id: T.string, - title: T.string, - color: T.string, - raw: T.string, - }), - ), - }), -} - -ContentSourceCard.defaultProps = { - data: { - communities: [], - tags: [], - pagedCommentsParticipators: { - entries: [], - totalCount: 0, - }, - }, -} - -export default React.memo(ContentSourceCard) diff --git a/src/components/ContentSourceCard/styles/desktop_view.ts b/src/components/ContentSourceCard/styles/desktop_view.ts deleted file mode 100644 index f787882dd..000000000 --- a/src/components/ContentSourceCard/styles/desktop_view.ts +++ /dev/null @@ -1,30 +0,0 @@ -import styled from 'styled-components' - -import { theme } from '@/utils/themes' -import css from '@/utils/css' - -export const Wrapper = styled.div` - min-height: 100px; - padding: 10px; - padding-bottom: 0; - max-width: 300px; - width: 100%; - flex-wrap: wrap; -` -export const Title = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 1em; -` -export const Desc = styled.div<{ column: boolean }>` - ${css.flex()}; - margin-top: 15px; - margin-bottom: 20px; - flex-direction: ${({ column }) => (column ? 'column' : 'row')}; - flex-wrap: wrap; -` -// export const Divider = styled.div` -// margin-top: 10px; -// margin-bottom: 10px; -// border-bottom: 1px solid; -// border-color: ${theme('drawer.sideDivider')}; -// ` diff --git a/src/components/ContentSourceCard/styles/mobile_view.ts b/src/components/ContentSourceCard/styles/mobile_view.ts deleted file mode 100644 index 8b15904c9..000000000 --- a/src/components/ContentSourceCard/styles/mobile_view.ts +++ /dev/null @@ -1,37 +0,0 @@ -import styled from 'styled-components' - -import { theme } from '@/utils/themes' -import css from '@/utils/css' - -export const Wrapper = styled.div` - ${css.flex('align-center')}; - width: 100%; - min-height: 120px; - padding: 0 25px; -` -export const Block = styled.div` - width: 40%; -` -export const Title = styled.div` - color: ${theme('thread.articleTitle')}; - font-size: 14px; -` -export const Desc = styled.div<{ column: boolean }>` - ${css.flex()}; - margin-top: 10px; - margin-bottom: 10px; - - flex-direction: ${({ column }) => (column ? 'column' : 'row')}; - flex-wrap: wrap; -` -export const Divider = styled.div` - min-height: 80px; - width: 1px; - margin-left: 5%; - margin-right: 10%; - background-color: ${theme('drawer.sideDivider')}; -` -export const NoMoreDesc = styled.div` - color: ${theme('banner.desc')}; - font-style: italic; -` diff --git a/src/components/ContentSourceCard/styles/tag_list.ts b/src/components/ContentSourceCard/styles/tag_list.ts deleted file mode 100755 index bf8c9307d..000000000 --- a/src/components/ContentSourceCard/styles/tag_list.ts +++ /dev/null @@ -1,22 +0,0 @@ -import styled from 'styled-components' - -import { theme } from '@/utils/themes' -import css from '@/utils/css' - -export const Wrapper = styled.div` - ${css.flex()}; - margin-bottom: 12px; - margin-left: 2px; -` -export const TagDot = styled.div` - ${css.circle(10)}; - background: ${theme('baseColor.red')}; - margin-right: 5px; -` -export const TagTitle = styled.div` - margin-top: -5px; -` -export const NoMoreDesc = styled.div` - color: ${theme('banner.desc')}; - font-style: italic; -` diff --git a/src/components/ContentSourceCard/styles/user_list.ts b/src/components/ContentSourceCard/styles/user_list.ts deleted file mode 100755 index 39b2c9402..000000000 --- a/src/components/ContentSourceCard/styles/user_list.ts +++ /dev/null @@ -1,19 +0,0 @@ -import styled from 'styled-components' - -import { theme } from '@/utils/themes' -import css from '@/utils/css' -import Img from '@/Img' - -export const Wrapper = styled.div` - ${css.flex()}; - flex-wrap: wrap; -` -export const Avatar = styled(Img)` - ${css.circle(20)}; - margin-right: 5px; - margin-bottom: 6px; -` -export const PopInfo = styled.div` - padding: 5px 10px; - color: ${theme('thread.articleTitle')}; -` diff --git a/src/components/ContentSourceCard/tests/index.test.ts b/src/components/ContentSourceCard/tests/index.test.ts deleted file mode 100755 index 21bb90c27..000000000 --- a/src/components/ContentSourceCard/tests/index.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -// import React from 'react' -// import { shallow } from 'enzyme' - -// import ContentSourceCard from '../index' - -describe('TODO ', () => { - it('Expect to have unit tests specified', () => { - expect(true).toEqual(true) - }) -}) diff --git a/src/components/WordsCounter/styles/index.ts b/src/components/WordsCounter/styles/index.ts index 1ff08f5af..dc4f1302e 100755 --- a/src/components/WordsCounter/styles/index.ts +++ b/src/components/WordsCounter/styles/index.ts @@ -36,4 +36,5 @@ export const Slash = styled.div` ` export const TotalNum = styled.div` font-size: 12px; + color: ${theme('thread.articleDigest')}; ` diff --git a/src/containers/editor/RichEditor/Options/index.tsx b/src/containers/editor/RichEditor/Options/index.tsx index 52b639be3..45c47de1e 100644 --- a/src/containers/editor/RichEditor/Options/index.tsx +++ b/src/containers/editor/RichEditor/Options/index.tsx @@ -11,6 +11,10 @@ type TProps = { const Options: FC = ({ type, onLinkChange, onUseTemplateChange }) => { switch (type) { + case 'comment': { + return null + } + case 'works': { return } diff --git a/src/containers/editor/RichEditor/RealEditor.tsx b/src/containers/editor/RichEditor/RealEditor.tsx index 6300f8c20..cce7cc669 100644 --- a/src/containers/editor/RichEditor/RealEditor.tsx +++ b/src/containers/editor/RichEditor/RealEditor.tsx @@ -24,6 +24,7 @@ const log = buildLog('C:RichEditor') type TProps = { richEditor?: TStore + placeholder?: string data?: string type?: 'article' | 'works' | 'job' | 'comment' | 'radar' reinitOnPropsChange?: boolean @@ -35,6 +36,7 @@ type TProps = { const RichEditorContainer: FC = ({ richEditor: store, data, + placeholder = "// 正文内容('Tab' 键快速插入)", type = 'article', reinitOnPropsChange = false, onChange = log, @@ -46,17 +48,18 @@ const RichEditorContainer: FC = ({ // 使用模板 or 转载或翻译 or 请保持友善 return ( - + - + diff --git a/src/containers/editor/RichEditor/styles/index.ts b/src/containers/editor/RichEditor/styles/index.ts index ea48c256c..55c7b943b 100755 --- a/src/containers/editor/RichEditor/styles/index.ts +++ b/src/containers/editor/RichEditor/styles/index.ts @@ -1,22 +1,25 @@ -import styled, { createGlobalStyle } from 'styled-components' +import styled from 'styled-components' import css from '@/utils/css' import { theme } from '@/utils/themes' +import { getWidth, getMinHeight } from './metric' + export const Wrapper = styled.div` ${css.flexColumn('align-center')}; position: relative; width: 100%; /* height: 100%; */ ` -export const InnerWrapper = styled.div` - width: 680px; +export const InnerWrapper = styled.div<{ type: string }>` + width: ${({ type }) => getWidth(type)}; ` -export const EditorWrapper = styled.div.attrs(() => ({ +const EditWrapperBase = styled.div<{ type: string }>`` +export const EditorWrapper = styled(EditWrapperBase).attrs(() => ({ spellCheck: false, }))` color: ${theme('thread.articleTitle')}; - min-height: 390px; + min-height: ${({ type }) => getMinHeight(type)}; // // media therdhold is 651 width: 100%; diff --git a/src/containers/editor/RichEditor/styles/metric.ts b/src/containers/editor/RichEditor/styles/metric.ts new file mode 100644 index 000000000..a42a0db8b --- /dev/null +++ b/src/containers/editor/RichEditor/styles/metric.ts @@ -0,0 +1,21 @@ +export const getWidth = (type) => { + switch (type) { + case 'comment': { + return '600px' + } + default: { + return '680px' + } + } +} + +export const getMinHeight = (type) => { + switch (type) { + case 'comment': { + return '250px' + } + default: { + return '390px' + } + } +} diff --git a/src/containers/unit/Comments/CommentBodyEditor.tsx b/src/containers/unit/Comments/CommentBodyEditor.tsx index 3c7a9845c..9f4c24310 100755 --- a/src/containers/unit/Comments/CommentBodyEditor.tsx +++ b/src/containers/unit/Comments/CommentBodyEditor.tsx @@ -1,23 +1,10 @@ import { FC, memo } from 'react' -import dynamic from 'next/dynamic' -import { InputEditorWrapper } from './styles/comment_editor' -import EditorFooter from './EditorFooter' +import RichEditor from '@/containers/editor/RichEditor/RealEditor' -import { - // onCommentInputChange, - backToEditor, - createCommentPreview, - onCommentInputBlur, -} from './logic' +import EditorFooter from './EditorFooter' -export const BodyEditor = dynamic( - () => import('@/containers/editor/RichEditor'), - { - /* eslint-disable react/display-name */ - loading: () =>
loading
, - }, -) +import { InputEditorWrapper } from './styles/comment_editor' type TProps = { showInputEditor?: boolean @@ -34,18 +21,13 @@ const CommentBodyEditor: FC = ({ }) => { return (
- - - - - + +
) } diff --git a/src/containers/unit/Comments/CommentEditor.tsx b/src/containers/unit/Comments/CommentEditor.tsx index 57c3127bf..b2c1100f3 100755 --- a/src/containers/unit/Comments/CommentEditor.tsx +++ b/src/containers/unit/Comments/CommentEditor.tsx @@ -1,14 +1,12 @@ import { FC, memo } from 'react' import type { TAccount, TUser } from '@/spec' -import MarkDownRender from '@/components/MarkDownRender' import EditorHeader from './EditorHeader' -import EditorFooter from './EditorFooter' import CommentBodyEditor from './CommentBodyEditor' -import { Container, PreviewerWrapper } from './styles/comment_editor' -import { backToEditor, createCommentPreview } from './logic' +import { Wrapper } from './styles/comment_editor' +import { backToEditor } from './logic' type TProps = { referUsers: TUser[] @@ -18,10 +16,8 @@ type TProps = { onCreate?: any restProps: { - countCurrent: number showInputBox: boolean showInputEditor: boolean - showInputPreview: boolean editContent: string creating: boolean } @@ -32,23 +28,14 @@ const CommentEditor: FC = (props) => { referUsers, accountInfo, onCreate, - restProps: { - countCurrent, - showInputBox, - showInputEditor, - showInputPreview, - editContent, - creating, - }, + restProps: { showInputBox, showInputEditor, editContent, creating }, } = props return ( - + {showInputEditor && ( @@ -58,21 +45,7 @@ const CommentEditor: FC = (props) => { creating={creating} /> )} - {showInputPreview && ( -
- - - - -
- )} -
+
) } diff --git a/src/containers/unit/Comments/CommentReplyEditor.tsx b/src/containers/unit/Comments/CommentReplyEditor.tsx index 773c5c322..b18e2243c 100755 --- a/src/containers/unit/Comments/CommentReplyEditor.tsx +++ b/src/containers/unit/Comments/CommentReplyEditor.tsx @@ -15,12 +15,7 @@ import { PreviewWrapper, } from './styles/comment_reply_editor' -import { - onReplyInputChange, - createReplyComment, - replyBackToEditor, - replyCommentPreview, -} from './logic' +import { createReplyComment } from './logic' export const BodyEditor = dynamic( () => import('@/containers/editor/RichEditor'), @@ -35,14 +30,12 @@ type TProps = { show: boolean isEdit: boolean accountInfo: TAccount - showReplyPreview: boolean - restProps: { - countCurrent: number - replyContent: string - replyToComment: TComment - replying: boolean - } + // restProps: { + // replyContent: string + // replyToComment: TComment + // replying: boolean + // } } const CommentReplyEditor: FC = ({ @@ -50,38 +43,22 @@ const CommentReplyEditor: FC = ({ show, isEdit, accountInfo, - showReplyPreview, - restProps: { countCurrent, replyContent, replyToComment, replying }, + // restProps: { replyToComment, replying }, }) => { return ( - + - {!isEdit && } + {/* {!isEdit && } */} - {show ? ( + {show && (
- ) : ( - - - )} - +
) } diff --git a/src/containers/unit/Comments/EditorFooter.tsx b/src/containers/unit/Comments/EditorFooter.tsx index 3fe8cd291..3c5985cbb 100755 --- a/src/containers/unit/Comments/EditorFooter.tsx +++ b/src/containers/unit/Comments/EditorFooter.tsx @@ -1,88 +1,26 @@ import { FC, memo } from 'react' -import { ICON, ICON_CMD } from '@/config' +import WordsCounter from '@/components/WordsCounter' +import SubmitButton from '@/components/Buttons/SubmitButton' -import Button from '@/components/Buttons/Button' -import { Space } from '@/components/Common' -import DocUploader from '@/containers/tool/DocUploader' - -import { - InputFooter, - InputHelper, - HelperIcon, - InputSubmit, - FoldBtn, - FoldArrow, - FoldText, -} from './styles/editor_footer' - -import { insertCode, insertQuote, onUploadImageDone } from './logic' +import { Wrapper } from './styles/editor_footer' type TProps = { loading: boolean - showPreview?: boolean onCreate: () => void - onBackEdit: () => void - onPreview: () => void onFold?: () => void showFold?: boolean } -const EditorFooter: FC = ({ - loading, - showPreview = true, - onCreate, - onBackEdit, - onPreview, - showFold, - onFold, -}) => ( - - {showPreview ? ( - - ) : ( - -
- -
-
- -
- - - -
- )} - - - {showFold && ( - - - 收起 - - )} - - {showPreview ? ( - - ) : ( - - )} - - {!loading ? ( - - ) : ( - - )} - -
+const EditorFooter: FC = ({ loading, onCreate, showFold, onFold }) => ( + + + + ) export default memo(EditorFooter) diff --git a/src/containers/unit/Comments/EditorHeader.tsx b/src/containers/unit/Comments/EditorHeader.tsx index 7b659558a..060c4183a 100755 --- a/src/containers/unit/Comments/EditorHeader.tsx +++ b/src/containers/unit/Comments/EditorHeader.tsx @@ -6,10 +6,9 @@ import { ICON, ICON_CMD } from '@/config' import AvatarsRow from '@/components/AvatarsRow' import { SpaceGrow } from '@/components/Common' -import WordsCounter from './WordsCounter' - import { Wrapper, + ExpandWrapper, UserAvatar, LeaveResponseText, LeaveResponseUsername, @@ -24,23 +23,19 @@ import { openInputBox } from './logic' type TProps = { accountInfo: TAccount showInputEditor: boolean - showInputPreview: boolean - countCurrent: number referUsers: TUser[] } const EditorHeader: FC = ({ accountInfo, showInputEditor, - showInputPreview, - countCurrent, referUsers, }) => { if (showInputEditor) { return ( - + - {accountInfo.nickname} + {accountInfo.nickname}: {referUsers.length > 0 && ( @@ -55,16 +50,7 @@ const EditorHeader: FC = ({ )} - - - ) - } - if (showInputPreview) { - return ( - - - {accountInfo.nickname} - + ) } return ( diff --git a/src/containers/unit/Comments/ReplyEditorHeader.tsx b/src/containers/unit/Comments/ReplyEditorHeader.tsx index 039951e35..534b05469 100755 --- a/src/containers/unit/Comments/ReplyEditorHeader.tsx +++ b/src/containers/unit/Comments/ReplyEditorHeader.tsx @@ -6,8 +6,6 @@ import { ICON_CMD } from '@/config' import { SpaceGrow } from '@/components/Common' import AvatarsRow from '@/components/AvatarsRow' -import WordsCounter from './WordsCounter' - import { Wrapper, UserAvatar, @@ -18,32 +16,22 @@ import { type TProps = { accountInfo: TAccount - countCurrent: number referUsers: TUser[] - showPreview: boolean } -const ReplyEditorHeader: FC = ({ - accountInfo, - countCurrent, - referUsers, - showPreview, -}) => ( +const ReplyEditorHeader: FC = ({ accountInfo, referUsers }) => ( {accountInfo.nickname} - {referUsers.length > 0 ? ( + {referUsers.length > 0 && (
- ) : ( -
)} - {showPreview ?
: } ) diff --git a/src/containers/unit/Comments/WordsCounter.tsx b/src/containers/unit/Comments/WordsCounter.tsx deleted file mode 100755 index 80f01bedd..000000000 --- a/src/containers/unit/Comments/WordsCounter.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { FC, memo } from 'react' - -import { WORD_LIMIT } from '@/config' - -// import { Wrapper } from './styles' -import { - Wrapper, - CounterSplit, - CounterCur, - CounterTotal, -} from './styles/words_counter' - -type TProps = { - countCurrent: number -} - -const WordsCounter: FC = ({ countCurrent }) => ( - - {countCurrent} - / - {WORD_LIMIT.COMMENT} - -) - -export default memo(WordsCounter) diff --git a/src/containers/unit/Comments/index.tsx b/src/containers/unit/Comments/index.tsx index 40ef111ce..83544c12f 100755 --- a/src/containers/unit/Comments/index.tsx +++ b/src/containers/unit/Comments/index.tsx @@ -11,11 +11,11 @@ import { buildLog } from '@/utils/logger' import { pluggedIn } from '@/utils/mobx' import Modal from '@/components/Modal' -import NoticeBar from '@/components/NoticeBar' +// import NoticeBar from '@/components/NoticeBar' import CommentEditor from './CommentEditor' import List from './List' -// import CommentReplyEditor from './CommentReplyEditor' +import CommentReplyEditor from './CommentReplyEditor' // import LockedMessage from './LockedMessage' import type { TStore } from './store' @@ -48,7 +48,6 @@ const CommentsContainer: FC = ({ accountInfo, showReplyBox, showReplyEditor, - showReplyPreview, isEdit, foldedIds, isAllFolded, @@ -57,16 +56,14 @@ const CommentsContainer: FC = ({ return ( - {/* {showReplyBox && ( + {showReplyBox && ( - )} */} + )} = ({ restProps={{ ...store }} /> -
+ {/*
+ /> */} { cb() }) -export const createCommentPreview = (): void => - store.mark({ - showInputEditor: false, - showInputPreview: true, - }) - export const backToEditor = (): void => store.mark({ showInputEditor: true, @@ -133,14 +120,12 @@ export const createReplyComment = (): void => { export const onCommentInputChange = (editContent): void => store.mark({ - countCurrent: countWords(editContent), extractMentions: extractMentions(editContent), editContent, }) export const onReplyInputChange = (replyContent): void => store.mark({ - countCurrent: countWords(replyContent), extractMentions: extractMentions(replyContent), replyContent, }) @@ -258,19 +243,6 @@ export const handleUpvote = ( } } -export const onUploadImageDone = (url: string): void => - send(EVENT.DRAFT_INSERT_SNIPPET, { data: `![](${url})` }) - -export const insertQuote = (): void => - send(EVENT.DRAFT_INSERT_SNIPPET, { data: '> ' }) - -export const insertCode = (): void => { - const communityRaw = store.curCommunity.raw - const data = `\`\`\`${communityRaw}\n\n\`\`\`` - - send(EVENT.DRAFT_INSERT_SNIPPET, { data }) -} - export const onMention = (user: TUser): void => store.addReferUser(user) export const onMentionSearch = (name: string): void => { if (name?.length >= 1) { diff --git a/src/containers/unit/Comments/store.ts b/src/containers/unit/Comments/store.ts index 0ded0ca76..40f5c6ccf 100755 --- a/src/containers/unit/Comments/store.ts +++ b/src/containers/unit/Comments/store.ts @@ -44,14 +44,13 @@ const CommentsStore = T.model('CommentsStore', { // toggle main comment box showInputBox: T.optional(T.boolean, false), // toggle editor inside the comment box - showInputEditor: T.optional(T.boolean, false), + showInputEditor: T.optional(T.boolean, true), // toggle markdown drawer inside the comment box showInputPreview: T.optional(T.boolean, false), // toggle modal editor for reply showReplyBox: T.optional(T.boolean, false), showReplyEditor: T.optional(T.boolean, false), - showReplyPreview: T.optional(T.boolean, false), // current to be delete comment id, use to target the confirm mask tobeDeleteId: T.maybeNull(T.string), diff --git a/src/containers/unit/Comments/styles/comment_editor.ts b/src/containers/unit/Comments/styles/comment_editor.ts index 7a1456da0..cd3338a3b 100755 --- a/src/containers/unit/Comments/styles/comment_editor.ts +++ b/src/containers/unit/Comments/styles/comment_editor.ts @@ -2,19 +2,22 @@ import styled from 'styled-components' // import Img from '@/Img' import type { TActive } from '@/spec' -import { theme } from '@/utils/themes' +// import { theme } from '@/utils/themes' import css from '@/utils/css' -export const Container = styled.div` +export const Wrapper = styled.div` ${css.flexColumn()}; - /* background: ${theme('drawer.articleBg')}; */ - background: #013340; - min-height: ${({ show }) => (show ? '100px' : '50px')}; + padding: ${({ show }) => (show ? '10px 0' : '0')}; + background: ${({ show }) => (show ? 'transparent' : '#013340')}; + min-height: ${({ show }) => (show ? '300px' : '50px')}; height: auto; - border-color: ${theme('drawer.articleBg')}; + border-top: 2px solid; + border-bottom: 3px solid; + border-color: #00424f; transition: all 0.3s; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04); + box-shadow: ${({ show }) => + show ? 'none' : '0 1px 4px rgba(0, 0, 0, 0.04)'}; border-radius: 3px; ${css.media.mobile` @@ -28,8 +31,3 @@ export const InputEditorWrapper = styled.div<{ showInputEditor: boolean }>` display: ${({ showInputEditor }) => (showInputEditor ? 'block' : 'none')}; font-size: 0.9em; ` - -export const PreviewerWrapper = styled.div` - padding: 0 33px; - min-height: 150px; -` diff --git a/src/containers/unit/Comments/styles/editor_footer.ts b/src/containers/unit/Comments/styles/editor_footer.ts index 514e8014c..6a59e3f0e 100755 --- a/src/containers/unit/Comments/styles/editor_footer.ts +++ b/src/containers/unit/Comments/styles/editor_footer.ts @@ -1,53 +1,12 @@ import styled from 'styled-components' -import Img from '@/Img' -import { theme } from '@/utils/themes' +// import Img from '@/Img' +// import { theme } from '@/utils/themes' import css from '@/utils/css' -export const InputFooter = styled.div` - ${css.flex()}; - padding: 0 10px; - margin-bottom: 10px; - margin-left: 20px; - margin-right: 15px; +export const Wrapper = styled.div` + ${css.flex('align-center', 'justify-between')}; + margin-bottom: 12px; ` -export const InputHelper = styled.div` - ${css.flexGrow()}; -` - -export const FoldBtn = styled.div` - ${css.flex('align-center')}; -` -export const FoldArrow = styled(Img)` - fill: ${theme('thread.articleDigest')}; - ${css.size(16)}; - margin-right: 3px; - ${FoldBtn}:hover & { - cursor: pointer; - fill: ${theme('thread.articleTitle')}; - } -` - -export const FoldText = styled.div` - color: ${theme('thread.articleDigest')}; - ${FoldBtn}:hover & { - cursor: pointer; - color: ${theme('thread.articleTitle')}; - } -` - -export const HelperIcon = styled(Img)` - fill: ${theme('comment.placeholder')}; - ${css.size(20)}; - margin-right: 8px; - - &:hover { - fill: #51abb2; - cursor: pointer; - } -` - -export const InputSubmit = styled.div` - ${css.flex('align-center')}; -` +export const holder = 1 diff --git a/src/containers/unit/Comments/styles/editor_header.ts b/src/containers/unit/Comments/styles/editor_header.ts index 45f012826..df39fdcd1 100755 --- a/src/containers/unit/Comments/styles/editor_header.ts +++ b/src/containers/unit/Comments/styles/editor_header.ts @@ -9,6 +9,9 @@ export const Wrapper = styled.div` height: 50px; margin-left: 10px; ` +export const ExpandWrapper = styled(Wrapper)` + margin-left: 0; +` export const UserAvatar = styled(Img)` ${css.circle(20)}; fill: ${theme('thread.articleTitle')}; diff --git a/utils/constant/event.ts b/utils/constant/event.ts index bf2386b96..fd6d56e12 100755 --- a/utils/constant/event.ts +++ b/utils/constant/event.ts @@ -45,9 +45,6 @@ const EVENT = { // sync repo SYNC_REPO: 'SYNC_REPO', - // Draft editor - DRAFT_INSERT_SNIPPET: 'DRAFT_INSERT_SNIPPET', - // favorites SET_FAVORITE_CONTENT: 'SET_FAVORITE_CONTENT', // customization From 3893214eb109496f5f5cec68d148d0751182c3b3 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 18 Oct 2021 21:49:24 +0800 Subject: [PATCH 02/20] refactor(comment-editor): re-org wip --- .../BodyEditor.tsx} | 11 ++--- .../{EditorFooter.tsx => Editor/Footer.tsx} | 2 +- .../{EditorHeader.tsx => Editor/Header.tsx} | 8 ++-- .../ReplyEditor.tsx} | 28 ++++--------- .../unit/Comments/Editor/ReplyHeader.tsx | 40 +++++++++++++++++++ .../{CommentEditor.tsx => Editor/index.tsx} | 11 +++-- .../unit/Comments/ReplyEditorHeader.tsx | 38 ------------------ src/containers/unit/Comments/index.tsx | 8 ++-- .../{editor_footer.ts => editor/footer.ts} | 1 + .../{editor_header.ts => editor/header.ts} | 9 +++++ .../{comment_editor.ts => editor/index.ts} | 1 - .../reply_editor.ts} | 4 -- .../reply_header.ts} | 0 .../unit/Comments/styles/words_counter.ts | 38 ------------------ 14 files changed, 76 insertions(+), 123 deletions(-) rename src/containers/unit/Comments/{CommentBodyEditor.tsx => Editor/BodyEditor.tsx} (77%) rename src/containers/unit/Comments/{EditorFooter.tsx => Editor/Footer.tsx} (91%) rename src/containers/unit/Comments/{EditorHeader.tsx => Editor/Header.tsx} (87%) rename src/containers/unit/Comments/{CommentReplyEditor.tsx => Editor/ReplyEditor.tsx} (57%) create mode 100755 src/containers/unit/Comments/Editor/ReplyHeader.tsx rename src/containers/unit/Comments/{CommentEditor.tsx => Editor/index.tsx} (78%) mode change 100755 => 100644 delete mode 100755 src/containers/unit/Comments/ReplyEditorHeader.tsx rename src/containers/unit/Comments/styles/{editor_footer.ts => editor/footer.ts} (93%) mode change 100755 => 100644 rename src/containers/unit/Comments/styles/{editor_header.ts => editor/header.ts} (84%) mode change 100755 => 100644 rename src/containers/unit/Comments/styles/{comment_editor.ts => editor/index.ts} (97%) mode change 100755 => 100644 rename src/containers/unit/Comments/styles/{comment_reply_editor.ts => editor/reply_editor.ts} (86%) rename src/containers/unit/Comments/styles/{reply_editor_header.ts => editor/reply_header.ts} (100%) delete mode 100755 src/containers/unit/Comments/styles/words_counter.ts diff --git a/src/containers/unit/Comments/CommentBodyEditor.tsx b/src/containers/unit/Comments/Editor/BodyEditor.tsx similarity index 77% rename from src/containers/unit/Comments/CommentBodyEditor.tsx rename to src/containers/unit/Comments/Editor/BodyEditor.tsx index 9f4c24310..ecdaae245 100755 --- a/src/containers/unit/Comments/CommentBodyEditor.tsx +++ b/src/containers/unit/Comments/Editor/BodyEditor.tsx @@ -1,16 +1,13 @@ import { FC, memo } from 'react' import RichEditor from '@/containers/editor/RichEditor/RealEditor' - -import EditorFooter from './EditorFooter' - -import { InputEditorWrapper } from './styles/comment_editor' +import EditorFooter from './Footer' type TProps = { showInputEditor?: boolean - body: string - onCreate: () => void - creating: boolean + body?: string + onCreate?: () => void + creating?: boolean } const CommentBodyEditor: FC = ({ diff --git a/src/containers/unit/Comments/EditorFooter.tsx b/src/containers/unit/Comments/Editor/Footer.tsx similarity index 91% rename from src/containers/unit/Comments/EditorFooter.tsx rename to src/containers/unit/Comments/Editor/Footer.tsx index 3c5985cbb..7ac559964 100755 --- a/src/containers/unit/Comments/EditorFooter.tsx +++ b/src/containers/unit/Comments/Editor/Footer.tsx @@ -3,7 +3,7 @@ import { FC, memo } from 'react' import WordsCounter from '@/components/WordsCounter' import SubmitButton from '@/components/Buttons/SubmitButton' -import { Wrapper } from './styles/editor_footer' +import { Wrapper } from '../styles/editor/footer' type TProps = { loading: boolean diff --git a/src/containers/unit/Comments/EditorHeader.tsx b/src/containers/unit/Comments/Editor/Header.tsx similarity index 87% rename from src/containers/unit/Comments/EditorHeader.tsx rename to src/containers/unit/Comments/Editor/Header.tsx index 060c4183a..5e7516d02 100755 --- a/src/containers/unit/Comments/EditorHeader.tsx +++ b/src/containers/unit/Comments/Editor/Header.tsx @@ -9,15 +9,16 @@ import { SpaceGrow } from '@/components/Common' import { Wrapper, ExpandWrapper, + HintText, UserAvatar, LeaveResponseText, LeaveResponseUsername, RefUsersWrapper, RefUserList, AtSignIcon, -} from './styles/editor_header' +} from '../styles/editor/header' -import { openInputBox } from './logic' +import { openInputBox } from '../logic' // import { Wrapper } from './styles' type TProps = { @@ -34,8 +35,9 @@ const EditorHeader: FC = ({ if (showInputEditor) { return ( + 创建评论: - {accountInfo.nickname}: + {accountInfo.nickname} {referUsers.length > 0 && ( diff --git a/src/containers/unit/Comments/CommentReplyEditor.tsx b/src/containers/unit/Comments/Editor/ReplyEditor.tsx similarity index 57% rename from src/containers/unit/Comments/CommentReplyEditor.tsx rename to src/containers/unit/Comments/Editor/ReplyEditor.tsx index b18e2243c..6b80421a3 100755 --- a/src/containers/unit/Comments/CommentReplyEditor.tsx +++ b/src/containers/unit/Comments/Editor/ReplyEditor.tsx @@ -1,29 +1,15 @@ import { FC, memo } from 'react' -import dynamic from 'next/dynamic' import type { TAccount, TUser, TComment } from '@/spec' -import MarkDownRender from '@/components/MarkDownRender' +import BodyEditor from './BodyEditor' +// import ReplyToBar from '../ReplyToBar' +import ReplyHeader from './ReplyHeader' +import EditorFooter from './Footer' -import ReplyToBar from './ReplyToBar' -import ReplyEditorHeader from './ReplyEditorHeader' -import EditorFooter from './EditorFooter' +import { Wrapper, InputEditorWrapper } from '../styles/editor/reply_editor' -import { - Wrapper, - InputEditorWrapper, - PreviewWrapper, -} from './styles/comment_reply_editor' - -import { createReplyComment } from './logic' - -export const BodyEditor = dynamic( - () => import('@/containers/editor/RichEditor'), - { - /* eslint-disable react/display-name */ - loading: () =>
loading
, - }, -) +import { createReplyComment } from '../logic' type TProps = { referUsers: TUser[] @@ -47,7 +33,7 @@ const CommentReplyEditor: FC = ({ }) => { return ( - + {/* {!isEdit && } */} diff --git a/src/containers/unit/Comments/Editor/ReplyHeader.tsx b/src/containers/unit/Comments/Editor/ReplyHeader.tsx new file mode 100755 index 000000000..76a33f96c --- /dev/null +++ b/src/containers/unit/Comments/Editor/ReplyHeader.tsx @@ -0,0 +1,40 @@ +import { FC, memo } from 'react' + +import type { TAccount, TUser } from '@/spec' +import { ICON_CMD } from '@/config' + +import { SpaceGrow } from '@/components/Common' +import AvatarsRow from '@/components/AvatarsRow' + +import { + Wrapper, + UserAvatar, + LeaveResponseUsername, + ReplyAvatars, + ReferToIcon, +} from '../styles/editor/reply_header' + +type TProps = { + accountInfo: TAccount + referUsers: TUser[] +} + +const ReplyHeader: FC = ({ accountInfo, referUsers }) => { + return ( + + + {accountInfo.nickname} + {referUsers.length > 0 && ( +
+ + + + +
+ )} + +
+ ) +} + +export default memo(ReplyHeader) diff --git a/src/containers/unit/Comments/CommentEditor.tsx b/src/containers/unit/Comments/Editor/index.tsx old mode 100755 new mode 100644 similarity index 78% rename from src/containers/unit/Comments/CommentEditor.tsx rename to src/containers/unit/Comments/Editor/index.tsx index b2c1100f3..9199272a8 --- a/src/containers/unit/Comments/CommentEditor.tsx +++ b/src/containers/unit/Comments/Editor/index.tsx @@ -2,11 +2,10 @@ import { FC, memo } from 'react' import type { TAccount, TUser } from '@/spec' -import EditorHeader from './EditorHeader' -import CommentBodyEditor from './CommentBodyEditor' +import Header from './Header' +import BodyEditor from './BodyEditor' -import { Wrapper } from './styles/comment_editor' -import { backToEditor } from './logic' +import { Wrapper } from '../styles/editor' type TProps = { referUsers: TUser[] @@ -33,13 +32,13 @@ const CommentEditor: FC = (props) => { return ( - {showInputEditor && ( - = ({ accountInfo, referUsers }) => ( - - - {accountInfo.nickname} - {referUsers.length > 0 && ( -
- - - - -
- )} - -
-) - -export default memo(ReplyEditorHeader) diff --git a/src/containers/unit/Comments/index.tsx b/src/containers/unit/Comments/index.tsx index 83544c12f..4079ce832 100755 --- a/src/containers/unit/Comments/index.tsx +++ b/src/containers/unit/Comments/index.tsx @@ -13,9 +13,9 @@ import { pluggedIn } from '@/utils/mobx' import Modal from '@/components/Modal' // import NoticeBar from '@/components/NoticeBar' -import CommentEditor from './CommentEditor' +import Editor from './Editor' import List from './List' -import CommentReplyEditor from './CommentReplyEditor' +import ReplyEditor from './Editor/ReplyEditor' // import LockedMessage from './LockedMessage' import type { TStore } from './store' @@ -57,7 +57,7 @@ const CommentsContainer: FC = ({ {showReplyBox && ( - = ({ )} - ` background: ${({ show }) => (show ? 'transparent' : '#013340')}; min-height: ${({ show }) => (show ? '300px' : '50px')}; height: auto; - border-top: 2px solid; border-bottom: 3px solid; border-color: #00424f; transition: all 0.3s; diff --git a/src/containers/unit/Comments/styles/comment_reply_editor.ts b/src/containers/unit/Comments/styles/editor/reply_editor.ts similarity index 86% rename from src/containers/unit/Comments/styles/comment_reply_editor.ts rename to src/containers/unit/Comments/styles/editor/reply_editor.ts index 4b8901817..fce305700 100755 --- a/src/containers/unit/Comments/styles/comment_reply_editor.ts +++ b/src/containers/unit/Comments/styles/editor/reply_editor.ts @@ -22,7 +22,3 @@ export const InputEditorWrapper = styled.div` margin-bottom: 10px; font-size: 1rem; ` -export const PreviewWrapper = styled.div` - min-height: 200px; - padding: 0 20px; -` diff --git a/src/containers/unit/Comments/styles/reply_editor_header.ts b/src/containers/unit/Comments/styles/editor/reply_header.ts similarity index 100% rename from src/containers/unit/Comments/styles/reply_editor_header.ts rename to src/containers/unit/Comments/styles/editor/reply_header.ts diff --git a/src/containers/unit/Comments/styles/words_counter.ts b/src/containers/unit/Comments/styles/words_counter.ts deleted file mode 100755 index ac8e1ced7..000000000 --- a/src/containers/unit/Comments/styles/words_counter.ts +++ /dev/null @@ -1,38 +0,0 @@ -import styled from 'styled-components' - -import { WORD_LIMIT } from '@/config' -import { theme } from '@/utils/themes' -import css from '@/utils/css' - -export const Wrapper = styled.div` - ${css.flex('align-center')}; - color: #c2d9da; -` -export const CounterSplit = styled.div` - font-size: 1.5em; - font-weight: lighter; - color: ${theme('comment.placeholder')}; -` - -const getColor = (num) => { - if (num > WORD_LIMIT.COMMENT) { - return 'tomato' - } - if (num >= WORD_LIMIT.COMMENT - 50 && num <= WORD_LIMIT.COMMENT) { - return 'orange' - } - return 'yellowgreen' -} - -export const CounterCur = styled.div<{ num: number }>` - margin-right: 5px; - font-size: 1em; - color: ${({ num }) => getColor(num)}; -` - -export const CounterTotal = styled.div` - margin-left: 5px; - margin-right: 5px; - font-size: 1em; - color: ${theme('comment.placeholder')}; -` From 744c2244e6531c6b19558022d8cdc2b8a5672d01 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Mon, 18 Oct 2021 22:57:43 +0800 Subject: [PATCH 03/20] refactor(comment-editor): re-org wip --- .../unit/Comments/Editor/BodyEditor.tsx | 8 +--- .../unit/Comments/Editor/Footer.tsx | 3 +- .../unit/Comments/Editor/Header.tsx | 20 +++++----- src/containers/unit/Comments/Editor/index.tsx | 32 +++++++++------- src/containers/unit/Comments/index.tsx | 2 + src/containers/unit/Comments/logic.ts | 38 ++++--------------- src/containers/unit/Comments/store.ts | 6 +-- .../unit/Comments/styles/editor/header.ts | 25 +++++++++++- .../unit/Comments/styles/editor/index.ts | 37 ++++++++++-------- 9 files changed, 85 insertions(+), 86 deletions(-) diff --git a/src/containers/unit/Comments/Editor/BodyEditor.tsx b/src/containers/unit/Comments/Editor/BodyEditor.tsx index ecdaae245..e9662055b 100755 --- a/src/containers/unit/Comments/Editor/BodyEditor.tsx +++ b/src/containers/unit/Comments/Editor/BodyEditor.tsx @@ -4,18 +4,12 @@ import RichEditor from '@/containers/editor/RichEditor/RealEditor' import EditorFooter from './Footer' type TProps = { - showInputEditor?: boolean body?: string onCreate?: () => void creating?: boolean } -const CommentBodyEditor: FC = ({ - showInputEditor = true, - body, - onCreate, - creating, -}) => { +const CommentBodyEditor: FC = ({ body, onCreate, creating }) => { return (
= ({ loading, onCreate, showFold, onFold }) => ( ) diff --git a/src/containers/unit/Comments/Editor/Header.tsx b/src/containers/unit/Comments/Editor/Header.tsx index 5e7516d02..fb31d50be 100755 --- a/src/containers/unit/Comments/Editor/Header.tsx +++ b/src/containers/unit/Comments/Editor/Header.tsx @@ -13,26 +13,22 @@ import { UserAvatar, LeaveResponseText, LeaveResponseUsername, + PenIcon, RefUsersWrapper, RefUserList, AtSignIcon, } from '../styles/editor/header' -import { openInputBox } from '../logic' -// import { Wrapper } from './styles' +import { openEditor } from '../logic' type TProps = { accountInfo: TAccount - showInputEditor: boolean + showEditor: boolean referUsers: TUser[] } -const EditorHeader: FC = ({ - accountInfo, - showInputEditor, - referUsers, -}) => { - if (showInputEditor) { +const EditorHeader: FC = ({ accountInfo, showEditor, referUsers }) => { + if (showEditor) { return ( 创建评论: @@ -56,9 +52,11 @@ const EditorHeader: FC = ({ ) } return ( - + - 参与讨论 + 参与讨论 + + ) } diff --git a/src/containers/unit/Comments/Editor/index.tsx b/src/containers/unit/Comments/Editor/index.tsx index 9199272a8..24ade725d 100644 --- a/src/containers/unit/Comments/Editor/index.tsx +++ b/src/containers/unit/Comments/Editor/index.tsx @@ -5,7 +5,7 @@ import type { TAccount, TUser } from '@/spec' import Header from './Header' import BodyEditor from './BodyEditor' -import { Wrapper } from '../styles/editor' +import { Wrapper, ExpandWrapper } from '../styles/editor' type TProps = { referUsers: TUser[] @@ -15,8 +15,7 @@ type TProps = { onCreate?: any restProps: { - showInputBox: boolean - showInputEditor: boolean + showEditor: boolean editContent: string creating: boolean } @@ -27,24 +26,29 @@ const CommentEditor: FC = (props) => { referUsers, accountInfo, onCreate, - restProps: { showInputBox, showInputEditor, editContent, creating }, + restProps: { showEditor, editContent, creating }, } = props + if (!showEditor) { + return ( + +
+ + ) + } return ( - +
- {showInputEditor && ( - - )} - + + ) } diff --git a/src/containers/unit/Comments/index.tsx b/src/containers/unit/Comments/index.tsx index 4079ce832..7fc3c0a7a 100755 --- a/src/containers/unit/Comments/index.tsx +++ b/src/containers/unit/Comments/index.tsx @@ -53,6 +53,8 @@ const CommentsContainer: FC = ({ isAllFolded, } = store + console.log('showEditor: ', store.showEditor) + return ( diff --git a/src/containers/unit/Comments/logic.ts b/src/containers/unit/Comments/logic.ts index e6f26cd14..abc33610f 100755 --- a/src/containers/unit/Comments/logic.ts +++ b/src/containers/unit/Comments/logic.ts @@ -60,40 +60,17 @@ export const createComment = curry((cb, e) => { cb() }) -export const backToEditor = (): void => - store.mark({ - showInputEditor: true, - showInputPreview: false, - }) - -export const previewReply = (data): void => { - log('previewReply --> : ', data) -} - -export const openInputBox = (): void => { +export const openEditor = (): void => { if (!store.isLogin) return authWarn({ hideToast: true }) initDraftTimmer() - store.mark({ - showInputBox: true, - showInputEditor: true, - }) -} -export const openCommentEditor = (): void => { - initDraftTimmer() - - store.mark({ - showInputEditor: true, - }) + store.mark({ showEditor: true }) } -export const onCommentInputBlur = (): void => - store.mark({ - showInputBox: false, - showInputPreview: false, - showInputEditor: false, - }) +export const closeEditor = (): void => { + store.mark({ showEditor: false }) +} export const createReplyComment = (): void => { if (!store.validator('reply')) return @@ -271,7 +248,7 @@ const cancelLoading = () => store.mark({ loading: false, creating: false }) export const onReplyEditorClose = (): void => { closeReplyBox() - onCommentInputBlur() + // onCommentInputBlur() } const saveDraftIfNeed = (content): void => { @@ -318,8 +295,7 @@ const DataSolver = [ match: asyncRes('createComment'), action: () => { store.mark({ - showInputBox: false, - showInputEditor: false, + showEditor: false, editContent: '', creating: false, loading: false, diff --git a/src/containers/unit/Comments/store.ts b/src/containers/unit/Comments/store.ts index 40f5c6ccf..f9b893e71 100755 --- a/src/containers/unit/Comments/store.ts +++ b/src/containers/unit/Comments/store.ts @@ -42,11 +42,7 @@ const mentionMapper = (m) => ({ id: m.id, avatar: m.avatar, name: m.nickname }) const CommentsStore = T.model('CommentsStore', { mode: T.optional(T.enumeration([MODE.REPLIES, MODE.TIMELINE]), MODE.REPLIES), // toggle main comment box - showInputBox: T.optional(T.boolean, false), - // toggle editor inside the comment box - showInputEditor: T.optional(T.boolean, true), - // toggle markdown drawer inside the comment box - showInputPreview: T.optional(T.boolean, false), + showEditor: T.optional(T.boolean, false), // toggle modal editor for reply showReplyBox: T.optional(T.boolean, false), diff --git a/src/containers/unit/Comments/styles/editor/header.ts b/src/containers/unit/Comments/styles/editor/header.ts index 25debe840..097f6ea22 100644 --- a/src/containers/unit/Comments/styles/editor/header.ts +++ b/src/containers/unit/Comments/styles/editor/header.ts @@ -3,13 +3,19 @@ import styled from 'styled-components' import Img from '@/Img' import { theme } from '@/utils/themes' import css from '@/utils/css' +import PublishSVG from '@/icons/EditPen' export const Wrapper = styled.div` ${css.flex('align-center')}; height: 50px; margin-left: 10px; + border: 1px solid transparent; + + cursor: pointer; ` -export const ExpandWrapper = styled(Wrapper)` +export const ExpandWrapper = styled.div` + ${css.flex('align-center')}; + height: 50px; margin-left: 0; position: relative; ` @@ -31,6 +37,12 @@ export const LeaveResponseText = styled.div` font-size: 14px; margin-left: 15px; color: ${theme('comment.placeholder')}; + + ${Wrapper}:hover & { + color: ${theme('thread.articleTitle')}; + } + + transition: all 0.2s; ` export const LeaveResponseUsername = styled.div` color: ${theme('comment.username')}; @@ -38,6 +50,17 @@ export const LeaveResponseUsername = styled.div` margin-left: 12px; margin-right: 10px; ` +export const PenIcon = styled(PublishSVG)` + fill: ${theme('thread.articleDigest')}; + ${css.size(15)}; + margin-right: 14px; + + ${Wrapper}:hover & { + fill: ${theme('thread.articleTitle')}; + } + + transition: all 0.2s; +` export const RefUsersWrapper = styled.div` ${css.flex('align-center')}; ` diff --git a/src/containers/unit/Comments/styles/editor/index.ts b/src/containers/unit/Comments/styles/editor/index.ts index 835b47712..89af8195a 100644 --- a/src/containers/unit/Comments/styles/editor/index.ts +++ b/src/containers/unit/Comments/styles/editor/index.ts @@ -1,32 +1,37 @@ import styled from 'styled-components' // import Img from '@/Img' -import type { TActive } from '@/spec' // import { theme } from '@/utils/themes' import css from '@/utils/css' -export const Wrapper = styled.div` +export const Wrapper = styled.div` ${css.flexColumn()}; - padding: ${({ show }) => (show ? '10px 0' : '0')}; - background: ${({ show }) => (show ? 'transparent' : '#013340')}; - min-height: ${({ show }) => (show ? '300px' : '50px')}; + background: #00313e; + min-height: 30px; height: auto; - border-bottom: 3px solid; - border-color: #00424f; - transition: all 0.3s; + border-radius: 10px; + border: 1px solid transparent; - box-shadow: ${({ show }) => - show ? 'none' : '0 1px 4px rgba(0, 0, 0, 0.04)'}; - border-radius: 3px; + &:hover { + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04); + cursor: pointer; + border-color: #00424f; + } ${css.media.mobile` background: #08303c; /* TODO: same as comment background */ `}; + + transition: all 0.2s; ` -export const InputEditorWrapper = styled.div<{ showInputEditor: boolean }>` + +export const ExpandWrapper = styled.div` + ${css.flexColumn()}; + padding: 10px 0; + background: transparent; + min-height: 300px; height: auto; - margin: 0 30px; - margin-bottom: 30px; - display: ${({ showInputEditor }) => (showInputEditor ? 'block' : 'none')}; - font-size: 0.9em; + border-bottom: 3px solid; + border-color: #00424f; + transition: all 0.2s; ` From 26a9d774dc3f6f04f6f20cb250a505db1a53e1da Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 19 Oct 2021 14:58:25 +0800 Subject: [PATCH 04/20] refactor(comment-editor): re-org & ssr cookie logic --- package-lock.json | 42 +++++++-- package.json | 2 +- server/helper.js | 1 - .../Header/DesktopView/ArticleLayout.tsx | 23 ++++- .../styles/desktop_view/article_layout.ts | 10 +++ src/containers/layout/GlobalLayout/logic.ts | 4 + .../ArticleFooter/styles/author_info/index.ts | 2 +- .../unit/Comments/Editor/BodyEditor.tsx | 13 ++- .../unit/Comments/Editor/Footer.tsx | 32 +++++-- .../unit/Comments/Editor/Header.tsx | 25 +----- .../unit/Comments/Editor/ReplyEditor.tsx | 23 ++--- .../unit/Comments/Editor/ReplyHeader.tsx | 20 +---- src/containers/unit/Comments/Editor/index.tsx | 52 +++++------ src/containers/unit/Comments/List/index.tsx | 86 +++++++++--------- src/containers/unit/Comments/index.tsx | 25 +++--- src/containers/unit/Comments/logic.ts | 53 ++++------- src/containers/unit/Comments/schema.ts | 19 +--- src/containers/unit/Comments/spec.ts | 6 ++ src/containers/unit/Comments/store.ts | 88 +++++++++---------- .../unit/Comments/styles/editor/header.ts | 11 --- .../Comments/styles/editor/reply_header.ts | 9 -- src/containers/viewer/ArticleViewer/index.tsx | 2 +- src/pages/post/[id].tsx | 10 +-- utils/bstore.ts | 41 +++------ utils/index.ts | 1 + utils/ssr.js | 21 ++++- 26 files changed, 302 insertions(+), 319 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49203756b..26f9c45b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "chalk": "^2.4.1", "compatible-debug": "^1.0.0", "cookie-parser": "^1.4.4", + "cookies-next": "^2.0.3", "core-js": "3.6.5", "cross-env": "^7.0.2", "express": "^4.16.4", @@ -31,7 +32,6 @@ "graphql": "^15.5.1", "graphql-request": "3.5.0", "graphql-voyager": "^1.0.0-rc.31", - "js-cookie": "^2.2.0", "mastani-codehighlight": "0.0.7", "mobx": "6.3.2", "mobx-react": "7.2.0", @@ -2634,6 +2634,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "node_modules/@types/fined": { "version": "1.1.3", "integrity": "sha512-CWYnSRnun3CGbt6taXeVo2lCbuaj4mchVJ4UF/BdU5TSuIn3AmS13pGMwCsBUoehGbhZrBrpNJZSZI5EVilXww==", @@ -2778,8 +2783,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.9.1", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + "version": "16.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz", + "integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -6868,6 +6874,16 @@ "version": "1.0.6", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/cookies-next": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-2.0.3.tgz", + "integrity": "sha512-sgYc9YxR7eTbZ1ifYhHbwMCVau/deXGx2rhQoIsq3otR+mf1ZfsvMbilS0BzWhk0s1TyOVWalNE7JcaiZfwsGQ==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/node": "^16.10.2", + "cookie": "^0.4.0" + } + }, "node_modules/copy-concurrently": { "version": "1.0.5", "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", @@ -24495,6 +24511,11 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "@types/fined": { "version": "1.1.3", "integrity": "sha512-CWYnSRnun3CGbt6taXeVo2lCbuaj4mchVJ4UF/BdU5TSuIn3AmS13pGMwCsBUoehGbhZrBrpNJZSZI5EVilXww==", @@ -24640,8 +24661,9 @@ "dev": true }, "@types/node": { - "version": "16.9.1", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + "version": "16.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.1.tgz", + "integrity": "sha512-PYGcJHL9mwl1Ek3PLiYgyEKtwTMmkMw4vbiyz/ps3pfdRYLVv+SN7qHVAImrjdAXxgluDEw6Ph4lyv+m9UpRmA==" }, "@types/normalize-package-data": { "version": "2.4.1", @@ -27858,6 +27880,16 @@ "version": "1.0.6", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "cookies-next": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-2.0.3.tgz", + "integrity": "sha512-sgYc9YxR7eTbZ1ifYhHbwMCVau/deXGx2rhQoIsq3otR+mf1ZfsvMbilS0BzWhk0s1TyOVWalNE7JcaiZfwsGQ==", + "requires": { + "@types/cookie": "^0.4.1", + "@types/node": "^16.10.2", + "cookie": "^0.4.0" + } + }, "copy-concurrently": { "version": "1.0.5", "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", diff --git a/package.json b/package.json index 4323ea964..f00a54c21 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "chalk": "^2.4.1", "compatible-debug": "^1.0.0", "cookie-parser": "^1.4.4", + "cookies-next": "^2.0.3", "core-js": "3.6.5", "cross-env": "^7.0.2", "express": "^4.16.4", @@ -63,7 +64,6 @@ "graphql": "^15.5.1", "graphql-request": "3.5.0", "graphql-voyager": "^1.0.0-rc.31", - "js-cookie": "^2.2.0", "mastani-codehighlight": "0.0.7", "mobx": "6.3.2", "mobx-react": "7.2.0", diff --git a/server/helper.js b/server/helper.js index a8d2b2372..f860689b9 100644 --- a/server/helper.js +++ b/server/helper.js @@ -9,7 +9,6 @@ const renderAndCache = ({ req, res, path }) => { // do not cache in dev mode if (dev) { const pagePath = path || req.path - console.log('# pagePath: ', pagePath) return app.render(req, res, pagePath, { ...req.query, ...req.params, diff --git a/src/components/Header/DesktopView/ArticleLayout.tsx b/src/components/Header/DesktopView/ArticleLayout.tsx index 415f94cd3..f4e7e9b09 100644 --- a/src/components/Header/DesktopView/ArticleLayout.tsx +++ b/src/components/Header/DesktopView/ArticleLayout.tsx @@ -7,9 +7,14 @@ import { FC } from 'react' import { ICON } from '@/config' + import { buildLog } from '@/utils/logger' +import { authWarn } from '@/utils/helper' +import Tooltip from '@/components/Tooltip' +import UserCard from '@/components/Cards/UserCard' import Navigator from '@/components/Navigator' +import { useAccount } from '@/hooks' import type { TProps } from '../index' import { @@ -17,6 +22,7 @@ import { InnerWrapper, RouterWrapper, Operations, + LoginHint, MoreIcon, } from '../styles/desktop_view/article_layout' @@ -24,6 +30,8 @@ import { const log = buildLog('C:Header') const ArticleHeader: FC = ({ metric, c11n, community }) => { + const { isLogin, user } = useAccount() + return ( @@ -35,7 +43,20 @@ const ArticleHeader: FC = ({ metric, c11n, community }) => { /> - + {!isLogin ? ( + authWarn({ hideToast: true })}> + 登入 + + ) : ( + } + delay={0} + placement="bottom" + interactive={false} + > + + + )} diff --git a/src/components/Header/styles/desktop_view/article_layout.ts b/src/components/Header/styles/desktop_view/article_layout.ts index d0999a4d0..69bf2c880 100644 --- a/src/components/Header/styles/desktop_view/article_layout.ts +++ b/src/components/Header/styles/desktop_view/article_layout.ts @@ -28,6 +28,16 @@ export const Operations = styled.div<{ metric: TMetric }>` justify-content: ${({ metric }) => getStickerJustify(metric)}; ${({ metric }) => css.fitStickerWidth(metric)}; ` +export const LoginHint = styled.div` + color: ${theme('thread.articleTitle')}; + font-size: 13px; + margin-top: 1px; + + &:hover { + color: ${theme('button.primary')}; + cursor: pointer; + } +` export const MoreIcon = styled(Img)` fill: ${theme('banner.desc')}; ${css.size(24)}; diff --git a/src/containers/layout/GlobalLayout/logic.ts b/src/containers/layout/GlobalLayout/logic.ts index 1d91f4ddb..a1449dc9d 100755 --- a/src/containers/layout/GlobalLayout/logic.ts +++ b/src/containers/layout/GlobalLayout/logic.ts @@ -85,6 +85,10 @@ export const useInit = (_store: TStore, extra): void => { // scrollbars: { autoHide: 'scroll', autoHideDelay: 500 }, // }) + console.log( + 'global accountInfo isValidSession: ', + store.accountInfo.isValidSession, + ) const { online, isMobile } = extra store.mark({ online, isMobile }) diff --git a/src/containers/unit/ArticleFooter/styles/author_info/index.ts b/src/containers/unit/ArticleFooter/styles/author_info/index.ts index 7e506fead..a959ed2f8 100644 --- a/src/containers/unit/ArticleFooter/styles/author_info/index.ts +++ b/src/containers/unit/ArticleFooter/styles/author_info/index.ts @@ -42,6 +42,6 @@ export const AvatarIntro = styled.div` margin-top: 2px; ` export const Avatar = styled(Img)` - ${css.circle(38)}; + ${css.circle(33)}; margin-bottom: 16px; ` diff --git a/src/containers/unit/Comments/Editor/BodyEditor.tsx b/src/containers/unit/Comments/Editor/BodyEditor.tsx index e9662055b..e7aa8d3d8 100755 --- a/src/containers/unit/Comments/Editor/BodyEditor.tsx +++ b/src/containers/unit/Comments/Editor/BodyEditor.tsx @@ -1,24 +1,21 @@ import { FC, memo } from 'react' -import RichEditor from '@/containers/editor/RichEditor/RealEditor' -import EditorFooter from './Footer' +import RichEditor from '@/containers/editor/RichEditor' type TProps = { body?: string - onCreate?: () => void - creating?: boolean + onChange?: (v: string) => void } -const CommentBodyEditor: FC = ({ body, onCreate, creating }) => { +const CommentBodyEditor: FC = ({ body, onChange }) => { return (
onChange(JSON.stringify(v))} /> - -
) } diff --git a/src/containers/unit/Comments/Editor/Footer.tsx b/src/containers/unit/Comments/Editor/Footer.tsx index c51635b3e..2e580c2da 100755 --- a/src/containers/unit/Comments/Editor/Footer.tsx +++ b/src/containers/unit/Comments/Editor/Footer.tsx @@ -1,24 +1,38 @@ import { FC, memo } from 'react' +import type { TSubmitState } from '@/spec' + import WordsCounter from '@/components/WordsCounter' import SubmitButton from '@/components/Buttons/SubmitButton' import { Wrapper } from '../styles/editor/footer' -import { closeEditor } from '../logic' +import { closeEditor, setWordsCountState } from '../logic' type TProps = { - loading: boolean - onCreate: () => void - onFold?: () => void - showFold?: boolean + body: string + label?: string + submitState: TSubmitState + onPublish: () => void } -const EditorFooter: FC = ({ loading, onCreate, showFold, onFold }) => ( +const EditorFooter: FC = ({ + body, + label = '发 布', + submitState, + onPublish, +}) => ( - + diff --git a/src/containers/unit/Comments/Editor/Header.tsx b/src/containers/unit/Comments/Editor/Header.tsx index fb31d50be..b2b735667 100755 --- a/src/containers/unit/Comments/Editor/Header.tsx +++ b/src/containers/unit/Comments/Editor/Header.tsx @@ -1,9 +1,8 @@ import { FC, memo } from 'react' -import type { TAccount, TUser } from '@/spec' -import { ICON, ICON_CMD } from '@/config' +import type { TAccount } from '@/spec' +import { ICON } from '@/config' -import AvatarsRow from '@/components/AvatarsRow' import { SpaceGrow } from '@/components/Common' import { @@ -14,9 +13,6 @@ import { LeaveResponseText, LeaveResponseUsername, PenIcon, - RefUsersWrapper, - RefUserList, - AtSignIcon, } from '../styles/editor/header' import { openEditor } from '../logic' @@ -24,30 +20,15 @@ import { openEditor } from '../logic' type TProps = { accountInfo: TAccount showEditor: boolean - referUsers: TUser[] } -const EditorHeader: FC = ({ accountInfo, showEditor, referUsers }) => { +const EditorHeader: FC = ({ accountInfo, showEditor }) => { if (showEditor) { return ( 创建评论: {accountInfo.nickname} - {referUsers.length > 0 && ( - - - - - - - )} - ) } diff --git a/src/containers/unit/Comments/Editor/ReplyEditor.tsx b/src/containers/unit/Comments/Editor/ReplyEditor.tsx index 6b80421a3..f71fbd210 100755 --- a/src/containers/unit/Comments/Editor/ReplyEditor.tsx +++ b/src/containers/unit/Comments/Editor/ReplyEditor.tsx @@ -1,6 +1,6 @@ import { FC, memo } from 'react' -import type { TAccount, TUser, TComment } from '@/spec' +import type { TAccount, TSubmitState } from '@/spec' import BodyEditor from './BodyEditor' // import ReplyToBar from '../ReplyToBar' @@ -12,39 +12,40 @@ import { Wrapper, InputEditorWrapper } from '../styles/editor/reply_editor' import { createReplyComment } from '../logic' type TProps = { - referUsers: TUser[] show: boolean isEdit: boolean accountInfo: TAccount - // restProps: { - // replyContent: string - // replyToComment: TComment - // replying: boolean - // } + body: string + submitState: TSubmitState } const CommentReplyEditor: FC = ({ - referUsers, show, isEdit, accountInfo, + body, + submitState, // restProps: { replyToComment, replying }, }) => { return ( - + {/* {!isEdit && } */} {show && (
- +
)} - +
) } diff --git a/src/containers/unit/Comments/Editor/ReplyHeader.tsx b/src/containers/unit/Comments/Editor/ReplyHeader.tsx index 76a33f96c..a86d18b7b 100755 --- a/src/containers/unit/Comments/Editor/ReplyHeader.tsx +++ b/src/containers/unit/Comments/Editor/ReplyHeader.tsx @@ -1,38 +1,22 @@ import { FC, memo } from 'react' -import type { TAccount, TUser } from '@/spec' -import { ICON_CMD } from '@/config' - -import { SpaceGrow } from '@/components/Common' -import AvatarsRow from '@/components/AvatarsRow' +import type { TAccount } from '@/spec' import { Wrapper, UserAvatar, LeaveResponseUsername, - ReplyAvatars, - ReferToIcon, } from '../styles/editor/reply_header' type TProps = { accountInfo: TAccount - referUsers: TUser[] } -const ReplyHeader: FC = ({ accountInfo, referUsers }) => { +const ReplyHeader: FC = ({ accountInfo }) => { return ( {accountInfo.nickname} - {referUsers.length > 0 && ( -
- - - - -
- )} -
) } diff --git a/src/containers/unit/Comments/Editor/index.tsx b/src/containers/unit/Comments/Editor/index.tsx index 24ade725d..e3877448e 100644 --- a/src/containers/unit/Comments/Editor/index.tsx +++ b/src/containers/unit/Comments/Editor/index.tsx @@ -1,53 +1,47 @@ import { FC, memo } from 'react' -import type { TAccount, TUser } from '@/spec' +import type { TAccount, TSubmitState } from '@/spec' import Header from './Header' import BodyEditor from './BodyEditor' +import EditorFooter from './Footer' import { Wrapper, ExpandWrapper } from '../styles/editor' +import { commentOnChange, createComment } from '../logic' type TProps = { - referUsers: TUser[] accountInfo: TAccount - - /* TODO: () => void */ - onCreate?: any - - restProps: { - showEditor: boolean - editContent: string - creating: boolean - } + body: string + submitState: TSubmitState + showEditor: boolean } -const CommentEditor: FC = (props) => { - const { - referUsers, - accountInfo, - onCreate, - restProps: { showEditor, editContent, creating }, - } = props - +const CommentEditor: FC = ({ + accountInfo, + submitState, + showEditor, + body, +}) => { if (!showEditor) { return ( -
+
) } return ( -
+ commentOnChange(v, 'commentBody')} + /> + + - ) } diff --git a/src/containers/unit/Comments/List/index.tsx b/src/containers/unit/Comments/List/index.tsx index 95a725d51..bed409e51 100644 --- a/src/containers/unit/Comments/List/index.tsx +++ b/src/containers/unit/Comments/List/index.tsx @@ -2,13 +2,12 @@ import { FC, Fragment, memo } from 'react' import type { TID, TPagedComments } from '@/spec' import Pagi from '@/components/Pagi' -import { CommentLoading } from '@/components/Loading' import { Br } from '@/components/Common' import Header from './Header' import List from './List' -import type { TMode } from '../spec' +import type { TMode, TFoldState } from '../spec' import { pageChange } from '../logic' import { ListsWrapper, CommentBlock } from '../styles/list' @@ -16,8 +15,7 @@ import { ListsWrapper, CommentBlock } from '../styles/list' type TProps = { totalCommentsCount: number pagedComments: TPagedComments - foldedIds: TID[] - isAllFolded: boolean + foldState: TFoldState mode: TMode restProps: { loading: boolean @@ -27,48 +25,52 @@ type TProps = { const CommentsList: FC = ({ totalCommentsCount, - pagedComments: { entries, totalCount, pageSize, pageNumber }, - foldedIds, - isAllFolded, + pagedComments, + foldState, mode, restProps: { loading, tobeDeleteId }, -}) => ( - -
- {/* {loadingFresh && ( - - - - )} */} - - { + const { entries, totalCount, pageSize, pageNumber } = pagedComments + const { foldedIds, isAllFolded } = foldState + + return ( + +
- {/* + {/* {loadingFresh && ( + - */} - -
- {!loading && ( - - )} - -) +
+ )} */} + + + {/* + + */} + +
+ {!loading && ( + + )} + + ) +} export default memo(CommentsList) diff --git a/src/containers/unit/Comments/index.tsx b/src/containers/unit/Comments/index.tsx index 7fc3c0a7a..c99ac4d00 100755 --- a/src/containers/unit/Comments/index.tsx +++ b/src/containers/unit/Comments/index.tsx @@ -20,7 +20,7 @@ import ReplyEditor from './Editor/ReplyEditor' import type { TStore } from './store' import { Wrapper } from './styles' -import { useInit, createComment, onReplyEditorClose } from './logic' +import { useInit, onReplyEditorClose } from './logic' /* eslint-disable-next-line */ const log = buildLog('C:Comments') @@ -29,14 +29,12 @@ type TProps = { comments?: TStore ssr?: boolean locked?: boolean - onCreate?: () => void } const CommentsContainer: FC = ({ comments: store, ssr = false, locked = false, - onCreate = log, }) => { useInit(store, ssr, locked) @@ -44,35 +42,35 @@ const CommentsContainer: FC = ({ mode, viewingArticle, pagedCommentsData, - referUsersData, accountInfo, showReplyBox, showReplyEditor, isEdit, - foldedIds, - isAllFolded, + commentBody, + submitState, + showEditor, + foldState, } = store - console.log('showEditor: ', store.showEditor) - return ( {showReplyBox && ( )} {/*
@@ -87,8 +85,7 @@ const CommentsContainer: FC = ({ diff --git a/src/containers/unit/Comments/logic.ts b/src/containers/unit/Comments/logic.ts index abc33610f..fd26c8d8e 100755 --- a/src/containers/unit/Comments/logic.ts +++ b/src/containers/unit/Comments/logic.ts @@ -1,14 +1,15 @@ import { useEffect } from 'react' -import { curry, isEmpty, reject, equals } from 'ramda' +import { isEmpty, reject, equals } from 'ramda' -import type { TUser, TComment, TID, TEmotionType } from '@/spec' +import type { TUser, TComment, TID, TEmotionType, TEditValue } from '@/spec' import { EVENT, ERR } from '@/constant' import asyncSuit from '@/utils/async' import BStore from '@/utils/bstore' -import { extractMentions, errRescue, authWarn, titleCase } from '@/utils/helper' +import { errRescue, authWarn, titleCase } from '@/utils/helper' import { buildLog } from '@/utils/logger' import { scrollIntoEle } from '@/utils/dom' +import { updateEditing } from '@/utils/mobx' import type { TMode } from './spec' import type { TStore } from './store' @@ -42,23 +43,18 @@ export const loadComments = (): void => { sr71$.query(S.pagedComments, args) } -/* eslint-disable-next-line */ -export const createComment = curry((cb, e) => { - if (!store.validator('create')) return false +export const createComment = (): void => { + if (!store.isReady) return - store.mark({ creating: true }) const args = { id: store.viewingArticle.id, - body: store.editContent, + body: store.commentBody, thread: store.activeThread, - community: store.communityRaw, - mentionUsers: store.referUsersData.map((user) => ({ id: user.id })), } log('createComment args: ', args) - sr71$.mutate(S.createComment, args) - cb() -}) + // sr71$.mutate(S.createComment, args) +} export const openEditor = (): void => { if (!store.isLogin) return authWarn({ hideToast: true }) @@ -83,29 +79,21 @@ export const createReplyComment = (): void => { }) } - if (store.replying) return - - store.mark({ replying: true }) return sr71$.mutate(S.replyComment, { id: store.replyToComment.id, body: store.replyContent, community: store.curCommunity.raw, thread: store.activeThread, - mentionUsers: store.referUsersData.map((user) => ({ id: user.id })), }) } -export const onCommentInputChange = (editContent): void => - store.mark({ - extractMentions: extractMentions(editContent), - editContent, - }) +export const commentOnChange = (e: TEditValue, key: string): void => { + updateEditing(store, key, e) +} -export const onReplyInputChange = (replyContent): void => - store.mark({ - extractMentions: extractMentions(replyContent), - replyContent, - }) +export const setWordsCountState = (wordsCountReady: boolean): void => { + store?.mark({ wordsCountReady }) +} export const openUpdateEditor = (data): void => store.mark({ @@ -220,7 +208,6 @@ export const handleUpvote = ( } } -export const onMention = (user: TUser): void => store.addReferUser(user) export const onMentionSearch = (name: string): void => { if (name?.length >= 1) { sr71$.query(S.searchUsers, { name }) @@ -244,7 +231,7 @@ export const pageChange = (page = 1): void => { scrollIntoEle('lists-info') } -const cancelLoading = () => store.mark({ loading: false, creating: false }) +const cancelLoading = () => store.mark({ loading: false }) export const onReplyEditorClose = (): void => { closeReplyBox() @@ -296,8 +283,7 @@ const DataSolver = [ action: () => { store.mark({ showEditor: false, - editContent: '', - creating: false, + commentBody: '', loading: false, }) stopDraftTimmer() @@ -313,7 +299,6 @@ const DataSolver = [ action: () => { store.mark({ showReplyBox: false, - replying: false, replyToComment: null, }) scrollIntoEle('lists-info') @@ -411,10 +396,10 @@ const initDraftTimmer = (): void => { stopDraftTimmer() saveDraftTimmer = setInterval(() => { - const { showReplyEditor, editContent, replyContent } = store + const { showReplyEditor, commentBody, replyContent } = store if (showReplyEditor) return saveDraftIfNeed(replyContent) - saveDraftIfNeed(editContent) + saveDraftIfNeed(commentBody) }, 3000) } diff --git a/src/containers/unit/Comments/schema.ts b/src/containers/unit/Comments/schema.ts index 250e9d226..c3a3c88e9 100755 --- a/src/containers/unit/Comments/schema.ts +++ b/src/containers/unit/Comments/schema.ts @@ -20,26 +20,13 @@ const pagedComments = gql` } ` const createComment = gql` - mutation createComment( - $community: String! - $thread: CmsThread - $id: ID! - $body: String! - $mentionUsers: [Ids] - ) { - createComment( - community: $community - thread: $thread - id: $id - body: $body - mentionUsers: $mentionUsers - ) { + mutation ($thread: Thread!, $id: ID!, $body: String!) { + createComment(thread: $thread, id: $id, body: $body) { id - body + bodyHtml } } ` - const updateComment = gql` mutation ($thread: CmsThread!, $id: ID!, $body: String!) { updateComment(thread: $thread, id: $id, body: $body) { diff --git a/src/containers/unit/Comments/spec.ts b/src/containers/unit/Comments/spec.ts index 54f2098d3..2d704d805 100644 --- a/src/containers/unit/Comments/spec.ts +++ b/src/containers/unit/Comments/spec.ts @@ -1 +1,7 @@ +import type { TID } from '@/spec' + export type TMode = 'REPLIES' | 'TIMELINE' +export type TFoldState = { + isAllFolded: boolean + foldedIds: TID[] +} diff --git a/src/containers/unit/Comments/store.ts b/src/containers/unit/Comments/store.ts index f9b893e71..a1618d032 100755 --- a/src/containers/unit/Comments/store.ts +++ b/src/containers/unit/Comments/store.ts @@ -7,14 +7,13 @@ import { types as T, getParent, Instance } from 'mobx-state-tree' import { map, findIndex, - filter, - contains, clone, propEq, uniq, concat, toUpper, merge, + pick, } from 'ramda' import type { @@ -29,12 +28,14 @@ import type { TPagedComments, TComment, TEmotion, + TSubmitState, } from '@/spec' // import { TYPE } from '@/constant' import { markStates, toJS } from '@/utils/mobx' import { changeset } from '@/utils/validator' import { Comment, PagedComments, emptyPagi, Mention } from '@/model' +import type { TFoldState } from './spec' import { MODE } from './constant' const mentionMapper = (m) => ({ id: m.id, avatar: m.avatar, name: m.nickname }) @@ -50,10 +51,10 @@ const CommentsStore = T.model('CommentsStore', { // current to be delete comment id, use to target the confirm mask tobeDeleteId: T.maybeNull(T.string), - // words count for current comment (include reply comment) - countCurrent: T.optional(T.number, 0), // content input of current comment editor - editContent: T.optional(T.string, ''), + commentBody: T.optional(T.string, '{}'), + replyBody: T.optional(T.string, '{}'), + wordsCountReady: T.optional(T.boolean, false), // content input of current reply comment editor replyContent: T.optional(T.string, ''), // comments pagination data of current COMMUNITY / PART @@ -62,21 +63,12 @@ const CommentsStore = T.model('CommentsStore', { isEdit: T.optional(T.boolean, false), editComment: T.maybeNull(Comment), - // current "@user" in valid array format - referUsers: T.optional(T.array(Mention), []), - // current "@user" in string list - extractMentions: T.optional(T.array(T.string), []), - // parrent comment of current reply replyToComment: T.maybeNull(Comment), - // mention users in content - mentionList: T.optional(T.array(Mention), []), - // toggle loading for creating comment - creating: T.optional(T.boolean, false), - // toggle loading for creating reply comment - replying: T.optional(T.boolean, false), + publishing: T.optional(T.boolean, false), + publishDone: T.optional(T.boolean, false), // toggle loading for comments list loading: T.optional(T.boolean, false), @@ -87,19 +79,26 @@ const CommentsStore = T.model('CommentsStore', { const root = getParent(self) as TRootStore return root.curRoute }, + get isAllFolded(): boolean { + const slf = self as TStore + const { foldedIds, pagedCommentsData } = slf + return foldedIds.length === pagedCommentsData.totalCount + }, get foldedIds(): TID[] { return toJS(self.foldedCommentIds) }, + get foldState(): TFoldState { + const slf = self as TStore + + return { + foldedIds: slf.foldedCommentIds, + isAllFolded: slf.isAllFolded, + } + }, get isLogin(): boolean { const root = getParent(self) as TRootStore return root.account.isLogin }, - get referUsersData(): TUser[] { - const referUsers = toJS(self.referUsers) - const extractMentions = toJS(self.extractMentions) - // @ts-ignore - return filter((user) => contains(user.name, extractMentions), referUsers) - }, get participators(): TUser[] { const root = getParent(self) as TRootStore const { commentsParticipants } = root.viewing.viewingArticle @@ -121,9 +120,6 @@ const CommentsStore = T.model('CommentsStore', { return map(mentionMapper, commentsParticipants) }, - get mentionListData() { - return toJS(self.mentionList) - }, get pagedCommentsData(): TPagedComments { return toJS(self.pagedComments) }, @@ -154,10 +150,15 @@ const CommentsStore = T.model('CommentsStore', { get editCommentData() { return toJS(self.editComment) }, - get isAllFolded(): boolean { + get isReady(): boolean { const slf = self as TStore - const { foldedIds, pagedCommentsData } = slf - return foldedIds.length === pagedCommentsData.totalCount + const { wordsCountReady } = slf + + return wordsCountReady + }, + get submitState(): TSubmitState { + const slf = self as TStore + return pick(['publishing', 'publishDone', 'isReady'], slf) }, })) .actions((self) => ({ @@ -166,13 +167,18 @@ const CommentsStore = T.model('CommentsStore', { root.changesetErr(options) }, + updateEditing(sobj): void { + const slf = self as TStore + slf.mark(sobj) + }, + validator(type): boolean { const { changesetErr } = self as TStore switch (type) { case 'create': { - const result = changeset({ editContent: self.editContent }) + const result = changeset({ commentBody: self.commentBody }) // @ts-ignore - .exist({ editContent: '讨论内容' }, changesetErr) + .exist({ commentBody: '讨论内容' }, changesetErr) .done() return result.passed @@ -190,26 +196,14 @@ const CommentsStore = T.model('CommentsStore', { } } }, - addReferUser(user: TUser): void { - const index = findIndex((u) => u.id === String(user.id), self.referUsers) - if (index === -1) { - self.referUsers.push({ - id: String(user.id), - name: user.name, - avatar: user.avatar, - }) - } - }, updateMentionList(mentionArray): void { - const curMentionList = clone(self.mentionList) - const uniqList = concat(curMentionList, mentionArray) - const mentionList = map(mentionMapper, uniqList) - - // log('mentionList: ', mentionList) - // log('uniq: ', R.uniq(R.concat(mentionList, self.participators))) + console.log('TODO: updateMentionList') + // const curMentionList = clone(self.mentionList) + // const uniqList = concat(curMentionList, mentionArray) + // const mentionList = map(mentionMapper, uniqList) // @ts-ignore - self.mentionList = uniq(concat(mentionList, self.participators)) + // self.mentionList = uniq(concat(mentionList, self.participators)) }, updateOneComment(id, comment = {}): void { const { entries } = self.pagedCommentsData diff --git a/src/containers/unit/Comments/styles/editor/header.ts b/src/containers/unit/Comments/styles/editor/header.ts index 097f6ea22..02b158521 100644 --- a/src/containers/unit/Comments/styles/editor/header.ts +++ b/src/containers/unit/Comments/styles/editor/header.ts @@ -61,14 +61,3 @@ export const PenIcon = styled(PublishSVG)` transition: all 0.2s; ` -export const RefUsersWrapper = styled.div` - ${css.flex('align-center')}; -` -export const AtSignIcon = styled(Img)` - fill: ${theme('comment.username')}; - ${css.size(15)}; - margin-right: 5px; -` -export const RefUserList = styled.div` - margin-top: -10px; -` diff --git a/src/containers/unit/Comments/styles/editor/reply_header.ts b/src/containers/unit/Comments/styles/editor/reply_header.ts index 2b2b7426a..dd54122eb 100755 --- a/src/containers/unit/Comments/styles/editor/reply_header.ts +++ b/src/containers/unit/Comments/styles/editor/reply_header.ts @@ -25,12 +25,3 @@ export const LeaveResponseUsername = styled.div` color: #96b3b5; margin-right: 10px; ` - -export const ReferToIcon = styled(Img)` - fill: #b7cfd0; - ${css.size(20)}; - margin-right: 5px; - margin-top: 5px; -` - -export const ReplyAvatars = styled.div`` diff --git a/src/containers/viewer/ArticleViewer/index.tsx b/src/containers/viewer/ArticleViewer/index.tsx index 28a57df25..365395c59 100755 --- a/src/containers/viewer/ArticleViewer/index.tsx +++ b/src/containers/viewer/ArticleViewer/index.tsx @@ -36,7 +36,7 @@ const ArticleViewerContainer: FC = ({ - + ) diff --git a/src/pages/post/[id].tsx b/src/pages/post/[id].tsx index 7026acdec..e9c1ff9d5 100755 --- a/src/pages/post/[id].tsx +++ b/src/pages/post/[id].tsx @@ -5,10 +5,10 @@ import { ROUTE, ARTICLE_THREAD, METRIC } from '@/constant' import { ssrBaseStates, ssrFetchPrepare, - ssrRescue, ssrError, articleSEO, ssrGetParam, + refreshIfneed, } from '@/utils' import { useStore } from '@/stores/init' @@ -44,13 +44,11 @@ export const getServerSideProps = async (context) => { let resp try { resp = await fetchData(context) + const { post, sessionState } = resp + refreshIfneed(sessionState, `/post/${post.id}`, context) } catch (e) { console.log('#### error from server: ', e) - if (ssrRescue.hasLoginError(e.response?.errors)) { - resp = await fetchData(context, { tokenExpired: true }) - } else { - return ssrError(context, 'fetch', 500) - } + return ssrError(context, 'fetch', 500) } const { post } = resp diff --git a/utils/bstore.ts b/utils/bstore.ts index 919d04aa2..0630c1fe2 100755 --- a/utils/bstore.ts +++ b/utils/bstore.ts @@ -1,29 +1,5 @@ import store from 'store' -import Cookies from 'js-cookie' -import { path } from 'ramda' - -/* eslint-disable */ -const _has_key = (cookie: string, key: string): boolean => { - return new RegExp( - '(?:^|;\\s*)' + escape(key).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=', - ).test(cookie) -} - -// NOTE: this is used only in next's getInitialProps function -// because getInitialProps is runing on server, do not hove browser cookie -const from_req = (req: Record, key: string): string => { - const cookie: string = path(['headers', 'cookie'], req) - if (!cookie || !key || !_has_key(cookie, key)) { - return null - } - const regexpStr = - '(?:^|.*;\\s*)' + - escape(key).replace(/[\-\.\+\*]/g, '\\$&') + - '\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*' - // @ts-ignore - return unescape(cookie.replace(new RegExp(regexpStr), '$1')) -} -/* eslint-enable */ +import { setCookies, getCookie, removeCookies } from 'cookies-next' // js-cookie details: https://github.com/js-cookie/js-cookie // store.js details: https://github.com/marcuswestin/store.js @@ -35,12 +11,15 @@ const BStore = { remove: (key: string): void => store.remove(key), clearAll: (): void => store.clearAll(), cookie: { - from_req: (req: Record, key: string): string => - from_req(req, key), - set: (key: string, val: string, opt = {}): string => - Cookies.set(key, val, opt), - get: (key: string): string => Cookies.get(key), - remove: (key: string): void => Cookies.remove(key), + ssrGet: (context, key) => { + return getCookie(key, context) as string | undefined + }, + ssrSet: (context, key, value): void => { + return setCookies(key, value, context) + }, + ssrRemove: (context, key) => removeCookies(key, context), + set: (key, value) => setCookies(key, value), + remove: (key) => removeCookies(key), }, } diff --git a/utils/index.ts b/utils/index.ts index e54659da3..6593ec5ee 100755 --- a/utils/index.ts +++ b/utils/index.ts @@ -102,6 +102,7 @@ export { validCommunityFilters, parseTheme, ssrGetParam, + refreshIfneed, } from './ssr' export { diff --git a/utils/ssr.js b/utils/ssr.js index 9a12cf222..801205bf1 100755 --- a/utils/ssr.js +++ b/utils/ssr.js @@ -79,9 +79,26 @@ const ssrFetchToken = (context, opt) => { // get jwt from cookie or localStorage // props has to be getInitialProps's arg export const getJwtToken = (context) => { - if (isServerSide) return BStore.cookie.from_req(context.req, 'jwtToken') + return BStore.cookie.ssrGet(context, 'jwtToken') +} + +export const isTokenExpired = (sessionState, context) => { + if (!sessionState.isValid && getJwtToken(context)) { + return true + } - return BStore.get('token') + return false +} + +/** + * if the token is expired, then clear cookie and refresh + */ +export const refreshIfneed = (sessionState, path = '/', context) => { + if (isTokenExpired(sessionState, context)) { + BStore.cookie.ssrRemove(context, 'jwtToken') + context.res.writeHead(302, { Location: path }) + context.res.end() + } } export const ssrPagedArticleSchema = (threadPath) => { From 0d0ca60aa95473a6c8db1d9c6da0b5165f4f7c4f Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 19 Oct 2021 15:35:27 +0800 Subject: [PATCH 05/20] refactor(comment-editor): publish workflow done & style dajust --- .../Upvote/styles/comment_layout.ts | 2 +- src/containers/unit/Comments/List/index.tsx | 8 ------ src/containers/unit/Comments/logic.ts | 27 ++++++++++--------- src/containers/unit/Comments/store.ts | 2 +- .../styles/comment/desktop_view/index.ts | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/components/Upvote/styles/comment_layout.ts b/src/components/Upvote/styles/comment_layout.ts index 24003a422..8adb90bef 100755 --- a/src/components/Upvote/styles/comment_layout.ts +++ b/src/components/Upvote/styles/comment_layout.ts @@ -19,5 +19,5 @@ export const UpWrapper = styled.div` ` export const CountWrapper = styled.div` margin-top: -4px; - margin-left: 1px; + margin-left: 3px; ` diff --git a/src/containers/unit/Comments/List/index.tsx b/src/containers/unit/Comments/List/index.tsx index bed409e51..01adebbd3 100644 --- a/src/containers/unit/Comments/List/index.tsx +++ b/src/containers/unit/Comments/List/index.tsx @@ -41,11 +41,6 @@ const CommentsList: FC = ({ mode={mode} loading={loading} /> - {/* {loadingFresh && ( - - - - )} */} = ({ foldedIds={foldedIds} tobeDeleteId={tobeDeleteId} /> - {/* - - */}
{!loading && ( diff --git a/src/containers/unit/Comments/logic.ts b/src/containers/unit/Comments/logic.ts index fd26c8d8e..19f606189 100755 --- a/src/containers/unit/Comments/logic.ts +++ b/src/containers/unit/Comments/logic.ts @@ -29,14 +29,14 @@ let saveDraftTimmer = null let store: TStore | undefined // variables = %{id: post.id, thread: "POST", filter: %{page: 1, size: page_size}} -export const loadComments = (): void => { +export const loadComments = (page = 1): void => { const { viewingArticle: article, mode } = store const args = { id: article.id, thread: article.meta.thread, mode, - filter: { page: 1, size: 20 }, + filter: { page, size: 20 }, } log('query args: ', args) store.mark({ loading: true }) @@ -53,7 +53,8 @@ export const createComment = (): void => { } log('createComment args: ', args) - // sr71$.mutate(S.createComment, args) + store.mark({ publishing: true }) + sr71$.mutate(S.createComment, args) } export const openEditor = (): void => { @@ -248,10 +249,12 @@ const saveDraftIfNeed = (content): void => { const clearDraft = (): void => BStore.remove('recentDraft') export const foldComment = (id: TID): void => { + console.log('foldComment: ', id) store.mark({ foldedCommentIds: [id, ...store.foldedCommentIds] }) } export const expandComment = (id: TID): void => { + console.log('expandComment: ', id) store.mark({ foldedCommentIds: reject(equals(id), store.foldedCommentIds) }) } @@ -281,17 +284,17 @@ const DataSolver = [ { match: asyncRes('createComment'), action: () => { - store.mark({ - showEditor: false, - commentBody: '', - loading: false, - }) + store.mark({ loading: true, publishing: false, publishDone: true }) + loadComments() + setTimeout(() => { + store.mark({ + showEditor: false, + commentBody: '', + publishDone: false, + }) + }, 500) stopDraftTimmer() clearDraft() - // loadComents({ - // filter: { page: 1, sort: TYPE.DESC_INSERTED }, - // fresh: true, - // }) }, }, { diff --git a/src/containers/unit/Comments/store.ts b/src/containers/unit/Comments/store.ts index a1618d032..b4dca45e2 100755 --- a/src/containers/unit/Comments/store.ts +++ b/src/containers/unit/Comments/store.ts @@ -91,7 +91,7 @@ const CommentsStore = T.model('CommentsStore', { const slf = self as TStore return { - foldedIds: slf.foldedCommentIds, + foldedIds: toJS(slf.foldedCommentIds), isAllFolded: slf.isAllFolded, } }, diff --git a/src/containers/unit/Comments/styles/comment/desktop_view/index.ts b/src/containers/unit/Comments/styles/comment/desktop_view/index.ts index 629abc82b..582043800 100644 --- a/src/containers/unit/Comments/styles/comment/desktop_view/index.ts +++ b/src/containers/unit/Comments/styles/comment/desktop_view/index.ts @@ -69,7 +69,7 @@ export const IndentLine = styled.div` height: 100%; border-left: 1px dashed; border-left-color: ${theme('comment.indentLine')}; - margin-left: 6px; + margin-left: 5px; margin-top: 8px; opacity: 1; From 194f37deadfb872abb9e79c04f60b5a536dd74c0 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 19 Oct 2021 17:07:20 +0800 Subject: [PATCH 06/20] refactor(update): put isAuthorUptoved into workflow --- src/components/Icons/UserBadge.tsx | 18 ++++++++++++++++++ .../Comment/DesktopView/DefaultLayout.tsx | 4 ++-- src/containers/unit/Comments/logic.ts | 16 ++++++++++++---- src/containers/unit/Comments/schema.ts | 6 ++++++ src/containers/unit/Comments/store.ts | 9 ++++++++- .../styles/comment/desktop_view/index.ts | 11 +++++++---- 6 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 src/components/Icons/UserBadge.tsx diff --git a/src/components/Icons/UserBadge.tsx b/src/components/Icons/UserBadge.tsx new file mode 100644 index 000000000..cffec18c5 --- /dev/null +++ b/src/components/Icons/UserBadge.tsx @@ -0,0 +1,18 @@ +import { memo, SVGProps } from 'react' + +const UserBadge = (props: SVGProps) => { + return ( + + + + ) +} + +export default memo(UserBadge) diff --git a/src/containers/unit/Comments/Comment/DesktopView/DefaultLayout.tsx b/src/containers/unit/Comments/Comment/DesktopView/DefaultLayout.tsx index 2fa8dfb90..f1c4007c8 100644 --- a/src/containers/unit/Comments/Comment/DesktopView/DefaultLayout.tsx +++ b/src/containers/unit/Comments/Comment/DesktopView/DefaultLayout.tsx @@ -67,11 +67,11 @@ const DefaultLayout: FC = ({ data, tobeDeleteId, isReply = false }) => { /> {isArticleAuthorUpvoted && ( 作者顶过} + content={作者赞过} placement="bottom" noPadding > - + )} {isSolution && ( diff --git a/src/containers/unit/Comments/logic.ts b/src/containers/unit/Comments/logic.ts index 19f606189..b1a136f42 100755 --- a/src/containers/unit/Comments/logic.ts +++ b/src/containers/unit/Comments/logic.ts @@ -325,15 +325,23 @@ const DataSolver = [ { match: asyncRes('upvoteComment'), action: ({ upvoteComment }) => { - const { upvotesCount, viewerHasUpvoted } = upvoteComment - store.updateUpvote(upvoteComment, { upvotesCount, viewerHasUpvoted }) + const { upvotesCount, viewerHasUpvoted, meta } = upvoteComment + store.updateUpvote(upvoteComment, { + upvotesCount, + viewerHasUpvoted, + meta, + }) }, }, { match: asyncRes('undoUpvoteComment'), action: ({ undoUpvoteComment }) => { - const { upvotesCount, viewerHasUpvoted } = undoUpvoteComment - store.updateUpvote(undoUpvoteComment, { upvotesCount, viewerHasUpvoted }) + const { upvotesCount, viewerHasUpvoted, meta } = undoUpvoteComment + store.updateUpvote(undoUpvoteComment, { + upvotesCount, + viewerHasUpvoted, + meta, + }) }, }, { diff --git a/src/containers/unit/Comments/schema.ts b/src/containers/unit/Comments/schema.ts index c3a3c88e9..8f692c9be 100755 --- a/src/containers/unit/Comments/schema.ts +++ b/src/containers/unit/Comments/schema.ts @@ -68,6 +68,9 @@ const upvoteComment = gql` mutation ($id: ID!) { upvoteComment(id: $id) { id + meta { + isArticleAuthorUpvoted + } upvotesCount viewerHasUpvoted replyToId @@ -78,6 +81,9 @@ const undoUpvoteComment = gql` mutation ($id: ID!) { undoUpvoteComment(id: $id) { id + meta { + isArticleAuthorUpvoted + } upvotesCount viewerHasUpvoted replyToId diff --git a/src/containers/unit/Comments/store.ts b/src/containers/unit/Comments/store.ts index b4dca45e2..b24395df4 100755 --- a/src/containers/unit/Comments/store.ts +++ b/src/containers/unit/Comments/store.ts @@ -224,6 +224,9 @@ const CommentsStore = T.model('CommentsStore', { const replyIndex = findIndex(propEq('id', id), parentComment.replies) if (replyIndex < 0) return const replyComment = parentComment.replies[replyIndex] + if (info.meta) { + info.meta = { ...replyComment.meta, ...info.meta } + } self.pagedComments.entries[parentIndex].replies[replyIndex] = { ...replyComment, ...info, @@ -233,8 +236,12 @@ const CommentsStore = T.model('CommentsStore', { const index = findIndex(propEq('id', id), entries) if (index < 0) return + const comment = entries[index] + if (info.meta) { + info.meta = { ...comment.meta, ...info.meta } + } // @ts-ignore - self.pagedComments.entries[index] = { ...entries[index], ...info } + self.pagedComments.entries[index] = { ...comment, ...info } } }, upvoteEmotion(comment: TComment, emotion: TEmotion): void { diff --git a/src/containers/unit/Comments/styles/comment/desktop_view/index.ts b/src/containers/unit/Comments/styles/comment/desktop_view/index.ts index 582043800..358d7860c 100644 --- a/src/containers/unit/Comments/styles/comment/desktop_view/index.ts +++ b/src/containers/unit/Comments/styles/comment/desktop_view/index.ts @@ -3,8 +3,10 @@ import styled from 'styled-components' import Img from '@/Img' import { theme } from '@/utils/themes' import css from '@/utils/css' +import animate from '@/utils/animations' import PinSVG from '@/icons/Pin' +import UserBadge from '@/icons/UserBadge' type TWrapper = { isPinned: boolean @@ -51,11 +53,12 @@ export const BadgePopContent = styled.div` padding: 5px 10px; font-size: 12px; ` -export const AuthorUpvotedIcon = styled(Img)` - ${css.size(14)}; +export const AuthorUpvotedIcon = styled(UserBadge)` + ${css.size(15)}; fill: ${theme('comment.icon')}; - opacity: 0.6; - margin-top: 3px; + opacity: 0.8; + margin-top: 4px; + animation: ${animate.zoomIn} 0.2s linear; ` export const SolutionIcon = styled(Img)<{ isAuthorUpvoted: boolean }>` ${css.size(14)}; From b8822203ffeec8bec032ef4744f0e70ba6a3f3de Mon Sep 17 00:00:00 2001 From: mydearxym Date: Tue, 19 Oct 2021 23:44:37 +0800 Subject: [PATCH 07/20] refactor(comment-editor): update logic wip --- src/components/Icons/CloseCross.tsx | 17 ++++++ src/components/Modal/index.tsx | 9 +-- src/components/Modal/styles/index.ts | 13 ++-- .../unit/Comments/Comment/Actions.tsx | 10 +++- .../unit/Comments/Editor/Footer.tsx | 6 +- .../unit/Comments/Editor/ReplyEditor.tsx | 5 +- .../unit/Comments/Editor/UpdateEditor.tsx | 60 +++++++++++++++++++ src/containers/unit/Comments/Editor/index.tsx | 7 ++- src/containers/unit/Comments/constant.ts | 8 ++- src/containers/unit/Comments/index.tsx | 21 ++++++- src/containers/unit/Comments/logic.ts | 37 +++++++----- src/containers/unit/Comments/schema.ts | 9 +++ src/containers/unit/Comments/spec.ts | 2 + src/containers/unit/Comments/store.ts | 23 +++---- .../unit/Comments/styles/editor/footer.ts | 2 +- .../Comments/styles/editor/update_editor.ts | 35 +++++++++++ 16 files changed, 207 insertions(+), 57 deletions(-) create mode 100644 src/components/Icons/CloseCross.tsx create mode 100644 src/containers/unit/Comments/Editor/UpdateEditor.tsx create mode 100644 src/containers/unit/Comments/styles/editor/update_editor.ts diff --git a/src/components/Icons/CloseCross.tsx b/src/components/Icons/CloseCross.tsx new file mode 100644 index 000000000..ba647be18 --- /dev/null +++ b/src/components/Icons/CloseCross.tsx @@ -0,0 +1,17 @@ +import { memo, SVGProps } from 'react' + +const CloseCross = (props: SVGProps) => { + return ( + + + + ) +} + +export default memo(CloseCross) diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index 0e61e9f64..f2d6b9f8f 100755 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -77,13 +77,8 @@ const Modal: FC = ({ offsetTop={offsetTop} > setVisibleOnPage(true)} /> - - Esc + {showCloseBtn && } + {showCloseBtn && Esc} e.stopPropagation()}> {children} diff --git a/src/components/Modal/styles/index.ts b/src/components/Modal/styles/index.ts index e2646a664..3e774b5b1 100755 --- a/src/components/Modal/styles/index.ts +++ b/src/components/Modal/styles/index.ts @@ -5,6 +5,7 @@ import { theme } from '@/utils/themes' import css from '@/utils/css' import animate from '@/utils/animations' import Img from '@/Img' +import CloseCrossSVG from '@/icons/CloseCross' // display: ${props => (props.show ? 'block' : 'none')}; export const Mask = styled.div` @@ -51,20 +52,18 @@ export const ChildrenWrapper = styled.div` height: auto; overflow-y: scroll; ` -type TCloseBtn = TActive & { mode: string } -export const CloseBtn = styled(Img)` - fill: ${({ mode }) => - mode === 'default' ? theme('font') : theme('baseColor.red')}; +type TCloseBtn = { mode: string } +export const CloseBtn = styled(CloseCrossSVG)` position: absolute; top: 0; right: -48px; + fill: ${({ mode }) => + mode === 'default' ? '#0A658A' : theme('baseColor.red')}; ${css.size(30)}; - display: ${({ show }) => (show ? 'block' : 'none')}; z-index: ${css.zIndex.modalCloseBtn}; &:hover { - animation: ${animate.rotate360} 2s cubic-bezier(0, 0.56, 0.24, 0.72); - font-weight: bold; + animation: ${animate.pulse} 0.3s linear; cursor: pointer; } ` diff --git a/src/containers/unit/Comments/Comment/Actions.tsx b/src/containers/unit/Comments/Comment/Actions.tsx index fb3e54594..4ac0e09b4 100755 --- a/src/containers/unit/Comments/Comment/Actions.tsx +++ b/src/containers/unit/Comments/Comment/Actions.tsx @@ -1,6 +1,6 @@ import { FC, memo, useCallback } from 'react' -import type { TAccount, TComment } from '@/spec' +import type { TComment } from '@/spec' import { ICON } from '@/config' import { useAccount } from '@/hooks' @@ -16,6 +16,11 @@ type TProps = { } const menuOptions = [ + // { + // key: 'edit', + // icon: `${ICON}/edit/publish-pen.svg`, + // title: '编辑', + // }, { key: 'quote', icon: `${ICON}/shape/quote.svg`, @@ -35,11 +40,10 @@ const menuOptions = [ const Actions: FC = ({ data }) => { const { user } = useAccount() - const accountId = user.id let extraOptions = [] - if (String(data.author.id) === accountId) { + if (data.author.login === user.login) { extraOptions = [ { key: 'edit', diff --git a/src/containers/unit/Comments/Editor/Footer.tsx b/src/containers/unit/Comments/Editor/Footer.tsx index 2e580c2da..19e2038ed 100755 --- a/src/containers/unit/Comments/Editor/Footer.tsx +++ b/src/containers/unit/Comments/Editor/Footer.tsx @@ -6,13 +6,14 @@ import WordsCounter from '@/components/WordsCounter' import SubmitButton from '@/components/Buttons/SubmitButton' import { Wrapper } from '../styles/editor/footer' -import { closeEditor, setWordsCountState } from '../logic' +import { setWordsCountState } from '../logic' type TProps = { body: string label?: string submitState: TSubmitState onPublish: () => void + onCancel: () => void } const EditorFooter: FC = ({ @@ -20,6 +21,7 @@ const EditorFooter: FC = ({ label = '发 布', submitState, onPublish, + onCancel, }) => ( = ({ okText={label} submitState={submitState} onPublish={onPublish} - onCancel={closeEditor} + onCancel={onCancel} /> ) diff --git a/src/containers/unit/Comments/Editor/ReplyEditor.tsx b/src/containers/unit/Comments/Editor/ReplyEditor.tsx index f71fbd210..692ffc2ec 100755 --- a/src/containers/unit/Comments/Editor/ReplyEditor.tsx +++ b/src/containers/unit/Comments/Editor/ReplyEditor.tsx @@ -5,7 +5,7 @@ import type { TAccount, TSubmitState } from '@/spec' import BodyEditor from './BodyEditor' // import ReplyToBar from '../ReplyToBar' import ReplyHeader from './ReplyHeader' -import EditorFooter from './Footer' +import Footer from './Footer' import { Wrapper, InputEditorWrapper } from '../styles/editor/reply_editor' @@ -41,10 +41,11 @@ const CommentReplyEditor: FC = ({
)} -
) diff --git a/src/containers/unit/Comments/Editor/UpdateEditor.tsx b/src/containers/unit/Comments/Editor/UpdateEditor.tsx new file mode 100644 index 000000000..34190d676 --- /dev/null +++ b/src/containers/unit/Comments/Editor/UpdateEditor.tsx @@ -0,0 +1,60 @@ +import { FC, memo } from 'react' + +import type { TSubmitState } from '@/spec' + +import { LavaLampLoading } from '@/components/dynamic' +import CustomScroller from '@/components/CustomScroller' + +import BodyEditor from './BodyEditor' +import Footer from './Footer' + +import { + Wrapper, + Header, + EditorWrapper, + FooterWrapper, +} from '../styles/editor/update_editor' +import { commentOnChange, createComment, closeUpdateEditor } from '../logic' + +type TProps = { + body: string + submitState: TSubmitState + id: string +} + +const UpdateEditor: FC = ({ id, body, submitState }) => { + return ( + +
修改评论
+ + + {id !== '' ? ( + commentOnChange(v, 'commentBody')} + /> + ) : ( + + )} + + + + +