Give autocomplete providers the room they're in
Removes the gut-wrenching that RoomView does to jam the user list into the user autocomplete provider.
This commit is contained in:
parent
8800081cb9
commit
4953d4de4d
10 changed files with 107 additions and 97 deletions
|
@ -45,41 +45,56 @@ const PROVIDERS = [
|
|||
EmojiProvider,
|
||||
CommandProvider,
|
||||
DuckDuckGoProvider,
|
||||
].map((completer) => completer.getInstance());
|
||||
];
|
||||
|
||||
// Providers will get rejected if they take longer than this.
|
||||
const PROVIDER_COMPLETION_TIMEOUT = 3000;
|
||||
|
||||
export async function getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
|
||||
/* Note: That this waits for all providers to return is *intentional*
|
||||
otherwise, we run into a condition where new completions are displayed
|
||||
while the user is interacting with the list, which makes it difficult
|
||||
to predict whether an action will actually do what is intended
|
||||
*/
|
||||
const completionsList = await Promise.all(
|
||||
// Array of inspections of promises that might timeout. Instead of allowing a
|
||||
// single timeout to reject the Promise.all, reflect each one and once they've all
|
||||
// settled, filter for the fulfilled ones
|
||||
PROVIDERS.map((provider) => {
|
||||
return provider
|
||||
.getCompletions(query, selection, force)
|
||||
.timeout(PROVIDER_COMPLETION_TIMEOUT)
|
||||
.reflect();
|
||||
}),
|
||||
);
|
||||
export default class Autocompleter {
|
||||
constructor(room) {
|
||||
this.room = room;
|
||||
this.providers = PROVIDERS.map((p) => {
|
||||
return new p(room);
|
||||
});
|
||||
}
|
||||
|
||||
return completionsList.filter(
|
||||
(inspection) => inspection.isFulfilled(),
|
||||
).map((completionsState, i) => {
|
||||
return {
|
||||
completions: completionsState.value(),
|
||||
provider: PROVIDERS[i],
|
||||
destroy() {
|
||||
this.providers.forEach((p) => {
|
||||
p.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
/* the currently matched "command" the completer tried to complete
|
||||
* we pass this through so that Autocomplete can figure out when to
|
||||
* re-show itself once hidden.
|
||||
*/
|
||||
command: PROVIDERS[i].getCurrentCommand(query, selection, force),
|
||||
};
|
||||
});
|
||||
async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
|
||||
/* Note: That this waits for all providers to return is *intentional*
|
||||
otherwise, we run into a condition where new completions are displayed
|
||||
while the user is interacting with the list, which makes it difficult
|
||||
to predict whether an action will actually do what is intended
|
||||
*/
|
||||
const completionsList = await Promise.all(
|
||||
// Array of inspections of promises that might timeout. Instead of allowing a
|
||||
// single timeout to reject the Promise.all, reflect each one and once they've all
|
||||
// settled, filter for the fulfilled ones
|
||||
this.providers.map((provider) => {
|
||||
return provider
|
||||
.getCompletions(query, selection, force)
|
||||
.timeout(PROVIDER_COMPLETION_TIMEOUT)
|
||||
.reflect();
|
||||
}),
|
||||
);
|
||||
|
||||
return completionsList.filter(
|
||||
(inspection) => inspection.isFulfilled(),
|
||||
).map((completionsState, i) => {
|
||||
return {
|
||||
completions: completionsState.value(),
|
||||
provider: this.providers[i],
|
||||
|
||||
/* the currently matched "command" the completer tried to complete
|
||||
* we pass this through so that Autocomplete can figure out when to
|
||||
* re-show itself once hidden.
|
||||
*/
|
||||
command: this.providers[i].getCurrentCommand(query, selection, force),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue