@gameon/web
Version:
Chat clients for web
201 lines (166 loc) • 5.09 kB
text/typescript
import SendbirdChat, { BaseChannel } from '@sendbird/chat';
import {
GroupChannel,
GroupChannelHandler,
GroupChannelModule,
SendbirdGroupChat,
} from '@sendbird/chat/groupChannel';
import { BaseMessage, UserMessage } from '@sendbird/chat/message';
import { css, html, LitElement, PropertyValues } from 'lit';
import { customElement, property, query, state } from 'lit/decorators.js';
import { Content, Message, Speaker } from '@gameon/on-ui-components/types';
import { InputSubmitEventDetails } from '@gameon/on-ui-components/chat/input';
import { OnChatWindow } from '@gameon/on-ui-components/chat/window';
import '@gameon/on-ui-components/chat/window';
const CHANNEL_HANDLER_KEY = 'default-handler';
const DEFAULT_MESSAGE_LIMIT = 50;
export class OnChatGroupClient extends LitElement {
static override styles = css`
:host {
display: block;
}
on-chat-window {
height: 100%;
}
`;
authToken?: string;
roomId?: string;
userId?: string;
appId?: string;
private get speakers(): Speaker[] {
if (this.sbChannel?.members) {
return this.sbChannel.members.map((member) => ({
avatarUrl: member.profileUrl,
id: member.userId,
username: member.nickname,
}));
}
return [];
}
private onChatWindowEl!: OnChatWindow;
private messages: Message[] = [];
private sbClient?: SendbirdGroupChat;
private sbChannel?: GroupChannel;
override disconnectedCallback(): void {
super.disconnectedCallback();
this.disconnectFromSendbird();
}
override updated(changedProperties: PropertyValues): void {
if (changedProperties.has('appId')) {
this.initializeSendBirdClient();
}
if (
changedProperties.has('authToken') ||
changedProperties.has('roomId') ||
changedProperties.has('userId') ||
changedProperties.has('appId')
) {
this.connectToSendbird();
}
}
private initializeSendBirdClient(): void {
if (this.appId) {
this.sbClient = SendbirdChat.init({
appId: this.appId,
localCacheEnabled: true,
modules: [new GroupChannelModule()],
}) as SendbirdGroupChat;
}
}
private async connectToSendbird() {
if (!this.sbClient) {
return;
}
this.sbChannel = undefined;
this.messages = [];
if (this.userId) {
await this.sbClient.connect(this.userId, this.authToken);
if (this.roomId) {
this.sbChannel = await this.sbClient.groupChannel.getChannel(
this.roomId
);
this.messages = await this.fetchPastMessages(this.sbChannel);
const channelHandler = new GroupChannelHandler();
channelHandler.onMessageReceived =
this.handleMessageReceived.bind(this);
this.sbClient.groupChannel.addGroupChannelHandler(
CHANNEL_HANDLER_KEY,
channelHandler
);
}
}
}
private async disconnectFromSendbird() {
if (!this.sbClient) {
return;
}
await this.sbClient.disconnect();
}
private async fetchPastMessages(channel: GroupChannel) {
const messageListQuery = channel.createPreviousMessageListQuery({
limit: DEFAULT_MESSAGE_LIMIT,
});
const messages = await messageListQuery.load();
const userMessages = messages.filter((message) =>
message.isUserMessage()
) as UserMessage[];
const result = userMessages.map((message) => ({
timestamp: message.createdAt,
speakerId: message.sender ? message.sender.userId : '',
contents: [
{
text: message.message,
},
],
messageId: message.messageId,
}));
return result;
}
private sendMessage(content: Content) {
if (this.sbChannel) {
if (content.text) {
this.sbChannel
.sendUserMessage({ message: content.text })
.onSucceeded((message) => {
if (this.sbChannel) {
this.handleMessageReceived(this.sbChannel, message);
}
});
}
}
}
private handleMessageReceived(_: BaseChannel, message: BaseMessage) {
if (message.isUserMessage()) {
this.messages = [
...this.messages,
{
contents: [{ text: message.message }],
speakerId: message.sender.userId,
timestamp: message.createdAt,
},
];
}
}
private handleChatInputSubmit(e: CustomEvent<InputSubmitEventDetails>) {
this.sendMessage({ text: e.detail.value });
this.onChatWindowEl.inputValue = '';
}
override render() {
return html`
<on-chat-window
.conversationMessages="${this.messages}"
.conversationPrimarySpeakerId="${this.userId ?? ''}"
.conversationSpeakers="${this.speakers}"
-chat-input-submit="${this.handleChatInputSubmit}"
></on-chat-window>
`;
}
}