Skip to content

Commit

Permalink
fix: editor render issue #175 #177 #176
Browse files Browse the repository at this point in the history
  • Loading branch information
Blinko committed Nov 25, 2024
1 parent f7e1aee commit 3a51b33
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 51 deletions.
4 changes: 2 additions & 2 deletions src/components/Common/Editor/editorPlugins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const ProcessCodeBlocks = (content: string): string => {

while ((match = codeBlockRegex.exec(content)) !== null) {
const beforeCode = content.slice(lastIndex, match.index);
result += beforeCode.replace(/(<[^>]+>)/gi, '\\$1').replace(/^---$/gm, '\\---').replace(/<>/gm, '\\<>');
result += beforeCode.replace(/(<[^>]+>)/gi, '\\$1').replace(/^[-*_]{3,}$/gm, '\\$&').replace(/<>/gm, '\\<>');

const [_, language, code] = match;
if (!language || !(language in codeBlockLanguages)) {
Expand All @@ -45,7 +45,7 @@ export const ProcessCodeBlocks = (content: string): string => {
}

const afterLastCode = content.slice(lastIndex);
result += afterLastCode.replace(/(<[^>]+>)/gi, '\\$1').replace(/^---$/gm, '\\---').replace(/<>/gm, '\\<>');
result += afterLastCode.replace(/(<[^>]+>)/gi, '\\$1').replace(/^[-*_]{3,}$/gm, '\\$&').replace(/<>/gm, '\\<>');

return result;
};
Expand Down
92 changes: 57 additions & 35 deletions src/components/Common/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { AttachmentsRender } from '../AttachmentRender';

import { ShowCamera } from '../CameraDialog';
import { ShowAudioDialog } from '../AudioDialog';
import { showTagSelectPop } from '../PopoverFloat/tagSelectPop';
import { IsTagSelectVisible, showTagSelectPop } from '../PopoverFloat/tagSelectPop';
import { showAiWriteSuggestions } from '../PopoverFloat/aiWritePop';
import { AiStore } from '@/store/aiStore';
import { Icon } from '@iconify/react';
Expand Down Expand Up @@ -65,6 +65,27 @@ export const HandleFileType = (originFiles: Attachment[]): FileType[] => {
return res
}

export const getEditorElements = () => {
const editorElements = document.querySelectorAll('._contentEditable_uazmk_379') as NodeListOf<HTMLElement>
return editorElements
}


export const handleEditorKeyEvents = () => {
const editorElements = getEditorElements()
editorElements.forEach(element => {
element.addEventListener('keydown', (e) => {
const isTagSelectVisible = IsTagSelectVisible()
if (e.key === 'Enter' && isTagSelectVisible) {
e.preventDefault()
return false
}
}, true)
})
}




const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot, originFiles, mode }: IProps) => {
content = ProcessCodeBlocks(content)
Expand All @@ -89,6 +110,7 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
files: [] as FileType[],
lastRange: null as Range | null,
lastRangeText: '',
lastSelection: null as Selection | null,
updateSendStatus() {
if (store.files?.length == 0 && mdxEditorRef.current?.getMarkdown() == '') {
return setCanSend(false)
Expand All @@ -103,6 +125,7 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
replaceMarkdownTag(text: string, forceFocus = false) {
if (mdxEditorRef.current) {
if (store.lastRange) {
console.log('replaceMarkdownTag', store.lastRangeText)
const currentTextBeforeRange = store.lastRangeText.replace(/&#x20;/g, " ") ?? ''
const currentText = mdxEditorRef.current!.getMarkdown().replace(/\\/g, '').replace(/&#x20;/g, " ")
const tag = currentTextBeforeRange.replace(helper.regex.isEndsWithHashTag, "#" + text + '&#x20;')
Expand Down Expand Up @@ -141,30 +164,32 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
focus(force = false) {
console.log(mdxEditorRef.current)
if (force && store.lastRange) {
onChange?.(mdxEditorRef.current!.getMarkdown())
const editorElement = document.querySelector('._contentEditable_uazmk_379') as HTMLElement
if (editorElement) {
requestAnimationFrame(() => {
const range = document.createRange()
const selection = window.getSelection()
const walker = document.createTreeWalker(
editorElement,
NodeFilter.SHOW_TEXT,
null
)
let lastNode: any = null
while (walker.nextNode()) {
lastNode = walker.currentNode
}
if (lastNode) {
range.setStart(lastNode, lastNode?.length)
range.setEnd(lastNode, lastNode?.length)
selection?.removeAllRanges()
selection?.addRange(range)
editorElement.focus()
}
const editorElements = getEditorElements()
if (editorElements.length > 0) {
editorElements.forEach(editorElement => {
requestAnimationFrame(() => {
const range = document.createRange()
const selection = window.getSelection()
const walker = document.createTreeWalker(
editorElement,
NodeFilter.SHOW_TEXT,
null
)
let lastNode: any = null
while (walker.nextNode()) {
lastNode = walker.currentNode
}
if (lastNode) {
range.setStart(lastNode, lastNode?.length)
range.setEnd(lastNode, lastNode?.length)
selection?.removeAllRanges()
selection?.addRange(range)
editorElement.focus()
}
})
})
}
onChange?.(mdxEditorRef.current!.getMarkdown())
} else {
mdxEditorRef.current!.focus(() => {
onChange?.(mdxEditorRef.current!.getMarkdown())
Expand Down Expand Up @@ -231,16 +256,19 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
handlePopTag() {
const selection = window.getSelection();
if (selection!.rangeCount > 0) {
let lastRange = selection!.getRangeAt(0);
store.lastRange = lastRange
store.lastRangeText = lastRange.endContainer.textContent?.slice(0, lastRange.endOffset) ?? ''
if (!IsTagSelectVisible()) {
let lastRange = selection!.getRangeAt(0);
store.lastRange = lastRange
store.lastRangeText = lastRange.endContainer.textContent?.slice(0, lastRange.endOffset) ?? ''
store.lastSelection = selection
}
const hasHashTagRegex = /#[^\s#]+/g
const endsWithBankRegex = /\s$/g
const currentText = store.lastRange.startContainer.textContent?.slice(0, store.lastRange.endOffset) ?? ''
const currentText = store.lastRange?.startContainer.textContent?.slice(0, store.lastRange?.endOffset) ?? ''
const isEndsWithBank = endsWithBankRegex.test(currentText)
const isEndsWithHashTag = helper.regex.isEndsWithHashTag.test(currentText)
if (currentText == '' || !isEndsWithHashTag) {
setTimeout(() => eventBus.emit('tagselect:hidden'))
setTimeout(() => eventBus.emit('tagselect:hidden'))
return
}
if (isEndsWithHashTag && currentText != '' && !isEndsWithBank) {
Expand Down Expand Up @@ -300,6 +328,7 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
eventBus.on('editor:deleteLastChar', store.deleteLastChar)
eventBus.on('editor:focus', store.focus)
eventBus.on('editor:setMarkdownLoading', store.setMarkdownLoading)
handleEditorKeyEvents()
return () => {
eventBus.off('editor:replace', store.replaceMarkdownTag)
eventBus.off('editor:clear', store.clearMarkdown)
Expand Down Expand Up @@ -333,13 +362,6 @@ const Editor = observer(({ content, onChange, onSend, isSendLoading, bottomSlot,
shadow='none' {...getRootProps()}
className={`p-2 relative border-2 border-border transition-all ${isDragAccept ? 'border-2 border-green-500 border-dashed transition-all' : ''}`}>
<div ref={cardRef}
// onKeyDown={e => {
// if (e.key === 'Enter') {
// if (isPc) {
// e.preventDefault();
// }
// }
// }}
onKeyUp={async event => {
event.preventDefault();
if (event.key === 'Enter' && event.ctrlKey) {
Expand Down
23 changes: 12 additions & 11 deletions src/components/Common/PopoverFloat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const PopoverFloat = observer(({
}: PopoverFloatProps) => {
const isPc = useMediaQuery('(min-width: 768px)')
const popRef: any = useRef(null)

const getPosition = () => {
if (!anchorRect || typeof window === 'undefined') return { top: 0, left: 0 }
let top = anchorRect.bottom || anchorRect.top
Expand All @@ -35,7 +35,7 @@ const PopoverFloat = observer(({
const popWidth = popRef.current?.clientWidth ?? maxWidth
const viewportHeight = window.innerHeight
const viewportWidth = window.innerWidth

if (top + popHeight > viewportHeight) {
top = Math.max(10, anchorRect.top - popHeight)
} else {
Expand All @@ -55,27 +55,28 @@ const PopoverFloat = observer(({

useEffect(() => {
if (!show || !closeOnClickOutside) return

const handleClickOutside = (event: MouseEvent) => {
if (popRef.current && !popRef.current.contains(event.target as Node)) {
onHide()
}
}

document.addEventListener('mousedown', handleClickOutside)
return () => document.removeEventListener('mousedown', handleClickOutside)
}, [show, onHide, closeOnClickOutside])

return (
<motion.div
id='tag-select-popup'
ref={popRef}
animate={show ? 'enter' : 'exit'}
variants={{
enter: {
opacity: 1,
transition: { type: 'spring', bounce: 0.5, duration: 0.4 },
zIndex: 99,
y: 5,
y: 5,
x: 0
},
exit: {
Expand All @@ -94,14 +95,14 @@ const PopoverFloat = observer(({
left: position.left,
zIndex: -99
}}>
<Card
shadow='lg'
radius='md'
style={{
maxHeight: maxHeight + 'px',
<Card
shadow='lg'
radius='md'
style={{
maxHeight: maxHeight + 'px',
maxWidth: maxWidth + 'px',
minWidth: '150px'
}}
}}
className={`p-2 rounded-md overflow-y-scroll overflow-x-hidden`}
>
{children}
Expand Down
11 changes: 8 additions & 3 deletions src/components/Common/PopoverFloat/tagSelectPop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { RootStore } from '@/store';
import { BlinkoStore } from '@/store/blinkoStore';
import { DialogStore } from '@/store/module/Dialog';

export const IsTagSelectVisible = () => {
const tagSelectPopup = document.getElementById('tag-select-popup')
const isTagSelectVisible = tagSelectPopup && window.getComputedStyle(tagSelectPopup).opacity !== '0'
return isTagSelectVisible
}

export const showTagSelectPop = (text: string = '') => {
setTimeout(() => {
const selection = window.getSelection();
Expand Down Expand Up @@ -57,20 +63,19 @@ const TagSelect = observer(() => {
switch (e.key) {
case 'ArrowDown':
e.preventDefault()
e.stopPropagation()
store.selectedIndex = (store.selectedIndex + 1) % store.tagList.length
break
case 'ArrowUp':
e.preventDefault()
e.stopPropagation()
store.selectedIndex = (store.selectedIndex - 1 + store.tagList.length) % store.tagList.length
break
case 'Enter':
e.preventDefault()
e.stopPropagation()
e.preventDefault()
const selectedTag = store.tagList[store.selectedIndex]
if (selectedTag) {
store.hidden()
console.log('selectedTag', selectedTag)
eventBus.emit('editor:replace', selectedTag, true)
}
break
Expand Down

0 comments on commit 3a51b33

Please sign in to comment.