partey_workadventure/front/src/Stores/ChatStore.ts
David Négrier 5479aea9f0 Preventing a loop from occuring with chat API
When sending a chat message from the Scripting API, the chat message is no longer sent back to the chat listener.
This makes it easier to avoid infinite loops.
2022-04-26 14:57:04 +02:00

136 lines
4.5 KiB
TypeScript

import { writable } from "svelte/store";
import { playersStore } from "./PlayersStore";
import type { PlayerInterface } from "../Phaser/Game/PlayerInterface";
import { iframeListener } from "../Api/IframeListener";
import { Subject } from "rxjs";
export const chatVisibilityStore = writable(false);
export const chatInputFocusStore = writable(false);
const _newChatMessageSubject = new Subject<string>();
export const newChatMessageSubject = _newChatMessageSubject.asObservable();
export enum ChatMessageTypes {
text = 1,
me,
userIncoming,
userOutcoming,
}
export interface ChatMessage {
type: ChatMessageTypes;
date: Date;
author?: PlayerInterface;
targets?: PlayerInterface[];
text?: string[];
}
function getAuthor(authorId: number): PlayerInterface {
const author = playersStore.getPlayerById(authorId);
if (!author) {
throw new Error("Could not find data for author " + authorId);
}
return author;
}
function createChatMessagesStore() {
const { subscribe, update } = writable<ChatMessage[]>([]);
return {
subscribe,
addIncomingUser(authorId: number) {
update((list) => {
const lastMessage = list[list.length - 1];
if (lastMessage && lastMessage.type === ChatMessageTypes.userIncoming && lastMessage.targets) {
lastMessage.targets.push(getAuthor(authorId));
} else {
list.push({
type: ChatMessageTypes.userIncoming,
targets: [getAuthor(authorId)],
date: new Date(),
});
}
return list;
});
},
addOutcomingUser(authorId: number) {
update((list) => {
const lastMessage = list[list.length - 1];
if (lastMessage && lastMessage.type === ChatMessageTypes.userOutcoming && lastMessage.targets) {
lastMessage.targets.push(getAuthor(authorId));
} else {
list.push({
type: ChatMessageTypes.userOutcoming,
targets: [getAuthor(authorId)],
date: new Date(),
});
}
return list;
});
},
addPersonnalMessage(text: string) {
iframeListener.sendUserInputChat(text);
_newChatMessageSubject.next(text);
update((list) => {
const lastMessage = list[list.length - 1];
if (lastMessage && lastMessage.type === ChatMessageTypes.me && lastMessage.text) {
lastMessage.text.push(text);
} else {
list.push({
type: ChatMessageTypes.me,
text: [text],
date: new Date(),
});
}
return list;
});
},
/**
* @param origin The iframe that originated this message (if triggered from the Scripting API), or undefined otherwise.
*/
addExternalMessage(authorId: number, text: string, origin?: Window) {
update((list) => {
const lastMessage = list[list.length - 1];
if (
lastMessage &&
lastMessage.type === ChatMessageTypes.text &&
lastMessage.text &&
lastMessage?.author?.userId === authorId
) {
lastMessage.text.push(text);
} else {
list.push({
type: ChatMessageTypes.text,
text: [text],
author: getAuthor(authorId),
date: new Date(),
});
}
iframeListener.sendUserInputChat(text, origin);
return list;
});
chatVisibilityStore.set(true);
},
};
}
export const chatMessagesStore = createChatMessagesStore();
function createChatSubMenuVisibilityStore() {
const { subscribe, update } = writable<string>("");
return {
subscribe,
openSubMenu(playerName: string, index: number) {
const id = playerName + index;
update((oldValue) => {
return oldValue === id ? "" : id;
});
},
};
}
export const chatSubMenuVisibilityStore = createChatSubMenuVisibilityStore();