Hello,
I have a Compartment extension with async value. Here is what the code looks like
const myComp = new Compartment();
async resultDOM(state: EditorState, isMob: boolean) {
const resultWidgets: Range<Decoration>[] = [];
const results = await this.getResult(state);
results.forEach((res: Results, index: number) => {
const deco = Decoration.widget({
widget: new ResultWidget(res),
side: 1,
block: isMob,
});
const { to } = state.doc.line(index + 1);
resultWidgets.push(deco.range(to));
});
return Decoration.set(resultWidgets);
}
const resultPlugin = StateField.define({
async create(state: EditorState) {
return await resultDOM(state, isMobile);
},
async update(_, tr) {
return await resultDOM(tr.state, isMobile);
},
provide: (f) => {
EditorView.decorations.from(f); // ERROR: see below
},
});
const extensions = [ ... , myComp.of(resultPlugin), ...]
TS2345: Argument of type ‘StateField<Promise>’ is not assignable to parameter of type ‘StateField<DecorationSet | ((view: EditorView) => DecorationSet)>’. Type ‘Promise’ is not assignable to type ‘DecorationSet | ((view: EditorView) => DecorationSet)’
I can’t wrap my head around how to let provide the extension with await.
I have updated the code as below
const resultPlugin = StateField.define({
create(state: EditorState) {
return Decoration.none;
},
async update(_, tr) { // ERROR below
return await resultDOM(tr.state, isMobileBind);
},
provide: (f) => {
return EditorView.decorations.from(f);
},
});
TS2322: Type ‘(_: DecorationSet, tr: Transaction) => Promise’ is not assignable to type ‘(value: DecorationSet, transaction: Transaction) => DecorationSet’. Type ‘Promise’ is missing the following properties from type ‘RangeSet’: size, update, map, between, iter
So mainly the update that is updating the decorations (which contains array of widgets) but this update is happening async.
I am trying to figure out how to dispatch the changes in the decorations. Something like this
update(_, tr) {
return resultDOM(tr.state, isMobileBind).then(() => {
// update view again ?
});
I got this working based on the example provided here -
My code now looks like this -
const resultPlugin = StateField.define({
create() {
return Decoration.none;
},
update(value, tr) {
for (let effect of tr.effects) {
if (effect.is(stateEffect)) {
value = effect.value?.decorations;
}
}
return value;
},
provide(f) {
return EditorView.decorations.from(f);
},
});
let stateEffect = StateEffect.define<{ decorations: DecorationSet }>({});
const viewPlugin = ViewPlugin.define(() => {
return {
update(update) {
if (update.state.doc.toString() === update.startState.doc.toString())
return;
resultDOM(update.state, false).then((deco) => {
update.view.dispatch({
effects: stateEffect.of({
decorations: deco,
}),
});
});
},
};
});
const extensions = [ ... , viewPlugin,resultPlugin, ...]