So my question is related to this one about Async Decoration.
It basically boils down to how to perform an async operation in a plugin. Right now I’m after just getting a simple fetch to work, but eventually I want to implement Web Sockets.
I’m using tiptap
and have followed the linting example. Here is my boiled down version.
const properNouns = /\b(jim|oreo|jupiter)\b/gi;
const lint = doc => {
let result = [];
doc.descendants((node, pos) => {
if (node.isText) {
let m;
while ((m = properNouns.exec(node.text)))
result.push({
from: pos + m.index,
to: pos + m.index + m[0].length,
type: "proper-noun"
});
}
});
return result;
};
const lintDeco = doc => {
let decos = [];
lint(doc).forEach(({ from, to, type }) => {
decos.push(Decoration.inline(from, to, { class: type }));
});
return DecorationSet.create(doc, decos);
};
export default class ProperNounPlugin extends Extension {
get name() {
return "proper_noun_plugin";
}
get plugins() {
return [
new Plugin({
state: {
init(_, { doc }) {
return lintDeco(doc);
},
apply(transaction, value) {
return transaction.docChanged ? lintDeco(transaction.doc) : value;
}
},
props: {
decorations(state) {
return this.getState(state);
}
}
})
];
}
}
What I’ve gathered from other questions, the docs and examples is that I need the view to dispatch an action. In the other question linked, I think you need to do this in the plugin’s view.update
:
Plugin({
state: { ... },
view: () => ({
update: debounce((view, prevState) => {
// emulate API request
setTimeout(() => {
const response = true; // emulate response from API
view.dispatch(view.state.tr.setMeta("response", response));
}, 200);
}, 500)
})
});
From there, the state
's apply function will no longer just check if the doc has changed but if there’s metadata on the transaction:
Plugin({
state: {
apply(tr, value) {
if (tr.docChanged && tr.getMeta("response")) return lintDeco(tr.doc);
return value;
}
}
});
However, I still can’t get this to work for me. tr.docChanged
will return true
when tr.getMeta("response")
is returning undefined
and vice versa – so lintDeco is never getting called. What am I missing?
Also, what are the conditions I need to check in the view.update
method to know when the doc has been changed. Right now, debounced requests will fire constantly even though no changes have occurred to the document.
Any help is appreciated!