firenvim icon indicating copy to clipboard operation
firenvim copied to clipboard

Add draft-js support

Open glacambre opened this issue 5 years ago • 8 comments

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 avatar Aug 01 '20 08:08 glacambre

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 avatar Aug 10 '20 04:08 glacambre

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 avatar Feb 01 '21 07:02 glacambre

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

glacambre avatar Mar 24 '21 05:03 glacambre

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

glacambre avatar Feb 04 '22 05:02 glacambre

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.

glacambre avatar Apr 14 '22 07:04 glacambre