Skip to content

Commit

Permalink
Merge pull request #4452 from thematters/feat/revise-quote-comment
Browse files Browse the repository at this point in the history
Quote comment
  • Loading branch information
wlliaml authored May 27, 2024
2 parents 5044975 + fb761e8 commit b50eb4f
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 78 deletions.
63 changes: 61 additions & 2 deletions src/common/utils/dom.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'

import { dom } from './dom'
import { dom, isElementInViewport } from './dom'

describe('utils/dom/getAttributes', () => {
it('should return an empty array if no matches are found', () => {
Expand All @@ -27,3 +27,62 @@ describe('utils/dom/getAttributes', () => {
expect(result).toEqual(['image.jpg'])
})
})

describe('utils/detect/isElementInViewport', () => {
let element: HTMLElement

beforeEach(() => {
element = document.createElement('div')
document.body.appendChild(element)

element.getBoundingClientRect = vi.fn(() => ({
top: 0,
left: 0,
bottom: 0,
right: 0,
width: 0,
height: 0,
x: 0,
y: 0,
toJSON: () => ({}),
}))
})

afterEach(() => {
document.body.removeChild(element)
})

it('should return true if the element is in the viewport', () => {
element.getBoundingClientRect = vi.fn(() => ({
top: 100,
left: 100,
bottom: 200,
right: 200,
width: 100,
height: 100,
x: 100,
y: 100,
toJSON: () => ({}),
}))

const result = isElementInViewport(element)
expect(result).toBe(true)
})

it('should return false if the element is not in the viewport', () => {
element.getBoundingClientRect = vi.fn(() => ({
top: 900,
left: 700,
bottom: 1000,
right: 800,
width: 100,
height: 100,
x: 700,
y: 900,
toJSON: () => ({}),
}))

const result = isElementInViewport(element)
expect(result).toBe(false)
})
})
11 changes: 11 additions & 0 deletions src/common/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ export const dom = {
$$,
getAttributes,
}

export const isElementInViewport = (element: Element): boolean => {
const rect = element.getBoundingClientRect()
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
)
}
19 changes: 17 additions & 2 deletions src/components/CommentBeta/FooterActions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Editor } from '@matters/matters-editor'
import gql from 'graphql-tag'
import { useContext, useEffect, useRef, useState } from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
Expand All @@ -16,6 +17,7 @@ import {
Media,
Spacer,
toast,
useCommentEditorContext,
ViewerContext,
} from '~/components'
import {
Expand Down Expand Up @@ -97,6 +99,8 @@ const BaseFooterActions = ({

const [showForm, setShowForm] = useState(false)
const toggleShowForm = () => setShowForm(!showForm)
const [editor, setEditor] = useState<Editor | null>(null)
const { setActiveEditor, activeEditor } = useCommentEditorContext()

const { state, node } = comment
const article = node.__typename === 'Article' ? node : undefined
Expand Down Expand Up @@ -224,7 +228,12 @@ const BaseFooterActions = ({
{...buttonProps}
{...replyButtonProps}
{...replyCustomButtonProps}
onClick={toggleShowForm}
onClick={() => {
if (editor === activeEditor) {
setActiveEditor(null)
}
toggleShowForm()
}}
/>
</Media>
</>
Expand All @@ -237,11 +246,17 @@ const BaseFooterActions = ({
<Spacer size="base" />
<CommentFormBeta
articleId={article?.id}
setEditor={setEditor}
type={'article'}
replyToId={comment.id}
parentId={comment.parentComment?.id || comment.id}
submitCallback={submitCallback}
closeCallback={() => setShowForm(false)}
closeCallback={() => {
if (editor === activeEditor) {
setActiveEditor(null)
}
setShowForm(false)
}}
isInCommentDetail={isInCommentDetail}
defaultContent={defaultContent}
/>
Expand Down
23 changes: 0 additions & 23 deletions src/components/Context/ActiveCommentEditor/index.tsx

This file was deleted.

44 changes: 44 additions & 0 deletions src/components/Context/CommentEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Editor } from '@matters/matters-editor'
import { createContext, ReactNode, useContext, useState } from 'react'

interface CommentEditorContextProps {
activeEditor: Editor | null
fallbackEditor: Editor | null
setActiveEditor: (editor: Editor | null) => void
setFallbackEditor: (editor: Editor | null) => void
getCurrentEditor: () => Editor | null
}

const CommentEditorContext = createContext<CommentEditorContextProps>(
{} as CommentEditorContextProps
)

export const useCommentEditorContext = (): CommentEditorContextProps => {
const context = useContext(CommentEditorContext)
return context
}

export const CommentEditorProvider = ({
children,
}: {
children: ReactNode
}) => {
const [activeEditor, setActiveEditor] = useState<Editor | null>(null)
const [fallbackEditor, setFallbackEditor] = useState<Editor | null>(null)

const getCurrentEditor = () => activeEditor || fallbackEditor

return (
<CommentEditorContext.Provider
value={{
activeEditor,
setActiveEditor,
fallbackEditor,
setFallbackEditor,
getCurrentEditor,
}}
>
{children}
</CommentEditorContext.Provider>
)
}
2 changes: 1 addition & 1 deletion src/components/Context/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from './ActiveCommentEditor'
export * from './CommentDrafts'
export * from './CommentEditor'
export * from './DraftDetailState'
export * from './Features'
export * from './Language'
Expand Down
21 changes: 13 additions & 8 deletions src/components/Editor/Comment/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import {
EditorContent,
useCommentEditor,
} from '@matters/matters-editor'
import { useContext, useEffect } from 'react'
import { useEffect } from 'react'
import { useIntl } from 'react-intl'

import { BYPASS_SCROLL_LOCK, ENBABLE_SCROLL_LOCK } from '~/common/enums'
import { ActiveCommentEditorContext } from '~/components/Context'
import { useCommentEditorContext } from '~/components/Context'

import { makeMentionSuggestion } from '../Article/extensions'
import styles from './styles.module.css'
Expand All @@ -18,19 +18,19 @@ interface Props {
update: (params: { content: string }) => void
placeholder?: string
setEditor?: (editor: Editor | null) => void
syncQuote?: boolean
isFallbackEditor?: boolean
}

const CommentEditor: React.FC<Props> = ({
content,
update,
placeholder,
setEditor,
syncQuote,
isFallbackEditor,
}) => {
const client = useApolloClient()
const intl = useIntl()
const { setEditor: setActiveEditor } = useContext(ActiveCommentEditorContext)
const { setActiveEditor, setFallbackEditor } = useCommentEditorContext()

const editor = useCommentEditor({
placeholder:
Expand Down Expand Up @@ -58,8 +58,8 @@ const CommentEditor: React.FC<Props> = ({

useEffect(() => {
setEditor?.(editor)
if (syncQuote) {
setActiveEditor(editor)
if (isFallbackEditor) {
setFallbackEditor(editor)
}
}, [editor])

Expand All @@ -68,7 +68,12 @@ const CommentEditor: React.FC<Props> = ({
className={styles.commentEditor}
id="editor" // anchor for mention plugin
>
<EditorContent editor={editor} />
<EditorContent
editor={editor}
onFocus={() => {
setActiveEditor(editor)
}}
/>
</div>
)
}
Expand Down
21 changes: 16 additions & 5 deletions src/components/Forms/CommentFormBeta/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
CommentDraftsContext,
SpinnerBlock,
TextIcon,
useCommentEditorContext,
useMutation,
useRoute,
ViewerContext,
Expand All @@ -31,11 +32,12 @@ import styles from './styles.module.css'
export type CommentFormBetaType = 'article'

export interface CommentFormBetaProps {
type: CommentFormBetaType

commentId?: string
replyToId?: string
parentId?: string
articleId?: string
type: CommentFormBetaType
isInCommentDetail?: boolean

defaultContent?: string | null
Expand All @@ -44,7 +46,9 @@ export interface CommentFormBetaProps {

showClear?: boolean
placeholder?: string
syncQuote?: boolean

isFallbackEditor?: boolean
setEditor?: (editor: Editor | null) => void
}

export const CommentFormBeta: React.FC<CommentFormBetaProps> = ({
Expand All @@ -59,15 +63,21 @@ export const CommentFormBeta: React.FC<CommentFormBetaProps> = ({
closeCallback,
showClear,
placeholder,
syncQuote,
isFallbackEditor,
setEditor: propsSetEditor,
}) => {
const intl = useIntl()
const viewer = useContext(ViewerContext)
const { getDraft, updateDraft, removeDraft } =
useContext(CommentDraftsContext)
const { getQuery, routerLang } = useRoute()
const { setActiveEditor } = useCommentEditorContext()
const [editor, localSetEditor] = useState<Editor | null>(null)
const setEditor = (editor: Editor | null) => {
localSetEditor(editor)
propsSetEditor?.(editor)
}
const shortHash = getQuery('shortHash')
const [editor, setEditor] = useState<Editor | null>(null)

// retrieve comment draft
const commentDraftId = `${articleId}-${type}-${commentId || 0}-${
Expand Down Expand Up @@ -172,6 +182,7 @@ export const CommentFormBeta: React.FC<CommentFormBetaProps> = ({
editor.commands.setContent('')
}
removeDraft(commentDraftId)
setActiveEditor(null)
}

const onUpdate = ({ content: newContent }: { content: string }) => {
Expand All @@ -195,7 +206,7 @@ export const CommentFormBeta: React.FC<CommentFormBetaProps> = ({
content={content}
update={onUpdate}
placeholder={placeholder}
syncQuote={syncQuote}
isFallbackEditor={isFallbackEditor}
setEditor={(editor) => {
setEditor(editor)
}}
Expand Down
Loading

0 comments on commit b50eb4f

Please sign in to comment.