From 5e97bd69825dfa03497cbb6f338596c834c4b2e8 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Mon, 28 Oct 2024 18:18:24 +0100 Subject: [PATCH] Make updateSyncTime apply to synchronously updates completion sources FIX: Don't immediately show synchronously updated completions when there are some sources that still need to return. See https://issues.chromium.org/issues/366491590 --- src/state.ts | 21 +++++++++++++-------- src/view.ts | 10 +++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/state.ts b/src/state.ts index 57be788..1165720 100644 --- a/src/state.ts +++ b/src/state.ts @@ -89,13 +89,14 @@ class CompletionDialog { state: EditorState, id: string, prev: CompletionDialog | null, - conf: Required + conf: Required, + didSetActive: boolean ): CompletionDialog | null { + if (prev && !didSetActive && active.some(s => s.state == State.Pending)) + return prev.setDisabled() let options = sortOptions(active, state) - if (!options.length) { - return prev && active.some(a => a.state == State.Pending) ? - new CompletionDialog(prev.options, prev.attrs, prev.tooltip, prev.timestamp, prev.selected, true) : null - } + if (!options.length) + return prev && active.some(a => a.state == State.Pending) ? prev.setDisabled() : null let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1 if (prev && prev.selected != selected && prev.selected != -1) { let selectedValue = prev.options[prev.selected].completion @@ -115,6 +116,10 @@ class CompletionDialog { return new CompletionDialog(this.options, this.attrs, {...this.tooltip, pos: changes.mapPos(this.tooltip.pos)}, this.timestamp, this.selected, this.disabled) } + + setDisabled() { + return new CompletionDialog(this.options, this.attrs, this.tooltip, this.timestamp, this.selected, true) + } } export class CompletionState { @@ -137,11 +142,11 @@ export class CompletionState { }) if (active.length == this.active.length && active.every((a, i) => a == this.active[i])) active = this.active - let open = this.open + let open = this.open, didSet = tr.effects.some(e => e.is(setActiveEffect)) if (open && tr.docChanged) open = open.map(tr.changes) if (tr.selection || active.some(a => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) || - !sameResults(active, this.active)) - open = CompletionDialog.build(active, state, this.id, open, conf) + !sameResults(active, this.active) || didSet) + open = CompletionDialog.build(active, state, this.id, open, conf, didSet) else if (open && open.disabled && !active.some(a => a.state == State.Pending)) open = null diff --git a/src/view.ts b/src/view.ts index ba62a70..946b842 100644 --- a/src/view.ts +++ b/src/view.ts @@ -126,6 +126,9 @@ export const completionPlugin = ViewPlugin.fromClass(class implements PluginValu if (active.state == State.Pending && !this.running.some(r => r.active.source == active.source)) this.startQuery(active) } + if (this.running.length && cState.open && cState.open.disabled) + this.debounceAccept = setTimeout(() => this.accept(), + this.view.state.facet(completionConfig).updateSyncTime) } startQuery(active: ActiveSource) { @@ -159,7 +162,7 @@ export const completionPlugin = ViewPlugin.fromClass(class implements PluginValu this.debounceAccept = -1 let updated: ActiveSource[] = [] - let conf = this.view.state.facet(completionConfig) + let conf = this.view.state.facet(completionConfig), cState = this.view.state.field(completionState) for (let i = 0; i < this.running.length; i++) { let query = this.running[i] if (query.done === undefined) continue @@ -178,7 +181,7 @@ export const completionPlugin = ViewPlugin.fromClass(class implements PluginValu } } - let current = this.view.state.field(completionState).active.find(a => a.source == query.active.source) + let current = cState.active.find(a => a.source == query.active.source) if (current && current.state == State.Pending) { if (query.done == null) { // Explicitly failed. Should clear the pending status if it @@ -193,7 +196,8 @@ export const completionPlugin = ViewPlugin.fromClass(class implements PluginValu } } - if (updated.length) this.view.dispatch({effects: setActiveEffect.of(updated)}) + if (updated.length || cState.open && cState.open.disabled) + this.view.dispatch({effects: setActiveEffect.of(updated)}) } }, { eventHandlers: {