From 8f90c177fb540236f8322148a54d34036b8cd528 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Tue, 5 Oct 2021 14:04:12 +1100 Subject: [PATCH 1/3] Specify return types --- packages/status-communities/src/chat.ts | 15 +++++++++++---- packages/status-communities/src/chat_message.ts | 4 ++-- packages/status-communities/src/messenger.ts | 10 +++++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/status-communities/src/chat.ts b/packages/status-communities/src/chat.ts index 20abeb14..e08e3a22 100644 --- a/packages/status-communities/src/chat.ts +++ b/packages/status-communities/src/chat.ts @@ -14,7 +14,7 @@ export class Chat { /** * Create a public chat room. */ - public static async create(id: string) { + public static async create(id: string): Promise { const symKey = await createSymKeyFromPassword(id); return new Chat(id, symKey); @@ -34,7 +34,7 @@ export class Chat { return message; } - public handleNewMessage(message: ChatMessage) { + public handleNewMessage(message: ChatMessage): void { this._updateClockFromMessage(message); } @@ -52,11 +52,18 @@ export class Chat { } private _updateClockFromMessage(message: ChatMessage): void { - if (!this.lastMessage || this.lastMessage.clock <= message.clock) { + if ( + !this.lastMessage || + !this.lastMessage.clock || + (message.clock && this.lastMessage.clock <= message.clock) + ) { this.lastMessage = message; } - if (!this.lastClockValue || this.lastClockValue < message.clock) { + if ( + !this.lastClockValue || + (message.clock && this.lastClockValue < message.clock) + ) { this.lastClockValue = message.clock; } } diff --git a/packages/status-communities/src/chat_message.ts b/packages/status-communities/src/chat_message.ts index 31129b1d..e24d25ac 100644 --- a/packages/status-communities/src/chat_message.ts +++ b/packages/status-communities/src/chat_message.ts @@ -15,7 +15,7 @@ export class ChatMessage { timestamp: number, text: string, chatId: string - ) { + ): ChatMessage { const proto = { clock, // ms? timestamp, //ms? @@ -50,7 +50,7 @@ export class ChatMessage { return proto.ChatMessage.encode(this.proto).finish(); } - public get clock() { + public get clock(): number | undefined { return this.proto.clock; } diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index 68503d9c..d5fe484c 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -28,7 +28,7 @@ export class Messenger { public static async create( identity: Identity, wakuOptions?: WakuCreateOptions - ) { + ): Promise { const _wakuOptions = Object.assign({ bootstrap: true }, wakuOptions); const waku = await Waku.create(_wakuOptions); return new Messenger(identity, waku); @@ -39,7 +39,7 @@ export class Messenger { * * Use `addListener` to get messages received on this chat. */ - public async joinChat(chatId: string) { + public async joinChat(chatId: string): Promise { if (this.chatsById.has(chatId)) throw `Failed to join chat, it is already joined: ${chatId}`; @@ -102,7 +102,7 @@ export class Messenger { public addObserver( observer: (message: ApplicationMetadataMessage) => void, chatId: string - ) { + ): void { // Not sure this is the best design here. Maybe `addObserver` and `joinChat` should be merged. if (!this.chatsById.has(chatId)) @@ -153,7 +153,7 @@ export class Messenger { if (!chat) throw `Failed to retrieve messages, chat is not joined: ${chatId}`; - const _callback = (wakuMessages: WakuMessage[]) => { + const _callback = (wakuMessages: WakuMessage[]): void => { const isDefined = ( msg: ApplicationMetadataMessage | undefined ): msg is ApplicationMetadataMessage => { @@ -187,7 +187,7 @@ export class Messenger { private _handleNewChatMessage( chat: Chat, message: ApplicationMetadataMessage - ) { + ): void { if (!message.payload || !message.type || !message.signature) return; const chatMessage = ChatMessage.decode(message.payload); From db7fa52fa9fecadfde0223cd05a7cfa50773a903 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Wed, 6 Oct 2021 14:10:28 +1100 Subject: [PATCH 2/3] Add getters for all usable fields --- .../status-communities/src/chat_message.ts | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/packages/status-communities/src/chat_message.ts b/packages/status-communities/src/chat_message.ts index e24d25ac..b11447f4 100644 --- a/packages/status-communities/src/chat_message.ts +++ b/packages/status-communities/src/chat_message.ts @@ -1,7 +1,12 @@ import { Reader } from "protobufjs"; import * as proto from "./proto/communities/v1/chat_message"; -import { ChatMessage_ContentType } from "./proto/communities/v1/chat_message"; +import { + AudioMessage, + ChatMessage_ContentType, + ImageMessage, + StickerMessage, +} from "./proto/communities/v1/chat_message"; import { MessageType } from "./proto/communities/v1/enums"; export class ChatMessage { @@ -50,11 +55,80 @@ export class ChatMessage { return proto.ChatMessage.encode(this.proto).finish(); } + /** Lamport timestamp of the chat message */ public get clock(): number | undefined { return this.proto.clock; } - get text(): string | undefined { + /** + * Unix timestamps in milliseconds, currently not used as we use whisper as more reliable, but here + * so that we don't rely on it + */ + public get timestamp(): number | undefined { + return this.proto.timestamp; + } + + /** + * Text of the message + */ + public get text(): string | undefined { return this.proto.text; } + + /** + * Id of the message that we are replying to + */ + public get responseTo(): string | undefined { + return this.proto.responseTo; + } + + /** + * Ens name of the sender + */ + public get ensName(): string | undefined { + return this.proto.ensName; + } + + /** + * Chat id, this field is symmetric for public-chats and private group chats, + * but asymmetric in case of one-to-ones, as the sender will use the chat-id + * of the received, while the receiver will use the chat-id of the sender. + * Probably should be the concatenation of sender-pk & receiver-pk in alphabetical order + */ + public get chatId(): string { + return this.proto.chatId; + } + + /** + * The type of message (public/one-to-one/private-group-chat) + */ + public get messageType(): MessageType | undefined { + return this.proto.messageType; + } + + /** + * The type of the content of the message + */ + public get contentType(): ChatMessage_ContentType | undefined { + return this.proto.contentType; + } + + public get sticker(): StickerMessage | undefined { + return this.proto.sticker; + } + + public get image(): ImageMessage | undefined { + return this.proto.image; + } + + public get audio(): AudioMessage | undefined { + return this.proto.audio; + } + + /** + * Used when sharing a community via a chat message. + */ + public get community(): Uint8Array | undefined { + return this.proto.community; + } } From 7ccc3337579a27962d03add971af4ade1132d7af Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Wed, 6 Oct 2021 14:14:40 +1100 Subject: [PATCH 3/3] Only process message with a clock It may be better to use the timestamp on Waku Message than the Chat Message clock: https://github.com/status-im/dappconnect-chat-sdk/issues/5#issuecomment-935322419 --- packages/react-chat/src/hooks/useMessenger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-chat/src/hooks/useMessenger.ts b/packages/react-chat/src/hooks/useMessenger.ts index f6c17b08..82d4d08a 100644 --- a/packages/react-chat/src/hooks/useMessenger.ts +++ b/packages/react-chat/src/hooks/useMessenger.ts @@ -74,7 +74,7 @@ export function useMessenger(chatId: string, chatIdList: string[]) { const addNewMessage = useCallback( (msg: ApplicationMetadataMessage, id: string) => { - if (msg.signer && msg.chatMessage?.text) { + if (msg.signer && msg.chatMessage?.text && msg.chatMessage.clock) { const content = msg.chatMessage.text; const date = new Date(msg.chatMessage.clock); addNewMessageRaw(msg.signer, content, date, id);