diff --git a/package.json b/package.json
index 59a90e7f..e7da03b6 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-icons": "^4.1.0",
- "react-markdown-editor-lite": "^1.2.4",
+ "react-markdown-editor-lite-sunface": "^1.2.5",
"validator": "^13.5.2"
},
"devDependencies": {
diff --git a/pages/test.tsx b/pages/test.tsx
new file mode 100644
index 00000000..16de7a32
--- /dev/null
+++ b/pages/test.tsx
@@ -0,0 +1,63 @@
+import useCaretPosition from 'components/markdown-editor/position'
+import TestStyles from 'theme/caret.styles'
+import React, { useRef, useState, useEffect, Fragment } from 'react'
+import { render } from 'react-dom'
+
+
+const App = () => {
+ const triggerRef = useRef(null)
+ const [showTrigger, setShowTrigger] = useState(false)
+ const {
+ x: triggerX,
+ y: triggerY,
+ getPosition: getPositionTrigger,
+ } = useCaretPosition(triggerRef)
+
+ const handleCustomUI = (e) => {
+ const previousCharacter = e.target.value
+ .charAt(triggerRef.current.selectionStart - 2)
+ .trim()
+ const character = e.target.value
+ .charAt(triggerRef.current.selectionStart - 1)
+ .trim()
+ if (character === '@' && previousCharacter === '') {
+ setShowTrigger(true)
+ }
+ if (character === '' && showTrigger) {
+ setShowTrigger(false)
+ }
+ }
+
+ useEffect(() => {
+ if (triggerRef.current) {
+ getPositionTrigger(triggerRef)
+ }
+ }, [])
+
+ return (
+ <>
+
+
+ >
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/src/components/comments/comment.tsx b/src/components/comments/comment.tsx
index f3d7c143..835b2eb1 100644
--- a/src/components/comments/comment.tsx
+++ b/src/components/comments/comment.tsx
@@ -46,7 +46,7 @@ export const CommentCard = (props: Props) => {
return (
<>{
- editorVisible ? (user && {setEditorVisible(false);changeComment(md)}} onCancel={() => setEditorVisible(false)} />) :
+ editorVisible ? (user && {setEditorVisible(false);changeComment(md)}} onCancel={() => setEditorVisible(false)} menu={false}/>) :
@@ -95,12 +95,12 @@ export const CommentCard = (props: Props) => {
- {replyVisible && {submitReply(md)}} onCancel={() => setReplyVisible(false)} />}
+ {replyVisible && {submitReply(md)}} onCancel={() => setReplyVisible(false)} />}
{comment.replies.map(reply =>
-
+
)}
}
diff --git a/src/components/comments/comments.tsx b/src/components/comments/comments.tsx
index e4bb8290..a087f363 100644
--- a/src/components/comments/comments.tsx
+++ b/src/components/comments/comments.tsx
@@ -5,10 +5,11 @@ import useSession from "hooks/use-session"
import { requestApi } from "utils/axios/request"
import CommentCard from "./comment"
import CommentEditor from "./editor"
+import { Comment } from "src/types/comments"
interface Props {
storyID: string
- comments: any[]
+ comments: Comment[]
onChange: any
}
export const Comments = ({storyID, comments,onChange }: Props) => {
@@ -20,12 +21,21 @@ export const Comments = ({storyID, comments,onChange }: Props) => {
onChange()
}
+ const countComments = () => {
+ let n = comments.length
+ for (const c of comments) {
+ n += c.replies.length
+ }
+
+ return n
+ }
+
return (
- Comments ({comments.length})
+ Comments ({countComments()})
diff --git a/src/components/comments/editor.tsx b/src/components/comments/editor.tsx
index ea331ee2..41844ed4 100644
--- a/src/components/comments/editor.tsx
+++ b/src/components/comments/editor.tsx
@@ -15,6 +15,7 @@ interface Props {
md: string
onSubmit: any
onCancel: any
+ menu?: boolean
}
export const CommentEditor = (props: Props) => {
@@ -31,7 +32,7 @@ export const CommentEditor = (props: Props) => {
setEditMode(m)}/>
- {editMode===EditMode.Edit ? setMd(md)}/> : }
+ {editMode===EditMode.Edit ? setMd(md)}/> : }
diff --git a/src/components/comments/reply.tsx b/src/components/comments/reply.tsx
index 2f554524..01c4a3d5 100644
--- a/src/components/comments/reply.tsx
+++ b/src/components/comments/reply.tsx
@@ -14,17 +14,19 @@ import { requestApi } from "utils/axios/request"
interface Props {
user: User
comment: Comment
+ parent: Comment
onChange: any
}
export const Reply = (props: Props) => {
- const { comment, user,onChange} = props
+ const { comment, user,onChange,parent} = props
const [editorVisible, setEditorVisible] = useState(false)
const [replyVisible,setReplyVisible] = useState(false)
const [reply,setReply] = useState('')
const submitReply = async (md) => {
- await requestApi.post('/story/comment',{targetID: comment.id, md: md})
+ await requestApi.post('/story/comment',{targetID: parent.id, md: md})
setReplyVisible(false);
+ onChange()
}
const changeReply = async (md) => {
@@ -44,9 +46,19 @@ export const Reply = (props: Props) => {
}
+ const replyToReply = () => {
+ if (comment.creator.nickname === "") {
+ setReply(`@${comment.creator.username}`)
+ } else {
+ setReply(`[@${comment.creator.nickname}](/${comment.creator.username})`)
+ }
+
+ setReplyVisible(!replyVisible)
+ }
+
return (
<>{
- editorVisible ? (user && {setEditorVisible(false);changeReply(md)}} onCancel={() => setEditorVisible(false)} />) :
+ editorVisible ? (user && {setEditorVisible(false);changeReply(md)}} onCancel={() => setEditorVisible(false)} menu={false} />) :
@@ -69,7 +81,7 @@ export const Reply = (props: Props) => {
_focus={null}
color="gray.500"
icon={}
- onClick={() => setReplyVisible(!replyVisible)}
+ onClick={replyToReply}
fontSize="18px"
/>}
@@ -95,7 +107,7 @@ export const Reply = (props: Props) => {
{replyVisible &&
- {submitReply(md)}} onCancel={() => setReplyVisible(false)} />
+ {submitReply(md)}} onCancel={() => setReplyVisible(false)} menu={false}/>
}
}
>
diff --git a/src/components/markdown-editor/editor.tsx b/src/components/markdown-editor/editor.tsx
index 2ffb7c22..b4258d29 100644
--- a/src/components/markdown-editor/editor.tsx
+++ b/src/components/markdown-editor/editor.tsx
@@ -1,11 +1,13 @@
-import React from 'react';
+/*eslint-disable*/
+import React, { useRef, useEffect,useState} from 'react';
import 'highlight.js/styles/atom-one-dark.css';
-import { chakra,PropsOf} from '@chakra-ui/react';
+import { chakra,Popover,PopoverTrigger,PopoverContent,PopoverBody,Box,PropsOf, useDisclosure} from '@chakra-ui/react';
import dynamic from 'next/dynamic';
-import 'react-markdown-editor-lite/lib/index.css';
-
-const MdEditor = dynamic(() => import('react-markdown-editor-lite'), {
+import 'react-markdown-editor-lite-sunface/lib/index.css';
+import useCaretPosition from './position'
+import CaretStyles from 'theme/caret.styles'
+const MdEditor = dynamic(() => import('node_modules/react-markdown-editor-lite-sunface'), {
ssr: false
});
@@ -14,17 +16,52 @@ const MdEditor = dynamic(() => import('react-markdown-editor-lite'), {
type Props = PropsOf & {
md: string
onChange: any
+ menu?: boolean
}
-export function MarkdownEditor(props) {
+export function MarkdownEditor(props:Props) {
+ const { onOpen, onClose, isOpen } = useDisclosure()
+
function handleEditorChange({html, text}) {
props.onChange(text)
+ onOpen()
}
+
+ const triggerRef = useRef(null)
+ const [showTrigger, setShowTrigger] = useState(false)
+ const {
+ x: triggerX,
+ y: triggerY,
+ getPosition: getPositionTrigger,
+ } = useCaretPosition(triggerRef)
+
+ const handleCustomUI = (e) => {
+ const previousCharacter = e.target.value
+ .charAt(triggerRef.current.selectionStart - 2)
+ .trim()
+ const character = e.target.value
+ .charAt(triggerRef.current.selectionStart - 1)
+ .trim()
+ if (character === '@' && previousCharacter === '') {
+ setShowTrigger(true)
+ }
+ if (character === '' && showTrigger) {
+ setShowTrigger(false)
+ }
+ }
+
+ useEffect(() => {
+ if (triggerRef.current) {
+ getPositionTrigger(triggerRef)
+ }
+ }, [])
+
return (
-
+ {/* */}
+
+