2021-06-25 18:14:40 +02:00
|
|
|
import { HtmlUtils } from "./HtmlUtils";
|
|
|
|
import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
|
|
|
|
import { connectionManager } from "../Connexion/ConnectionManager";
|
|
|
|
import { GameConnexionTypes } from "../Url/UrlManager";
|
|
|
|
import { iframeListener } from "../Api/IframeListener";
|
|
|
|
import { showReportScreenStore } from "../Stores/ShowReportScreenStore";
|
2020-11-22 12:40:03 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
export type SendMessageCallback = (message: string) => void;
|
2020-10-25 21:59:14 +01:00
|
|
|
|
|
|
|
export class DiscussionManager {
|
|
|
|
private mainContainer: HTMLDivElement;
|
|
|
|
|
|
|
|
private divDiscuss?: HTMLDivElement;
|
|
|
|
private divParticipants?: HTMLDivElement;
|
|
|
|
private nbpParticipants?: HTMLParagraphElement;
|
|
|
|
private divMessages?: HTMLParagraphElement;
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
private participants: Map<number | string, HTMLDivElement> = new Map<number | string, HTMLDivElement>();
|
2020-10-25 21:59:14 +01:00
|
|
|
|
|
|
|
private activeDiscussion: boolean = false;
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
private sendMessageCallBack: Map<number | string, SendMessageCallback> = new Map<
|
|
|
|
number | string,
|
|
|
|
SendMessageCallback
|
|
|
|
>();
|
2020-10-25 21:59:14 +01:00
|
|
|
|
2020-11-10 12:38:32 +01:00
|
|
|
private userInputManager?: UserInputManager;
|
|
|
|
|
2020-12-04 11:30:35 +01:00
|
|
|
constructor() {
|
2021-06-25 18:14:40 +02:00
|
|
|
this.mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>("main-container");
|
|
|
|
this.createDiscussPart(""); //todo: why do we always use empty string?
|
2021-03-04 19:00:00 +01:00
|
|
|
|
|
|
|
iframeListener.chatStream.subscribe((chatEvent) => {
|
|
|
|
this.addMessage(chatEvent.author, chatEvent.message, false);
|
|
|
|
this.showDiscussion();
|
|
|
|
});
|
2021-06-25 18:14:40 +02:00
|
|
|
this.onSendMessageCallback("iframe_listener", (message) => {
|
2021-03-06 15:26:07 +01:00
|
|
|
iframeListener.sendUserInputChat(message);
|
2021-06-25 18:14:40 +02:00
|
|
|
});
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private createDiscussPart(name: string) {
|
2021-06-25 18:14:40 +02:00
|
|
|
this.divDiscuss = document.createElement("div");
|
|
|
|
this.divDiscuss.classList.add("discussion");
|
2020-10-25 21:59:14 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const buttonCloseDiscussion: HTMLButtonElement = document.createElement("button");
|
|
|
|
buttonCloseDiscussion.classList.add("close-btn");
|
2020-10-25 21:59:14 +01:00
|
|
|
buttonCloseDiscussion.innerHTML = `<img src="resources/logos/close.svg"/>`;
|
2021-06-25 18:14:40 +02:00
|
|
|
buttonCloseDiscussion.addEventListener("click", () => {
|
2020-11-10 12:38:32 +01:00
|
|
|
this.hideDiscussion();
|
2020-10-25 21:59:14 +01:00
|
|
|
});
|
|
|
|
this.divDiscuss.appendChild(buttonCloseDiscussion);
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const myName: HTMLParagraphElement = document.createElement("p");
|
2020-10-25 21:59:14 +01:00
|
|
|
myName.innerText = name.toUpperCase();
|
2021-06-25 18:14:40 +02:00
|
|
|
this.nbpParticipants = document.createElement("p");
|
|
|
|
this.nbpParticipants.innerText = "PARTICIPANTS (1)";
|
2020-10-25 21:59:14 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
this.divParticipants = document.createElement("div");
|
|
|
|
this.divParticipants.classList.add("participants");
|
2020-10-25 21:59:14 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
this.divMessages = document.createElement("div");
|
|
|
|
this.divMessages.classList.add("messages");
|
|
|
|
this.divMessages.innerHTML = "<h2>Local messages</h2>";
|
2020-10-25 21:59:14 +01:00
|
|
|
|
|
|
|
this.divDiscuss.appendChild(myName);
|
|
|
|
this.divDiscuss.appendChild(this.nbpParticipants);
|
|
|
|
this.divDiscuss.appendChild(this.divParticipants);
|
|
|
|
this.divDiscuss.appendChild(this.divMessages);
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const sendDivMessage: HTMLDivElement = document.createElement("div");
|
|
|
|
sendDivMessage.classList.add("send-message");
|
|
|
|
const inputMessage: HTMLInputElement = document.createElement("input");
|
2021-01-06 13:36:18 +01:00
|
|
|
inputMessage.onfocus = () => {
|
2021-06-25 18:14:40 +02:00
|
|
|
if (this.userInputManager) {
|
2021-03-22 16:10:21 +01:00
|
|
|
this.userInputManager.disableControls();
|
2021-01-06 13:36:18 +01:00
|
|
|
}
|
2021-06-25 18:14:40 +02:00
|
|
|
};
|
2021-01-06 13:36:18 +01:00
|
|
|
inputMessage.onblur = () => {
|
2021-06-25 18:14:40 +02:00
|
|
|
if (this.userInputManager) {
|
2021-03-22 16:10:21 +01:00
|
|
|
this.userInputManager.restoreControls();
|
2021-01-06 13:36:18 +01:00
|
|
|
}
|
2021-06-25 18:14:40 +02:00
|
|
|
};
|
2020-10-25 21:59:14 +01:00
|
|
|
inputMessage.type = "text";
|
2021-06-25 18:14:40 +02:00
|
|
|
inputMessage.addEventListener("keyup", (event: KeyboardEvent) => {
|
|
|
|
if (event.key === "Enter") {
|
2020-10-25 21:59:14 +01:00
|
|
|
event.preventDefault();
|
2021-06-25 18:14:40 +02:00
|
|
|
if (inputMessage.value === null || inputMessage.value === "" || inputMessage.value === undefined) {
|
2020-11-10 12:38:32 +01:00
|
|
|
return;
|
|
|
|
}
|
2020-10-25 21:59:14 +01:00
|
|
|
this.addMessage(name, inputMessage.value, true);
|
2021-06-25 18:14:40 +02:00
|
|
|
for (const callback of this.sendMessageCallBack.values()) {
|
2020-10-25 21:59:14 +01:00
|
|
|
callback(inputMessage.value);
|
|
|
|
}
|
|
|
|
inputMessage.value = "";
|
|
|
|
}
|
|
|
|
});
|
|
|
|
sendDivMessage.appendChild(inputMessage);
|
|
|
|
this.divDiscuss.appendChild(sendDivMessage);
|
|
|
|
|
|
|
|
//append in main container
|
|
|
|
this.mainContainer.appendChild(this.divDiscuss);
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
this.addParticipant("me", "Moi", undefined, true);
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
2020-10-27 20:18:25 +01:00
|
|
|
public addParticipant(
|
2021-06-25 18:14:40 +02:00
|
|
|
userId: number | "me",
|
|
|
|
name: string | undefined,
|
|
|
|
img?: string | undefined,
|
|
|
|
isMe: boolean = false
|
2020-10-27 20:18:25 +01:00
|
|
|
) {
|
2021-06-25 18:14:40 +02:00
|
|
|
const divParticipant: HTMLDivElement = document.createElement("div");
|
|
|
|
divParticipant.classList.add("participant");
|
2020-10-25 21:59:14 +01:00
|
|
|
divParticipant.id = `participant-${userId}`;
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const divImgParticipant: HTMLImageElement = document.createElement("img");
|
|
|
|
divImgParticipant.src = "resources/logos/boy.svg";
|
2020-10-25 21:59:14 +01:00
|
|
|
if (img !== undefined) {
|
|
|
|
divImgParticipant.src = img;
|
|
|
|
}
|
2021-06-25 18:14:40 +02:00
|
|
|
const divPParticipant: HTMLParagraphElement = document.createElement("p");
|
|
|
|
if (!name) {
|
|
|
|
name = "Anonymous";
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
divPParticipant.innerText = name;
|
|
|
|
|
|
|
|
divParticipant.appendChild(divImgParticipant);
|
|
|
|
divParticipant.appendChild(divPParticipant);
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
if (
|
|
|
|
!isMe &&
|
|
|
|
connectionManager.getConnexionType &&
|
|
|
|
connectionManager.getConnexionType !== GameConnexionTypes.anonymous &&
|
|
|
|
userId !== "me"
|
2020-11-22 12:40:03 +01:00
|
|
|
) {
|
2021-06-25 18:14:40 +02:00
|
|
|
const reportBanUserAction: HTMLButtonElement = document.createElement("button");
|
|
|
|
reportBanUserAction.classList.add("report-btn");
|
|
|
|
reportBanUserAction.innerText = "Report";
|
|
|
|
reportBanUserAction.addEventListener("click", () => {
|
|
|
|
showReportScreenStore.set({ userId: userId, userName: name ? name : "" });
|
2020-10-25 21:59:14 +01:00
|
|
|
});
|
|
|
|
divParticipant.appendChild(reportBanUserAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.divParticipants?.appendChild(divParticipant);
|
2020-11-04 13:07:38 +01:00
|
|
|
|
2020-10-25 21:59:14 +01:00
|
|
|
this.participants.set(userId, divParticipant);
|
|
|
|
|
|
|
|
this.updateParticipant(this.participants.size);
|
|
|
|
}
|
|
|
|
|
|
|
|
public updateParticipant(nb: number) {
|
|
|
|
if (!this.nbpParticipants) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.nbpParticipants.innerText = `PARTICIPANTS (${nb})`;
|
|
|
|
}
|
|
|
|
|
|
|
|
public addMessage(name: string, message: string, isMe: boolean = false) {
|
2021-06-25 18:14:40 +02:00
|
|
|
const divMessage: HTMLDivElement = document.createElement("div");
|
|
|
|
divMessage.classList.add("message");
|
|
|
|
if (isMe) {
|
|
|
|
divMessage.classList.add("me");
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const pMessage: HTMLParagraphElement = document.createElement("p");
|
2020-10-25 21:59:14 +01:00
|
|
|
const date = new Date();
|
2021-06-25 18:14:40 +02:00
|
|
|
if (isMe) {
|
|
|
|
name = "Me";
|
2021-06-07 10:42:08 +02:00
|
|
|
} else {
|
|
|
|
name = HtmlUtils.escapeHtml(name);
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
pMessage.innerHTML = `<span style="font-weight: bold">${name}</span>
|
|
|
|
<span style="color:#bac2cc;display:inline-block;font-size:12px;">
|
|
|
|
${date.getHours()}:${date.getMinutes()}
|
|
|
|
</span>`;
|
|
|
|
divMessage.appendChild(pMessage);
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
const userMessage: HTMLParagraphElement = document.createElement("p");
|
2021-01-22 15:01:10 +01:00
|
|
|
userMessage.innerHTML = HtmlUtils.urlify(message);
|
2021-06-25 18:14:40 +02:00
|
|
|
userMessage.classList.add("body");
|
2020-10-25 21:59:14 +01:00
|
|
|
divMessage.appendChild(userMessage);
|
|
|
|
this.divMessages?.appendChild(divMessage);
|
2021-01-06 17:08:13 +01:00
|
|
|
|
|
|
|
//automatic scroll when there are new message
|
|
|
|
setTimeout(() => {
|
|
|
|
this.divMessages?.scroll({
|
|
|
|
top: this.divMessages?.scrollTop + divMessage.getBoundingClientRect().y,
|
2021-06-25 18:14:40 +02:00
|
|
|
behavior: "smooth",
|
2021-01-06 17:08:13 +01:00
|
|
|
});
|
|
|
|
}, 200);
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
public removeParticipant(userId: number | string) {
|
2020-10-25 21:59:14 +01:00
|
|
|
const element = this.participants.get(userId);
|
2021-06-25 18:14:40 +02:00
|
|
|
if (element) {
|
2020-10-25 21:59:14 +01:00
|
|
|
element.remove();
|
2020-11-04 13:07:38 +01:00
|
|
|
this.participants.delete(userId);
|
|
|
|
}
|
|
|
|
//if all participant leave, hide discussion button
|
|
|
|
|
2020-10-26 14:13:51 +01:00
|
|
|
this.sendMessageCallBack.delete(userId);
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
public onSendMessageCallback(userId: string | number, callback: SendMessageCallback): void {
|
2020-10-26 14:13:51 +01:00
|
|
|
this.sendMessageCallBack.set(userId, callback);
|
2020-10-25 21:59:14 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
get activatedDiscussion() {
|
2020-10-27 20:46:53 +01:00
|
|
|
return this.activeDiscussion;
|
|
|
|
}
|
2020-11-04 13:07:38 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
private showDiscussion() {
|
2020-11-10 12:38:32 +01:00
|
|
|
this.activeDiscussion = true;
|
2021-06-25 18:14:40 +02:00
|
|
|
this.divDiscuss?.classList.add("active");
|
2020-11-10 12:38:32 +01:00
|
|
|
}
|
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
private hideDiscussion() {
|
2020-11-10 12:38:32 +01:00
|
|
|
this.activeDiscussion = false;
|
2021-06-25 18:14:40 +02:00
|
|
|
this.divDiscuss?.classList.remove("active");
|
2020-11-10 12:38:32 +01:00
|
|
|
}
|
2021-01-21 10:16:08 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
public setUserInputManager(userInputManager: UserInputManager) {
|
2020-11-10 12:38:32 +01:00
|
|
|
this.userInputManager = userInputManager;
|
|
|
|
}
|
2020-11-17 16:46:46 +01:00
|
|
|
|
2021-06-25 18:14:40 +02:00
|
|
|
public showDiscussionPart() {
|
2020-11-17 16:46:46 +01:00
|
|
|
this.showDiscussion();
|
|
|
|
}
|
2020-12-04 11:30:35 +01:00
|
|
|
}
|
|
|
|
|
2021-01-21 10:16:08 +01:00
|
|
|
export const discussionManager = new DiscussionManager();
|