Unable to retrieve current cursor position.
I was implementing @mention feature. I could show the user list when the user types @ but couldn't find a solution to append the user to the current cursor position. Anyone has encountered the same issue or anyone have gone through the same issue?
Hi @injas427, Do you have any solution for this problem?
@anhln1998 Not yet
@injas427 i am also implementing mentions feature, are you still using this lib or have switched to another lib?
@anhln1998 We're still using this lib, but have not implemented mentions feature yet.
@injas427 @anhln1998 still no solution for this case? i am implementing the @mention feature too and i am with the same problem.
@Cannon99 Do you have any solution for this problem? i am implementing the @mention feature, I couldn't find a solution to append the user to the current cursor position.
@sandeepa91 unfortunately not, in the current situation i had to remove my emotions feature, because it's depends exclusively from the curson position. Any solution, i am going to post here, if you find something, please let us know too.
any solution?
Did you guys find any solution? @injas427 @Cannon99
I have not solution yet for this. 🙁
De: may @.> Enviado: sexta-feira, 20 de outubro de 2023 02:03 Para: wxik/react-native-rich-editor @.> Cc: Thiago Furlan @.>; Mention @.> Assunto: Re: [wxik/react-native-rich-editor] Unable to retrieve current cursor position. (Issue #228)
Did you guys find any solution? @injas427https://github.com/injas427 @Cannon99https://github.com/Cannon99
— Reply to this email directly, view it on GitHubhttps://github.com/wxik/react-native-rich-editor/issues/228#issuecomment-1771959474, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARZ2GXFRTGTWRB2YDFF3WFDYAHLWVAVCNFSM5N4VRU5KU5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCNZXGE4TKOJUG42A. You are receiving this because you were mentioned.Message ID: @.***>
@Cannon99 I've implemented recently the mentions feature using this library. It was really complicated and I still feel that this library is in some way "abandoned". I can share a little bit about the ideas I've used to implement it, and I hope I can create a PR or something when I have more time, but the code now is not the best it could be and I don't have much time to create a PR or better understanding this library...
Below is the approach I used to implement mentions (I'll paste some code afterward):
- You'll need to work with javascript vanilla most part of the time to listen to input events. So, you'll have to write scripts and execute them using the
richInputRef?.current?.injectJavascript(script)andrichInputRef?.current?.commandDOM(script)functions. - Start the input listeners on the
editorInitializedCallbackfunction, the listener below will listen to cursor position changes for example:document.addEventListener('selectionchange', () => {}) - You'll need to track the cursor position in the plain input text and also in the inside input HTML text. This is important because you'll need to replace the typed
@typing...with the selected mentioned user later. - Send the cursor position to react native using the
_.sendEvent(type, data)script function. You can listen to these events using the RichEditor componentonMessagecallback function. - With the cursor position available on react native, you are able to save the "@" position to be replaced later and also show your user mention list panel.
Below is some code to at least help you track the cursor position and send it to react-native:
// scripts.ts
export const loadMentionScripts = `
const inputElement = document.querySelector('div.pell-content')
function getRange() {
const selection = window.getSelection()
const range = selection.getRangeAt(0)
return range
}
function getHTMLAndPlainTextFromRange(range) {
const clonedRange = range.cloneRange()
clonedRange.selectNodeContents(inputElement)
clonedRange.setEnd(range.startContainer, range.startOffset)
const tempElement = document.createElement('div')
tempElement.appendChild(clonedRange.cloneContents())
const plainText = clonedRange.toString()
const htmlText = tempElement.innerHTML
return { plainText, htmlText }
}
function findCursorPositionInHtmlString(htmlText, cursorPositionOrigin) {
let insideTag = false
let cursorCharIndex = -1
let loopIndex = 0
while (loopIndex < cursorPositionOrigin) {
cursorCharIndex++
let currentChar = htmlText[cursorCharIndex]
if (currentChar === '<') {
let insideTag = true
while (insideTag) {
cursorCharIndex++
currentChar = htmlText[cursorCharIndex]
const nextChar = htmlText[cursorCharIndex + 1]
if (currentChar === '>' && nextChar !== '<') {
loopIndex-- // Skip the closing tag
insideTag = false
}
}
}
loopIndex++
}
const cursorPosition = cursorCharIndex + 1
return cursorPosition
}
document.addEventListener('selectionchange', () => {
const range = getRange()
const { plainText, htmlText } = getHTMLAndPlainTextFromRange(range)
const cursorPositionPlain = plainText.length
const cursorPositionHtml = findCursorPositionInHtmlString(htmlText, plainText)
_.sendEvent('OnCursorMove', { cursorPositionPlain, cursorPositionHtml })
})
`
// MyRichText.tsx
<RichEditor
ref={richInputRef}
editorInitializedCallback={() => richInputRef?.current?.injectJavascript(loadMentionScripts)}
onMessage={({type: string, data?: any}) => {
if (type === 'OnCursorMove') {
const cursorPositionPlain = data.cursorPositionPlain
const cursorPositionHtml = data.cursorPositionHtml
}
}}
...
/>
There's a lot more to do in terms of replacement and typing handling, but I hope that this ideas help you at least to start with something...
@eduardo-santos-tribia Thanks a lot for share your ideas about this. I think you are on the right path because we have a webview here, so we haven't another way to implement it than to inject some javascript.
If you decided to make a fork or submit a PR about this feature let us know, and one more time thank you for this, it helped me a lot!