2022-02-23 15:49:00 +01:00
|
|
|
import { idToContentTopic } from './contentTopic'
|
|
|
|
import { createSymKeyFromPassword } from './encryption'
|
2022-02-24 22:58:50 +01:00
|
|
|
import { ChatMessage } from './wire/chat_message'
|
|
|
|
|
|
|
|
import type { Content } from './wire/chat_message'
|
|
|
|
import type { CommunityChat } from './wire/community_chat'
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-09-23 15:42:15 +10:00
|
|
|
/**
|
|
|
|
* Represent a chat room. Only public chats are currently supported.
|
|
|
|
*/
|
2021-09-14 12:50:33 +10:00
|
|
|
export class Chat {
|
2022-02-23 15:49:00 +01:00
|
|
|
private lastClockValue?: number
|
|
|
|
private lastMessage?: ChatMessage
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-10-19 14:17:51 +11:00
|
|
|
private constructor(
|
|
|
|
public id: string,
|
|
|
|
public symKey: Uint8Array,
|
|
|
|
public communityChat?: CommunityChat
|
|
|
|
) {}
|
2021-09-23 15:42:15 +10:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a public chat room.
|
2021-10-06 14:51:45 +11:00
|
|
|
* [[Community.instantiateChat]] MUST be used for chats belonging to a community.
|
2021-09-23 15:42:15 +10:00
|
|
|
*/
|
2021-10-19 14:17:51 +11:00
|
|
|
public static async create(
|
|
|
|
id: string,
|
|
|
|
communityChat?: CommunityChat
|
|
|
|
): Promise<Chat> {
|
2022-02-23 15:49:00 +01:00
|
|
|
const symKey = await createSymKeyFromPassword(id)
|
2021-09-23 15:42:15 +10:00
|
|
|
|
2022-02-23 15:49:00 +01:00
|
|
|
return new Chat(id, symKey, communityChat)
|
2021-09-14 13:49:42 +10:00
|
|
|
}
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-09-14 15:16:40 +10:00
|
|
|
public get contentTopic(): string {
|
2022-02-23 15:49:00 +01:00
|
|
|
return idToContentTopic(this.id)
|
2021-09-14 15:16:40 +10:00
|
|
|
}
|
|
|
|
|
2021-12-06 23:31:53 +01:00
|
|
|
public createMessage(content: Content, responseTo?: string): ChatMessage {
|
2022-02-23 15:49:00 +01:00
|
|
|
const { timestamp, clock } = this._nextClockAndTimestamp()
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-10-07 14:21:49 +11:00
|
|
|
const message = ChatMessage.createMessage(
|
|
|
|
clock,
|
|
|
|
timestamp,
|
|
|
|
this.id,
|
2021-12-06 23:31:53 +01:00
|
|
|
content,
|
|
|
|
responseTo
|
2022-02-23 15:49:00 +01:00
|
|
|
)
|
2021-09-22 15:05:36 +10:00
|
|
|
|
2022-02-23 15:49:00 +01:00
|
|
|
this._updateClockFromMessage(message)
|
2021-09-22 15:05:36 +10:00
|
|
|
|
2022-02-23 15:49:00 +01:00
|
|
|
return message
|
2021-09-14 13:49:42 +10:00
|
|
|
}
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-10-05 14:04:12 +11:00
|
|
|
public handleNewMessage(message: ChatMessage): void {
|
2022-02-23 15:49:00 +01:00
|
|
|
this._updateClockFromMessage(message)
|
2021-09-14 15:16:40 +10:00
|
|
|
}
|
|
|
|
|
2021-09-22 15:05:36 +10:00
|
|
|
private _nextClockAndTimestamp(): { clock: number; timestamp: number } {
|
2022-02-23 15:49:00 +01:00
|
|
|
let clock = this.lastClockValue
|
|
|
|
const timestamp = Date.now()
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-09-14 13:49:42 +10:00
|
|
|
if (!clock || clock < timestamp) {
|
2022-02-23 15:49:00 +01:00
|
|
|
clock = timestamp
|
2021-09-14 13:49:42 +10:00
|
|
|
} else {
|
2022-02-23 15:49:00 +01:00
|
|
|
clock += 1
|
2021-09-14 13:49:42 +10:00
|
|
|
}
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2022-02-23 15:49:00 +01:00
|
|
|
return { clock, timestamp }
|
2021-09-14 13:49:42 +10:00
|
|
|
}
|
2021-09-14 12:50:33 +10:00
|
|
|
|
2021-09-23 14:33:09 +10:00
|
|
|
private _updateClockFromMessage(message: ChatMessage): void {
|
2021-10-05 14:04:12 +11:00
|
|
|
if (
|
|
|
|
!this.lastMessage ||
|
|
|
|
!this.lastMessage.clock ||
|
|
|
|
(message.clock && this.lastMessage.clock <= message.clock)
|
|
|
|
) {
|
2022-02-23 15:49:00 +01:00
|
|
|
this.lastMessage = message
|
2021-09-14 12:50:33 +10:00
|
|
|
}
|
|
|
|
|
2021-10-05 14:04:12 +11:00
|
|
|
if (
|
|
|
|
!this.lastClockValue ||
|
|
|
|
(message.clock && this.lastClockValue < message.clock)
|
|
|
|
) {
|
2022-02-23 15:49:00 +01:00
|
|
|
this.lastClockValue = message.clock
|
2021-09-14 12:50:33 +10:00
|
|
|
}
|
2021-09-14 13:49:42 +10:00
|
|
|
}
|
2021-09-14 12:50:33 +10:00
|
|
|
}
|