mirror of https://github.com/vector-im/riot-web
Allow tab completing users in brackets (#28460)
* Allow tab completing users in brackets Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Account for range offsets when tab completing to not replace unrelated characters Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/28453/head
parent
d36cfc37e2
commit
ae3ca52bd2
|
@ -37,7 +37,7 @@ const USER_REGEX = /\B@\S*/g;
|
||||||
|
|
||||||
// used when you hit 'tab' - we allow some separator chars at the beginning
|
// used when you hit 'tab' - we allow some separator chars at the beginning
|
||||||
// to allow you to tab-complete /mat into /(matthew)
|
// to allow you to tab-complete /mat into /(matthew)
|
||||||
const FORCED_USER_REGEX = /[^/,:; \t\n]\S*/g;
|
const FORCED_USER_REGEX = /[^/,.():; \t\n]\S*/g;
|
||||||
|
|
||||||
export default class UserProvider extends AutocompleteProvider {
|
export default class UserProvider extends AutocompleteProvider {
|
||||||
public matcher: QueryMatcher<RoomMember>;
|
public matcher: QueryMatcher<RoomMember>;
|
||||||
|
|
|
@ -10,11 +10,12 @@ import { KeyboardEvent } from "react";
|
||||||
|
|
||||||
import { Part, CommandPartCreator, PartCreator } from "./parts";
|
import { Part, CommandPartCreator, PartCreator } from "./parts";
|
||||||
import DocumentPosition from "./position";
|
import DocumentPosition from "./position";
|
||||||
import { ICompletion } from "../autocomplete/Autocompleter";
|
import { ICompletion, ISelectionRange } from "../autocomplete/Autocompleter";
|
||||||
import Autocomplete from "../components/views/rooms/Autocomplete";
|
import Autocomplete from "../components/views/rooms/Autocomplete";
|
||||||
|
|
||||||
export interface ICallback {
|
export interface ICallback {
|
||||||
replaceParts?: Part[];
|
replaceParts?: Part[];
|
||||||
|
range?: ISelectionRange;
|
||||||
close?: boolean;
|
close?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ export default class AutocompleteWrapperModel {
|
||||||
this.updateCallback({
|
this.updateCallback({
|
||||||
replaceParts: this.partForCompletion(completion),
|
replaceParts: this.partForCompletion(completion),
|
||||||
close: true,
|
close: true,
|
||||||
|
range: completion.range,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,14 +250,24 @@ export default class EditorModel {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
private onAutoComplete = ({ replaceParts, close }: ICallback): void => {
|
private onAutoComplete = ({ replaceParts, close, range }: ICallback): void => {
|
||||||
let pos: DocumentPosition | undefined;
|
let pos: DocumentPosition | undefined;
|
||||||
if (replaceParts) {
|
if (replaceParts) {
|
||||||
const autoCompletePartIdx = this.autoCompletePartIdx || 0;
|
const autoCompletePartIdx = this.autoCompletePartIdx || 0;
|
||||||
this._parts.splice(autoCompletePartIdx, this.autoCompletePartCount, ...replaceParts);
|
|
||||||
|
this.replaceRange(
|
||||||
|
new DocumentPosition(autoCompletePartIdx, range?.start ?? 0),
|
||||||
|
new DocumentPosition(
|
||||||
|
autoCompletePartIdx + this.autoCompletePartCount - 1,
|
||||||
|
range?.end ?? this.parts[autoCompletePartIdx + this.autoCompletePartCount - 1].text.length,
|
||||||
|
),
|
||||||
|
replaceParts,
|
||||||
|
);
|
||||||
|
|
||||||
this.autoCompletePartCount = replaceParts.length;
|
this.autoCompletePartCount = replaceParts.length;
|
||||||
const lastPart = replaceParts[replaceParts.length - 1];
|
const lastPart = replaceParts[replaceParts.length - 1];
|
||||||
const lastPartIndex = autoCompletePartIdx + replaceParts.length - 1;
|
// `replaceRange` merges adjacent parts so we need to find it in the new parts list
|
||||||
|
const lastPartIndex = this.parts.indexOf(lastPart);
|
||||||
pos = new DocumentPosition(lastPartIndex, lastPart.text.length);
|
pos = new DocumentPosition(lastPartIndex, lastPart.text.length);
|
||||||
}
|
}
|
||||||
if (close) {
|
if (close) {
|
||||||
|
|
Loading…
Reference in New Issue