glacambre / firenvim

Embed Neovim in Chrome, Firefox & others.
GNU General Public License v3.0
4.8k stars 147 forks source link

Add draft-js support #672

Open glacambre opened 4 years ago

glacambre commented 4 years ago

https://www.npmjs.com/package/draft-js

It is highly likely that this would solve issues with Reddit, Twitter, Facebook and many other react websites.

Related issues: https://github.com/glacambre/firenvim/issues/625, https://github.com/glacambre/firenvim/issues/322

glacambre commented 4 years ago

I've been working on this for a week now and I can't get writing to work. The following code is enough to retrieve text:

let elem = document.querySelector(selec) as any;
let editorState : any = undefined;
do {
    const prop = Object.keys(elem).find(k => k.startsWith("__reactInternalInstance"));
    if (elem[prop] === undefined) {
        return elem.innerText;
    }
    // TODO: replace with optional chaining once the build system supports it
    editorState = Object
        .values(((elem[prop] || {}).child || {}).pendingProps || {})
        .find((state: any) => (typeof (state || {}).getCurrentContent) === "function");
    elem = elem.parentElement;
} while (editorState === undefined);
return editorState.getCurrentContent().getPlainText();

But to write, you need to find something that has an onChange method and call it. This works really well when done from the debugger:

// Attempt to change the content of a draftjs element by recursively traversing
// all of its attributes and seeing if they have an `onChange` function.
function recurseChange(list, i, text) {
  // If the end of the list has been reached, abort
  if (i >= list.length)
    return;
  let current_object = list[i];
  // If current_object is not in fact an object, skip to next list element
  if (current_object === undefined || current_object === null)
    return recurseChange(list, i+1, text);
  // Add children of current_object that are not in the list to the list
  Object.values(current_object).forEach(obj => {
    if (!list.includes(obj)) {
      list.push(v);
    }
  })
  if (current_object.onChange !== undefined) {
    try {
      const newContentState = current_object.editorState.getCurrentContent().constructor.createFromText(text);
      const newEditorState = current_object.editorState.constructor.createWithContent(newContentState);
      current_object.onChange(newEditorState);
    } catch (e) {}
  }
  const current_text = document.activeElement.__reactInternalInstance$XXX.child.pendingProps.editorState.getCurrentContent().getPlainText();
  if (current_text === text) {
    throw "Success!";
  }
  return recurseChange(list, i+1, text);
}

But doesn't from the extension. I'd need the help of someone who understands what draftjs does behind the scenes.

glacambre commented 3 years ago

I have something that can reliably get and set the content of draftjs elements here: https://github.com/glacambre/firenvim/compare/draftjs

The problem with that is that draft-js triggers an onChange to overwrite the state we set as soon as the element is focused. So the changes are immediately lost...

glacambre commented 3 years ago

Note to self: Try the document.execCommand("insertText") & paste.

glacambre commented 2 years ago

This sounds intriguing and potentially worth looking into: https://github.com/reactjs/reactjs.org/issues/3896 .

glacambre commented 2 years ago

Draft-js is dead: https://github.com/facebook/draft-js/commit/d327fac6a3af73d4a029893891b7643bd822a5ac

I'll close all draft-js related issues in a couple of years.

jedenastka commented 5 months ago

I think this is still relevant in 2024 at least because of #779. Discord is probably not changing this ever.

glacambre commented 5 months ago

For the record, I won't be working on this myself, ever. As said earlier in this issue I already spent >40 hours trying to figure out a solution and couldn't. Either supporting Draftjs is not possible or I don't have the technical chops it requires.

jedenastka commented 5 months ago

Oh... If you weren't able to figure it out, and you are the one who created the great hack that is this extension, I guess it really is too complex to be feasible.

Maybe I'll work on a Vencord (open source Discord client modification) plugin that replaces draft.js with a regular textbox lol. Having Vim powers in Discord would really be a great thing.