diff --git a/addon/services/chat.js b/addon/services/chat.js index d9040f5..4f82157 100644 --- a/addon/services/chat.js +++ b/addon/services/chat.js @@ -3,6 +3,7 @@ import Evented from '@ember/object/evented'; import { tracked } from '@glimmer/tracking'; import { isArray } from '@ember/array'; import { task } from 'ember-concurrency'; +import isModel from '../utils/is-model'; export default class ChatService extends Service.extend(Evented) { @service store; @@ -28,8 +29,8 @@ export default class ChatService extends Service.extend(Evented) { } createChatChannel(name) { - const chatChannel = this.store.createRecord('chat-channel', { name }); - return chatChannel.save().finally(() => { + const chatChannelRecord = this.store.createRecord('chat-channel', { name }); + return chatChannelRecord.save().finally(() => { this.trigger('chat.created', chatChannelRecord); }); } @@ -53,13 +54,13 @@ export default class ChatService extends Service.extend(Evented) { user_uuid: userRecord.id, }); return chatParticipant.save().finally(() => { - this.trigger('chat.added_participant', chatChannelRecord, chatParticipant); + this.trigger('chat.added_participant', chatParticipant, chatChannelRecord); }); } - removeParticipant(chatParticipant) { + removeParticipant(chatChannelRecord, chatParticipant) { return chatParticipant.destroyRecord().finally(() => { - this.trigger('chat.removed_participant', chatChannelRecord, chatParticipant); + this.trigger('chat.removed_participant', chatParticipant, chatChannelRecord); }); } @@ -69,11 +70,17 @@ export default class ChatService extends Service.extend(Evented) { sender_uuid: senderRecord.id, content: messageContent, }); - await chatMessage.save().finally(() => { - this.trigger('chat.message_created', chatMessage, chatChannelRecord); - }); - chatChannelRecord.messages.pushObject(chatMessage); - await this.loadMessages.perform(chatChannelRecord); + await chatMessage + .save() + .then((chatMessage) => { + if (!this.messageExistInChat(chatChannelRecord, chatMessage)) { + chatChannelRecord.messages.pushObject(chatMessage); + } + return chatMessage; + }) + .finally(() => { + this.trigger('chat.message_created', chatMessage, chatChannelRecord); + }); } deleteMessage(chatMessageRecord) { @@ -82,6 +89,19 @@ export default class ChatService extends Service.extend(Evented) { }); } + insertMessageFromSocket(chatChannelRecord, data) { + const normalizedChatMessage = this.store.normalize('chat-message', data); + const chatMessageRecord = this.store.push(normalizedChatMessage); + if (this.messageExistInChat(chatChannelRecord, chatMessageRecord)) { + return; + } + chatChannelRecord.messages.pushObject(chatMessageRecord); + } + + messageExistInChat(chatChannelRecord, chatMessageRecord) { + return chatChannelRecord.messages.find((_) => _.id === chatMessageRecord.id) !== undefined; + } + @task *loadMessages(chatChannelRecord) { const messages = yield this.store.query('chat-message', { chat_channel_uuid: chatChannelRecord.id }); chatChannelRecord.set('messages', messages); diff --git a/addon/services/socket.js b/addon/services/socket.js index 0feed69..0e700b7 100644 --- a/addon/services/socket.js +++ b/addon/services/socket.js @@ -1,6 +1,7 @@ import Service from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { isBlank } from '@ember/utils'; +import { later } from '@ember/runloop'; import toBoolean from '../utils/to-boolean'; import config from 'ember-get-config'; @@ -29,22 +30,28 @@ export default class SocketService extends Service { } async listen(channelId, callback) { - const channel = this.socket.subscribe(channelId); - - // Track channel - this.channels.pushObject(channel); - - // Listen to channel for events - await channel.listener('subscribe').once(); - - // Listen for channel subscription - (async () => { - for await (let output of channel) { - if (typeof callback === 'function') { - callback(output); - } - } - })(); + later( + this, + async () => { + const channel = this.socket.subscribe(channelId); + + // Track channel + this.channels.pushObject(channel); + + // Listen to channel for events + await channel.listener('subscribe').once(); + + // Listen for channel subscription + (async () => { + for await (let output of channel) { + if (typeof callback === 'function') { + callback(output); + } + } + })(); + }, + 300 + ); } closeChannels() {