This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/plugins/chat/assets/javascripts/discourse/components/direct-message-creator.js
Joffrey JAFFEUX 66130dc8c1
REFACTOR: handles every chat resource as an URL (#18961)
- Note this is also tweaking the UI a little bit as we are now using links/buttons in the header as needed
- It disables the find ideal channel in drawer mode, if loading `/chat` in drawer mode it will either reopen at the last position or just stay on index
2022-11-11 06:39:15 +01:00

317 lines
7.6 KiB
JavaScript

import { caretPosition } from "discourse/lib/utilities";
import { isEmpty } from "@ember/utils";
import Component from "@ember/component";
import { action } from "@ember/object";
import discourseDebounce from "discourse-common/lib/debounce";
import discourseComputed, { bind } from "discourse-common/utils/decorators";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { inject as service } from "@ember/service";
import { schedule } from "@ember/runloop";
import { gt, not } from "@ember/object/computed";
import { createDirectMessageChannelDraft } from "discourse/plugins/chat/discourse/models/chat-channel";
export default Component.extend({
tagName: "",
users: null,
selectedUsers: null,
term: null,
isFiltering: false,
isFilterFocused: false,
highlightedSelectedUser: null,
focusedUser: null,
chat: service(),
router: service(),
chatStateManager: service(),
isLoading: false,
onSwitchChannel: null,
init() {
this._super(...arguments);
this.set("users", []);
this.set("selectedUsers", []);
this.set("channel", createDirectMessageChannelDraft());
},
didInsertElement() {
this._super(...arguments);
this.filterUsernames();
},
didReceiveAttrs() {
this._super(...arguments);
this.set("term", null);
this.focusFilter();
if (!this.hasSelection) {
this.filterUsernames();
}
},
hasSelection: gt("channel.chatable.users.length", 0),
@discourseComputed
chatProgressBarContainer() {
return document.querySelector("#chat-progress-bar-container");
},
@bind
filterUsernames(term = null) {
this.set("isFiltering", true);
this.chat
.searchPossibleDirectMessageUsers({
term,
limit: 6,
exclude: this.channel.chatable?.users?.mapBy("username") || [],
lastSeenUsers: isEmpty(term) ? true : false,
})
.then((r) => {
if (this.isDestroying || this.isDestroyed) {
return;
}
if (r !== "__CANCELLED") {
this.set("users", r.users || []);
this.set("focusedUser", this.users.firstObject);
}
})
.finally(() => {
if (this.isDestroying || this.isDestroyed) {
return;
}
this.set("isFiltering", false);
});
},
shouldRenderResults: not("isFiltering"),
@action
selectUser(user) {
this.selectedUsers.pushObject(user);
this.users.removeObject(user);
this.set("users", []);
this.set("focusedUser", null);
this.set("highlightedSelectedUser", null);
this.set("term", null);
this.focusFilter();
this.onChangeSelectedUsers?.(this.selectedUsers);
},
@action
deselectUser(user) {
this.users.removeObject(user);
this.selectedUsers.removeObject(user);
this.set("focusedUser", this.users.firstObject);
this.set("highlightedSelectedUser", null);
this.set("term", null);
if (isEmpty(this.selectedUsers)) {
this.filterUsernames();
}
this.focusFilter();
this.onChangeSelectedUsers?.(this.selectedUsers);
},
@action
focusFilter() {
this.set("isFilterFocused", true);
schedule("afterRender", () => {
document.querySelector(".filter-usernames")?.focus();
});
},
@action
onFilterInput(term) {
this.set("term", term);
this.set("users", []);
if (!term?.length) {
return;
}
this.set("isFiltering", true);
discourseDebounce(this, this.filterUsernames, term, INPUT_DELAY);
},
@action
handleUserKeyUp(user, event) {
if (event.key === "Enter") {
event.stopPropagation();
event.preventDefault();
this.selectUser(user);
}
},
@action
onFilterInputFocusOut() {
this.set("isFilterFocused", false);
this.set("highlightedSelectedUser", null);
},
@action
leaveChannel() {
this.router.transitionTo("chat.index");
},
@action
handleFilterKeyUp(event) {
if (event.key === "Tab") {
const enabledComposer = document.querySelector(".chat-composer-input");
if (enabledComposer && !enabledComposer.disabled) {
event.preventDefault();
event.stopPropagation();
enabledComposer.focus();
}
}
if (
(event.key === "Enter" || event.key === "Backspace") &&
this.highlightedSelectedUser
) {
event.preventDefault();
event.stopPropagation();
this.deselectUser(this.highlightedSelectedUser);
return;
}
if (event.key === "Backspace" && isEmpty(this.term) && this.hasSelection) {
event.preventDefault();
event.stopPropagation();
this.deselectUser(this.channel.chatable.users.lastObject);
}
if (event.key === "Enter" && this.focusedUser) {
event.preventDefault();
event.stopPropagation();
this.selectUser(this.focusedUser);
}
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
this._handleVerticalArrowKeys(event);
}
if (event.key === "Escape" && this.highlightedSelectedUser) {
this.set("highlightedSelectedUser", null);
}
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
this._handleHorizontalArrowKeys(event);
}
},
_firstSelectWithArrows(event) {
if (event.key === "ArrowRight") {
return;
}
if (event.key === "ArrowLeft") {
const position = caretPosition(
document.querySelector(".filter-usernames")
);
if (position > 0) {
return;
} else {
event.preventDefault();
event.stopPropagation();
this.set(
"highlightedSelectedUser",
this.channel.chatable.users.lastObject
);
}
}
},
_changeSelectionWithArrows(event) {
if (event.key === "ArrowRight") {
if (
this.highlightedSelectedUser === this.channel.chatable.users.lastObject
) {
this.set("highlightedSelectedUser", null);
return;
}
if (this.channel.chatable.users.length === 1) {
return;
}
this._highlightNextSelectedUser(event.key === "ArrowLeft" ? -1 : 1);
}
if (event.key === "ArrowLeft") {
if (this.channel.chatable.users.length === 1) {
return;
}
this._highlightNextSelectedUser(event.key === "ArrowLeft" ? -1 : 1);
}
},
_highlightNextSelectedUser(modifier) {
const newIndex =
this.channel.chatable.users.indexOf(this.highlightedSelectedUser) +
modifier;
if (this.channel.chatable.users.objectAt(newIndex)) {
this.set(
"highlightedSelectedUser",
this.channel.chatable.users.objectAt(newIndex)
);
} else {
this.set(
"highlightedSelectedUser",
event.key === "ArrowLeft"
? this.channel.chatable.users.lastObject
: this.channel.chatable.users.firstObject
);
}
},
_handleHorizontalArrowKeys(event) {
const position = caretPosition(document.querySelector(".filter-usernames"));
if (position > 0) {
return;
}
if (!this.highlightedSelectedUser) {
this._firstSelectWithArrows(event);
} else {
this._changeSelectionWithArrows(event);
}
},
_handleVerticalArrowKeys(event) {
if (isEmpty(this.users)) {
return;
}
event.preventDefault();
event.stopPropagation();
if (!this.focusedUser) {
this.set("focusedUser", this.users.firstObject);
return;
}
const modifier = event.key === "ArrowUp" ? -1 : 1;
const newIndex = this.users.indexOf(this.focusedUser) + modifier;
if (this.users.objectAt(newIndex)) {
this.set("focusedUser", this.users.objectAt(newIndex));
} else {
this.set(
"focusedUser",
event.key === "ArrowUp" ? this.users.lastObject : this.users.firstObject
);
}
},
});