blob: b5ef9d712c3c7f6af04f6329435459bee68151bd [file] [log] [blame]
simon26e79f72022-10-05 22:16:08 -04001/*
2 * Copyright (C) 2022 Savoir-faire Linux Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License as
6 * published by the Free Software Foundation; either version 3 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <https://www.gnu.org/licenses/>.
17 */
simon20076982022-10-11 15:04:13 -040018import { Contact } from './Contact.js';
simond8ca2f22022-10-11 23:30:55 -040019import { PromiseExecutor } from './util.js';
simon06527b02022-10-01 15:01:47 -040020
21export interface ConversationMember {
22 contact: Contact;
23 role?: 'admin' | 'member' | 'invited' | 'banned' | 'left';
24}
25
26type ConversationInfos = Record<string, unknown>;
27
28export type Message = Record<string, string>;
29type ConversationRequest = PromiseExecutor<Message[]>;
30
31type ConversationListeners = Record<
32 string,
33 {
simond8ca2f22022-10-11 23:30:55 -040034 socket: any; // TODO: Improve typing
35 session: any;
simon06527b02022-10-01 15:01:47 -040036 }
37>;
38
simon20076982022-10-11 15:04:13 -040039export class Conversation {
simon06527b02022-10-01 15:01:47 -040040 private readonly id: string | undefined;
41 private readonly accountId: string;
42 private readonly members: ConversationMember[];
simon5e32f742022-10-04 18:03:12 -040043 private messages: Message[];
44 private _infos: ConversationInfos;
45 private _requests: Record<string, ConversationRequest>;
46 private _listeners: ConversationListeners;
simon06527b02022-10-01 15:01:47 -040047
48 constructor(id: string | undefined, accountId: string, members?: ConversationMember[]) {
49 this.id = id;
50 this.accountId = accountId;
51 this.members = members || [];
simon5e32f742022-10-04 18:03:12 -040052
53 this.messages = [];
54 this._infos = {};
55 this._requests = {};
56 this._listeners = {};
simon06527b02022-10-01 15:01:47 -040057 }
58
simon5e32f742022-10-04 18:03:12 -040059 static from(accountId: string, object: any) {
simon06527b02022-10-01 15:01:47 -040060 const conversation = new Conversation(
61 object.id,
62 accountId,
simon5e32f742022-10-04 18:03:12 -040063 object.members.map((member: any) => {
simon06527b02022-10-01 15:01:47 -040064 member.contact = Contact.from(member.contact);
65 return member;
66 })
67 );
68 conversation.messages = object.messages;
idillonae655dd2022-10-14 18:11:02 -040069 conversation.infos = object.infos;
simon06527b02022-10-01 15:01:47 -040070 return conversation;
71 }
72 static fromSingleContact(accountId: string, contact: Contact) {
73 return new Conversation(undefined, accountId, [{ contact }]);
74 }
75
76 getId() {
77 return this.id;
78 }
79
80 getAccountId() {
81 return this.accountId;
82 }
83
84 getDisplayName() {
85 if (this.members.length !== 0) {
86 return this.members[0].contact.getDisplayName();
87 }
88 return this.getDisplayUri();
89 }
90
91 getDisplayNameNoFallback() {
92 if (this.members.length !== 0) {
93 return this.members[0].contact.getDisplayNameNoFallback();
94 }
95 }
96
97 async getObject(params?: {
98 memberFilter: (value: ConversationMember, index: number, array: ConversationMember[]) => boolean;
99 }) {
100 const members = params?.memberFilter ? this.members.filter(params.memberFilter) : this.members;
101 return {
102 id: this.id,
103 messages: this.messages,
104 members: await Promise.all(
105 members.map(async (member) => {
106 //Object.assign({}, member);
107 return {
108 role: member.role,
109 contact: await member.contact.getObject(),
110 };
111 })
112 ),
idillonae655dd2022-10-14 18:11:02 -0400113 infos: this._infos,
simon06527b02022-10-01 15:01:47 -0400114 };
115 }
116
117 getSummary() {
118 return this.getObject();
119 }
120
121 getDisplayUri() {
122 return this.getId() || this.getFirstMember().contact.getUri();
123 }
124
125 getFirstMember() {
126 return this.members[0];
127 }
128
129 getMembers() {
130 return this.members;
131 }
132
133 addMessage(message: Message) {
134 if (this.messages.length === 0) this.messages.push(message);
135 else if (message.id === this.messages[this.messages.length - 1].linearizedParent) {
136 this.messages.push(message);
137 } else if (message.linearizedParent === this.messages[0].id) {
138 this.messages.unshift(message);
139 } else {
140 console.log("Can't insert message " + message.id);
141 }
142 }
143
144 addLoadedMessages(messages: Message[]) {
145 messages.forEach((message) => this.addMessage(message));
146 }
147
148 getMessages() {
149 return this.messages;
150 }
151
idillonae655dd2022-10-14 18:11:02 -0400152 get infos() {
153 return this._infos;
154 }
155
simon06527b02022-10-01 15:01:47 -0400156 set infos(infos: ConversationInfos) {
157 this._infos = infos;
158 }
159
160 get requests(): Record<string, ConversationRequest> {
161 return this._requests;
162 }
163
164 set requests(value: Record<string, ConversationRequest>) {
165 this._requests = value;
166 }
167
168 get listeners(): ConversationListeners {
169 return this._listeners;
170 }
171
172 set listeners(listeners: ConversationListeners) {
173 this._listeners = listeners;
174 }
175}