UNPKG

@gameon/web

Version:
201 lines (166 loc) 5.09 kB
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; @customElement('on-chat-group-client') export class OnChatGroupClient extends LitElement { static override styles = css` :host { display: block; } on-chat-window { height: 100%; } `; @property({ attribute: 'auth-token' }) authToken?: string; @property({ attribute: 'room-id' }) roomId?: string; @property({ attribute: 'user-id' }) userId?: string; @property({ attribute: 'app-id' }) appId?: string; @state() private get speakers(): Speaker[] { if (this.sbChannel?.members) { return this.sbChannel.members.map((member) => ({ avatarUrl: member.profileUrl, id: member.userId, username: member.nickname, })); } return []; } @query('on-chat-window') private onChatWindowEl!: OnChatWindow; @state() 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}" @on-chat-input-submit="${this.handleChatInputSubmit}" ></on-chat-window> `; } }