A message contains either text or media

This commit is contained in:
Franck Royer 2021-10-08 11:29:15 +11:00
parent 2491bba0c6
commit 64abd9dd2e
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 76 additions and 76 deletions

View File

@ -176,14 +176,18 @@ export function useMessenger(chatId: string, chatIdList: string[]) {
const sendMessage = useCallback( const sendMessage = useCallback(
async (messageText: string, image?: Uint8Array) => { async (messageText: string, image?: Uint8Array) => {
const mediaContent = image // TODO: A message can either contain text or media, not both.
const content = image
? { ? {
image, image,
imageType: 1, imageType: 1,
contentType: 1, contentType: 2,
} }
: undefined; : {
await messenger?.sendMessage(messageText, chatId, mediaContent); text: messageText,
contentType: 0,
};
await messenger?.sendMessage(chatId, content);
addNewMessageRaw( addNewMessageRaw(
messenger?.identity.publicKey ?? new Uint8Array(), messenger?.identity.publicKey ?? new Uint8Array(),
messageText, messageText,

View File

@ -1,4 +1,4 @@
import { ChatMessage, MediaContent } from "./chat_message"; import { ChatMessage, Content } from "./chat_message";
import { chatIdToContentTopic } from "./contentTopic"; import { chatIdToContentTopic } from "./contentTopic";
import { createSymKeyFromPassword } from "./encryption"; import { createSymKeyFromPassword } from "./encryption";
@ -24,15 +24,14 @@ export class Chat {
return chatIdToContentTopic(this.id); return chatIdToContentTopic(this.id);
} }
public createMessage(text: string, mediaContent?: MediaContent): ChatMessage { public createMessage(content: Content): ChatMessage {
const { timestamp, clock } = this._nextClockAndTimestamp(); const { timestamp, clock } = this._nextClockAndTimestamp();
const message = ChatMessage.createMessage( const message = ChatMessage.createMessage(
clock, clock,
timestamp, timestamp,
text,
this.id, this.id,
mediaContent content
); );
this._updateClockFromMessage(message); this._updateClockFromMessage(message);

View File

@ -23,13 +23,7 @@ describe("Chat Message", () => {
contentType: ContentType.Image, contentType: ContentType.Image,
}; };
const message = ChatMessage.createMessage( const message = ChatMessage.createMessage(1, 1, "chat-id", imageContent);
1,
1,
"Some text",
"chat-id",
imageContent
);
const buf = message.encode(); const buf = message.encode();
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf);
@ -50,13 +44,7 @@ describe("Chat Message", () => {
contentType: ContentType.Audio, contentType: ContentType.Audio,
}; };
const message = ChatMessage.createMessage( const message = ChatMessage.createMessage(1, 1, "chat-id", audioContent);
1,
1,
"Some text",
"chat-id",
audioContent
);
const buf = message.encode(); const buf = message.encode();
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf);
@ -77,13 +65,7 @@ describe("Chat Message", () => {
contentType: ContentType.Sticker, contentType: ContentType.Sticker,
}; };
const message = ChatMessage.createMessage( const message = ChatMessage.createMessage(1, 1, "chat-id", stickerContent);
1,
1,
"Some text",
"chat-id",
stickerContent
);
const buf = message.encode(); const buf = message.encode();
const dec = ChatMessage.decode(buf); const dec = ChatMessage.decode(buf);

View File

@ -10,14 +10,24 @@ import {
} from "./proto/communities/v1/chat_message"; } from "./proto/communities/v1/chat_message";
import { ImageType, MessageType } from "./proto/communities/v1/enums"; import { ImageType, MessageType } from "./proto/communities/v1/enums";
export type MediaContent = StickerContent | ImageContent | AudioContent; export type Content =
| TextContent
| StickerContent
| ImageContent
| AudioContent;
export enum ContentType { export enum ContentType {
Text,
Sticker, Sticker,
Image, Image,
Audio, Audio,
} }
export interface TextContent {
text: string;
contentType: ContentType.Text;
}
export interface StickerContent { export interface StickerContent {
hash: string; hash: string;
pack: number; pack: number;
@ -37,15 +47,19 @@ export interface AudioContent {
contentType: ContentType.Audio; contentType: ContentType.Audio;
} }
function isSticker(content: MediaContent): content is StickerContent { function isText(content: Content): content is TextContent {
return content.contentType === ContentType.Text;
}
function isSticker(content: Content): content is StickerContent {
return content.contentType === ContentType.Sticker; return content.contentType === ContentType.Sticker;
} }
function isImage(content: MediaContent): content is ImageContent { function isImage(content: Content): content is ImageContent {
return content.contentType === ContentType.Image; return content.contentType === ContentType.Image;
} }
function isAudio(content: MediaContent): content is AudioContent { function isAudio(content: Content): content is AudioContent {
return content.contentType === ContentType.Audio; return content.contentType === ContentType.Audio;
} }
@ -60,44 +74,42 @@ export class ChatMessage {
public static createMessage( public static createMessage(
clock: number, clock: number,
timestamp: number, timestamp: number,
text: string,
chatId: string, chatId: string,
mediaContent?: MediaContent content: Content
): ChatMessage { ): ChatMessage {
let sticker, image, audio; let sticker,
image,
audio,
text = "Upgrade to the latest version to see this media content.";
let contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN; let contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN;
if (mediaContent) { if (isText(content)) {
if (isSticker(mediaContent)) { if (!content.text) throw "Malformed Text Content";
if (!mediaContent.hash || !mediaContent.pack) text = content.text;
throw "Malformed Sticker Content"; contentType = ChatMessage_ContentType.CONTENT_TYPE_TEXT_PLAIN;
sticker = { } else if (isSticker(content)) {
hash: mediaContent.hash, if (!content.hash || !content.pack) throw "Malformed Sticker Content";
pack: mediaContent.pack, sticker = {
}; hash: content.hash,
contentType = ChatMessage_ContentType.CONTENT_TYPE_STICKER; pack: content.pack,
} else if (isImage(mediaContent)) { };
if (!mediaContent.image || !mediaContent.imageType) contentType = ChatMessage_ContentType.CONTENT_TYPE_STICKER;
throw "Malformed Image Content"; } else if (isImage(content)) {
image = { if (!content.image || !content.imageType) throw "Malformed Image Content";
payload: mediaContent.image, image = {
type: mediaContent.imageType, payload: content.image,
}; type: content.imageType,
contentType = ChatMessage_ContentType.CONTENT_TYPE_IMAGE; };
} else if (isAudio(mediaContent)) { contentType = ChatMessage_ContentType.CONTENT_TYPE_IMAGE;
if ( } else if (isAudio(content)) {
!mediaContent.audio || if (!content.audio || !content.audioType || !content.durationMs)
!mediaContent.audioType || throw "Malformed Audio Content";
!mediaContent.durationMs audio = {
) payload: content.audio,
throw "Malformed Audio Content"; type: content.audioType,
audio = { durationMs: content.durationMs,
payload: mediaContent.audio, };
type: mediaContent.audioType, contentType = ChatMessage_ContentType.CONTENT_TYPE_AUDIO;
durationMs: mediaContent.durationMs,
};
contentType = ChatMessage_ContentType.CONTENT_TYPE_AUDIO;
}
} }
const proto = { const proto = {

View File

@ -3,6 +3,7 @@ import debug from "debug";
import { utils } from "js-waku"; import { utils } from "js-waku";
import { ApplicationMetadataMessage } from "./application_metadata_message"; import { ApplicationMetadataMessage } from "./application_metadata_message";
import { ContentType } from "./chat_message";
import { Identity } from "./identity"; import { Identity } from "./identity";
import { Messenger } from "./messenger"; import { Messenger } from "./messenger";
@ -73,7 +74,10 @@ describe("Messenger", () => {
}, testChatId); }, testChatId);
}); });
await messengerAlice.sendMessage(text, testChatId); await messengerAlice.sendMessage(testChatId, {
text,
contentType: ContentType.Text,
});
const receivedMessage = await receivedMessagePromise; const receivedMessage = await receivedMessagePromise;
@ -95,7 +99,10 @@ describe("Messenger", () => {
}, testChatId); }, testChatId);
}); });
await messengerAlice.sendMessage(text, testChatId); await messengerAlice.sendMessage(testChatId, {
text,
contentType: ContentType.Text,
});
const receivedMessage = await receivedMessagePromise; const receivedMessage = await receivedMessagePromise;

View File

@ -4,7 +4,7 @@ import { CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"
import { ApplicationMetadataMessage } from "./application_metadata_message"; import { ApplicationMetadataMessage } from "./application_metadata_message";
import { Chat } from "./chat"; import { Chat } from "./chat";
import { ChatMessage, MediaContent } from "./chat_message"; import { ChatMessage, Content } from "./chat_message";
import { Identity } from "./identity"; import { Identity } from "./identity";
import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message"; import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message";
@ -72,15 +72,11 @@ export class Messenger {
/** /**
* Sends a message on the given chat Id. * Sends a message on the given chat Id.
*/ */
public async sendMessage( public async sendMessage(chatId: string, content: Content): Promise<void> {
text: string,
chatId: string,
mediaContent?: MediaContent
): Promise<void> {
const chat = this.chatsById.get(chatId); const chat = this.chatsById.get(chatId);
if (!chat) throw `Failed to send message, chat not joined: ${chatId}`; if (!chat) throw `Failed to send message, chat not joined: ${chatId}`;
const chatMessage = chat.createMessage(text, mediaContent); const chatMessage = chat.createMessage(content);
const appMetadataMessage = ApplicationMetadataMessage.create( const appMetadataMessage = ApplicationMetadataMessage.create(
chatMessage.encode(), chatMessage.encode(),