Add composing notification
Change-Id: I2c052c4395a56ba6acf882cea3be4b82e2fde761
diff --git a/server/src/app.ts b/server/src/app.ts
index ff94a59..0e1b055 100644
--- a/server/src/app.ts
+++ b/server/src/app.ts
@@ -32,6 +32,7 @@
import { linkPreviewRouter } from './routers/link-preview-router.js';
import { nameserverRouter } from './routers/nameserver-router.js';
import { setupRouter } from './routers/setup-router.js';
+import { bindChatCallbacks } from './websocket/chat-handler.js';
import { bindWebRtcCallbacks } from './websocket/webrtc-handler.js';
@Service()
@@ -59,6 +60,7 @@
this.app.use('/ns', nameserverRouter);
// Setup WebSocket callbacks
+ bindChatCallbacks();
bindWebRtcCallbacks();
// Setup 404 error handling
diff --git a/server/src/jamid/jami-signal-interfaces.ts b/server/src/jamid/jami-signal-interfaces.ts
index 851239b..188dfaf 100644
--- a/server/src/jamid/jami-signal-interfaces.ts
+++ b/server/src/jamid/jami-signal-interfaces.ts
@@ -133,3 +133,10 @@
conversationId: string;
message: Message;
}
+
+export interface ComposingStatusChanged {
+ accountId: string;
+ conversationId: string;
+ from: string;
+ status: number;
+}
diff --git a/server/src/jamid/jami-signal.ts b/server/src/jamid/jami-signal.ts
index 6a9b15b..15bef48 100644
--- a/server/src/jamid/jami-signal.ts
+++ b/server/src/jamid/jami-signal.ts
@@ -25,6 +25,7 @@
AccountsChanged = 'AccountsChanged',
AccountDetailsChanged = 'AccountDetailsChanged',
RegistrationStateChanged = 'RegistrationStateChanged',
+ ComposingStatusChanged = 'ComposingStatusChanged',
IncomingTrustRequest = 'IncomingTrustRequest',
ContactAdded = 'ContactAdded',
ContactRemoved = 'ContactRemoved',
diff --git a/server/src/jamid/jami-swig.ts b/server/src/jamid/jami-swig.ts
index cd6a95c..07fa2dd 100644
--- a/server/src/jamid/jami-swig.ts
+++ b/server/src/jamid/jami-swig.ts
@@ -123,6 +123,7 @@
sendMessage(accountId: string, conversationId: string, message: string, replyTo: string, flag: number): void;
loadConversationMessages(accountId: string, conversationId: string, fromMessage: string, n: number): number;
+ setIsComposing(accountId: string, conversationId: string, isWriting: boolean): void;
getCallList(accountId: string): StringVect;
getCallDetails(accountId: string, callId: string): StringMap;
diff --git a/server/src/jamid/jamid.ts b/server/src/jamid/jamid.ts
index a868afe..ab4d8a8 100644
--- a/server/src/jamid/jamid.ts
+++ b/server/src/jamid/jamid.ts
@@ -19,6 +19,7 @@
import {
AccountDetails,
+ ComposingStatus,
ContactDetails,
ConversationInfos,
ConversationMessage,
@@ -41,6 +42,7 @@
import {
AccountDetailsChanged,
AccountMessageStatusChanged,
+ ComposingStatusChanged,
ContactAdded,
ContactRemoved,
ConversationLoaded,
@@ -167,6 +169,10 @@
handlers.MessageReceived = (accountId: string, conversationId: string, message: Message) =>
onMessageReceived.next({ accountId, conversationId, message });
+ const onComposingStatusChanged = new Subject<ComposingStatusChanged>();
+ handlers.ComposingStatusChanged = (accountId: string, conversationId: string, from: string, status: number) =>
+ onComposingStatusChanged.next({ accountId, conversationId, from, status });
+
// Expose all signals in an events object to allow other handlers to subscribe after jamiSwig.init()
this.events = {
onAccountsChanged: onAccountsChanged.asObservable(),
@@ -186,6 +192,7 @@
onConversationLoaded: onConversationLoaded.asObservable(),
onConversationMemberEvent: onConversationMemberEvent.asObservable(),
onMessageReceived: onMessageReceived.asObservable(),
+ onComposingStatusChanged: onComposingStatusChanged.asObservable(),
};
this.setupSignalHandlers();
@@ -378,6 +385,10 @@
this.jamiSwig.sendMessage(accountId, conversationId, message, replyTo ?? '', flag ?? 0);
}
+ setIsComposing(accountId: string, conversationId: string, isWriting: boolean) {
+ this.jamiSwig.setIsComposing(accountId, conversationId, isWriting);
+ }
+
getCallIds(accountId: string): string[] {
return stringVectToArray(this.jamiSwig.getCallList(accountId));
}
@@ -503,5 +514,16 @@
};
this.webSocketServer.send(signal.accountId, WebSocketMessageType.ConversationMessage, data);
});
+
+ this.events.onComposingStatusChanged.subscribe((signal) => {
+ log.debug('Received ComposingStatusChanged:', JSON.stringify(signal));
+
+ const data: ComposingStatus = {
+ contactId: signal.from,
+ conversationId: signal.conversationId,
+ isWriting: signal.status === 1,
+ };
+ this.webSocketServer.send(signal.accountId, WebSocketMessageType.OnComposingStatusChanged, data);
+ });
}
}
diff --git a/server/src/websocket/chat-handler.ts b/server/src/websocket/chat-handler.ts
new file mode 100644
index 0000000..161203b
--- /dev/null
+++ b/server/src/websocket/chat-handler.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 Savoir-faire Linux Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+import { ComposingStatus, WebSocketMessageType } from 'jami-web-common';
+import log from 'loglevel';
+import { Container } from 'typedi';
+
+import { Jamid } from '../jamid/jamid.js';
+import { WebSocketServer } from './websocket-server.js';
+
+const jamid = Container.get(Jamid);
+const webSocketServer = Container.get(WebSocketServer);
+
+export function bindChatCallbacks() {
+ webSocketServer.bind(
+ WebSocketMessageType.SetIsComposing,
+ (accountId, { contactId, conversationId, isWriting }: ComposingStatus) => {
+ if (contactId !== undefined) {
+ log.warn('SetIsComposing expects contactId to be undefined');
+ return;
+ }
+
+ jamid.setIsComposing(accountId, conversationId, isWriting);
+ }
+ );
+}