diff --git a/assets/chat/js/chat.js b/assets/chat/js/chat.js index a046aa39..b0e669c8 100644 --- a/assets/chat/js/chat.js +++ b/assets/chat/js/chat.js @@ -757,16 +757,15 @@ class Chat { addMessage(message, win = null) { // eslint-disable-next-line no-param-reassign if (win === null) win = this.mainwindow; - const previousMessage = win.getPreviousMessage(message); // Break the current combo if this message is not an emote // We don't need to check what type the current message is, we just know that its a new message, so the combo is invalid. if ( - previousMessage && - previousMessage.type === MessageTypes.EMOTE && - previousMessage.emotecount > 1 + win.lastmessage && + win.lastmessage.type === MessageTypes.EMOTE && + win.lastmessage.emotecount > 1 ) - previousMessage.completeCombo(); + win.lastmessage.completeCombo(); // Populate the tag and mentioned users for this $message. if ( @@ -799,7 +798,7 @@ class Chat { // Populate highlight for this $message if (message.type === MessageTypes.USER) { // check if the last message was from the same user - message.continued = win.isContinued(message, previousMessage); + message.continued = win.isContinued(message); // set highlighted state message.highlighted = this.shouldHighlightMessage(message); } @@ -1143,26 +1142,32 @@ class Chat { const textonly = this.removeSlashCmdFromText(data.data); const usr = this.users.get(data.nick.toLowerCase()); const win = this.mainwindow; + const message = MessageBuilder.message(data.data, usr, data.timestamp); - const previousMessage = win.getPreviousMessage(message); + if (win.containsMessage(message)) return; + const isCombo = this.emoteService.canUserUseEmote(usr, textonly) && - this.removeSlashCmdFromText(previousMessage?.message) === textonly; + this.removeSlashCmdFromText(win.lastmessage?.message) === textonly; - if (isCombo && previousMessage?.type === MessageTypes.EMOTE) { - previousMessage.incEmoteCount(); + if (isCombo && win.lastmessage?.type === MessageTypes.EMOTE) { + win.lastmessage.add(message); if (this.user.equalWatching(usr.watching)) { - previousMessage.ui.classList.toggle('watching-same', true); + win.lastmessage.ui.classList.toggle('watching-same', true); } this.mainwindow.update(); return; } - if (isCombo && previousMessage?.type === MessageTypes.USER) { - win.removeMessage(previousMessage); - const msg = MessageBuilder.emote(textonly, data.timestamp, 2).into(this); + if (isCombo && win.lastmessage?.type === MessageTypes.USER) { + const lastMessage = win.lastmessage; + win.removeLastMessage(); + const msg = MessageBuilder.emote(textonly, lastMessage.timestamp, [ + lastMessage, + message, + ]).into(this); if (this.user.equalWatching(usr.watching)) { msg.ui.classList.add('watching-same'); diff --git a/assets/chat/js/messages/ChatEmoteMessage.js b/assets/chat/js/messages/ChatEmoteMessage.js index 38d5fc4a..37c61a9a 100644 --- a/assets/chat/js/messages/ChatEmoteMessage.js +++ b/assets/chat/js/messages/ChatEmoteMessage.js @@ -27,9 +27,14 @@ function ChatEmoteMessageCount(message) { const ChatEmoteMessageCountThrottle = throttle(63, ChatEmoteMessageCount); export default class ChatEmoteMessage extends ChatMessage { - constructor(emote, timestamp, count = 1) { + messages = []; + + emotecount = 0; + + constructor(emote, timestamp, messages) { super(emote, timestamp, MessageTypes.EMOTE); - this.emotecount = count; + this.messages = messages; + this.emotecount = messages.length; this.emoteFormatter = new EmoteFormatter(); } @@ -62,11 +67,16 @@ export default class ChatEmoteMessage extends ChatMessage { this.ui.append(this.text.get(0), this.combo.get(0)); } - incEmoteCount() { + add(message) { + this.messages.push(message); this.emotecount += 1; ChatEmoteMessageCountThrottle(this); } + containsMessage(message) { + return this.messages.find((msg) => msg.md5 === message.md5); + } + completeCombo() { ChatEmoteMessageCount(this); this.combo.attr('class', `${this.combo.attr('class')} combo-complete`); diff --git a/assets/chat/js/messages/MessageBuilder.js b/assets/chat/js/messages/MessageBuilder.js index 5349d760..93185b5e 100644 --- a/assets/chat/js/messages/MessageBuilder.js +++ b/assets/chat/js/messages/MessageBuilder.js @@ -41,8 +41,8 @@ export default class MessageBuilder { return new ChatUserMessage(message, user, timestamp); } - static emote(emote, timestamp, count = 1) { - return new ChatEmoteMessage(emote, timestamp, count); + static emote(emote, timestamp, messages) { + return new ChatEmoteMessage(emote, timestamp, messages); } static whisper(message, user, target, timestamp = null, id = null) { diff --git a/assets/chat/js/window.js b/assets/chat/js/window.js index 5d1fce4d..b76f7bcf 100644 --- a/assets/chat/js/window.js +++ b/assets/chat/js/window.js @@ -75,55 +75,24 @@ class ChatWindow extends EventEmitter { } addMessage(chat, message) { - // Return if message is already in chat. - if (this.containsMessage(message)) return; - message.ui = message.html(chat); message.afterRender(chat); - // Get index of where the message should be based on timestamp. - const index = this.getMessageIndex(message); - - /** - * If the index of the message is 0 then prepend. - * If it's equal the length of the array then append. - * Otherwise insert at index. - */ - if (index === 0) { - this.lines.prepend(message.ui); - this.messages.unshift(message); - } else if (index === this.messages.length) { - this.lines.append(message.ui); - this.messages.push(message); - this.lastmessage = message; - } else { - this.lines.insertBefore(message.ui, this.messages[index].ui); - this.messages.splice(index, 0, message); - } + this.lines.append(message.ui); + this.messages.push(message); + this.lastmessage = message; this.linecount += 1; this.cleanupThrottle(); } - getMessageIndex(message) { - return ( - this.messages.findLastIndex( - (m) => m.timestamp.valueOf() <= message.timestamp.valueOf(), - ) + 1 - ); - } - - getPreviousMessage(message) { - const index = this.getMessageIndex(message); - if (index === 0) { - return null; - } - - return this.messages[index - 1]; - } - containsMessage(message) { - return this.messages.find((msg) => msg.md5 === message.md5); + return this.messages.find((msg) => { + if (msg.type === MessageTypes.EMOTE) { + return msg.containsMessage(message); + } + return msg.md5 === message.md5; + }); } getlines(sel) { @@ -212,9 +181,9 @@ class ChatWindow extends EventEmitter { } } - removeMessage(message) { - message.remove(); - this.messages = this.messages.filter((m) => m !== message); + removeLastMessage() { + this.lastmessage.remove(); + this.messages = this.messages.filter((m) => m !== this.lastmessage); } /**