Merge pull request #3361 from matrix-org/bwindels/autocomplete-colon

New composer: append colon to completed user pill when at start of message
This commit is contained in:
Bruno Windels 2019-08-30 16:02:58 +00:00 committed by GitHub
commit ec0d048cf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 23 deletions

View file

@ -27,8 +27,7 @@ export default class AutocompleteWrapperModel {
onEscape(e) { onEscape(e) {
this._getAutocompleterComponent().onEscape(e); this._getAutocompleterComponent().onEscape(e);
this._updateCallback({ this._updateCallback({
replacePart: this._partCreator.plain(this._queryPart.text), replaceParts: [this._partCreator.plain(this._queryPart.text)],
caretOffset: this._queryOffset,
close: true, close: true,
}); });
} }
@ -66,30 +65,29 @@ export default class AutocompleteWrapperModel {
this._getAutocompleterComponent().moveSelection(+1); this._getAutocompleterComponent().moveSelection(+1);
} }
onPartUpdate(part, offset) { onPartUpdate(part, pos) {
// cache the typed value and caret here // cache the typed value and caret here
// so we can restore it in onComponentSelectionChange when the value is undefined (meaning it should be the typed text) // so we can restore it in onComponentSelectionChange when the value is undefined (meaning it should be the typed text)
this._queryPart = part; this._queryPart = part;
this._queryOffset = offset; this._partIndex = pos.index;
return this._updateQuery(part.text); return this._updateQuery(part.text);
} }
onComponentSelectionChange(completion) { onComponentSelectionChange(completion) {
if (!completion) { if (!completion) {
this._updateCallback({ this._updateCallback({
replacePart: this._queryPart, replaceParts: [this._queryPart],
caretOffset: this._queryOffset,
}); });
} else { } else {
this._updateCallback({ this._updateCallback({
replacePart: this._partForCompletion(completion), replaceParts: this._partForCompletion(completion),
}); });
} }
} }
onComponentConfirm(completion) { onComponentConfirm(completion) {
this._updateCallback({ this._updateCallback({
replacePart: this._partForCompletion(completion), replaceParts: this._partForCompletion(completion),
close: true, close: true,
}); });
} }
@ -101,16 +99,18 @@ export default class AutocompleteWrapperModel {
switch (firstChr) { switch (firstChr) {
case "@": { case "@": {
if (completionId === "@room") { if (completionId === "@room") {
return this._partCreator.atRoomPill(completionId); return [this._partCreator.atRoomPill(completionId)];
} else { } else {
return this._partCreator.userPill(text, completionId); const pill = this._partCreator.userPill(text, completionId);
const postfix = this._partCreator.plain(this._partIndex === 0 ? ": " : " ");
return [pill, postfix];
} }
} }
case "#": case "#":
return this._partCreator.roomPill(completionId); return [this._partCreator.roomPill(completionId)];
// used for emoji and command completion replacement // used for emoji and command completion replacement
default: default:
return this._partCreator.plain(text); return [this._partCreator.plain(text)];
} }
} }
} }

View file

@ -47,6 +47,7 @@ export default class EditorModel {
this._activePartIdx = null; this._activePartIdx = null;
this._autoComplete = null; this._autoComplete = null;
this._autoCompletePartIdx = null; this._autoCompletePartIdx = null;
this._autoCompletePartCount = 0;
this._transformCallback = null; this._transformCallback = null;
this.setUpdateCallback(updateCallback); this.setUpdateCallback(updateCallback);
} }
@ -218,34 +219,36 @@ export default class EditorModel {
// make sure that react picks up the difference between both acs // make sure that react picks up the difference between both acs
this._autoComplete = ac; this._autoComplete = ac;
this._autoCompletePartIdx = index; this._autoCompletePartIdx = index;
this._autoCompletePartCount = 1;
} }
} }
} }
// not _autoComplete, only there if active part is autocomplete part // not _autoComplete, only there if active part is autocomplete part
if (this.autoComplete) { if (this.autoComplete) {
return this.autoComplete.onPartUpdate(part, pos.offset); return this.autoComplete.onPartUpdate(part, pos);
} }
} else { } else {
this._activePartIdx = null; this._activePartIdx = null;
this._autoComplete = null; this._autoComplete = null;
this._autoCompletePartIdx = null; this._autoCompletePartIdx = null;
this._autoCompletePartCount = 0;
} }
return Promise.resolve(); return Promise.resolve();
} }
_onAutoComplete = ({replacePart, caretOffset, close}) => { _onAutoComplete = ({replaceParts, close}) => {
let pos; let pos;
if (replacePart) { if (replaceParts) {
this._replacePart(this._autoCompletePartIdx, replacePart); this._parts.splice(this._autoCompletePartIdx, this._autoCompletePartCount, ...replaceParts);
const index = this._autoCompletePartIdx; this._autoCompletePartCount = replaceParts.length;
if (caretOffset === undefined) { const lastPart = replaceParts[replaceParts.length - 1];
caretOffset = replacePart.text.length; const lastPartIndex = this._autoCompletePartIdx + replaceParts.length - 1;
} pos = new DocumentPosition(lastPartIndex, lastPart.text.length);
pos = new DocumentPosition(index, caretOffset);
} }
if (close) { if (close) {
this._autoComplete = null; this._autoComplete = null;
this._autoCompletePartIdx = null; this._autoCompletePartIdx = null;
this._autoCompletePartCount = 0;
} }
// rerender even if editor contents didn't change // rerender even if editor contents didn't change
// to make sure the MessageEditor checks // to make sure the MessageEditor checks

View file

@ -40,12 +40,12 @@ class MockAutoComplete {
} else { } else {
pill = this._partCreator.roomPill(match.resourceId); pill = this._partCreator.roomPill(match.resourceId);
} }
this._updateCallback({replacePart: pill, close}); this._updateCallback({replaceParts: [pill], close});
} }
} }
// called by EditorModel when typing into pill-candidate part // called by EditorModel when typing into pill-candidate part
onPartUpdate(part, offset) { onPartUpdate(part, pos) {
this._part = part; this._part = part;
} }
} }