From 3a5191917aa7a0763cbe8f3fc59a756149a9be24 Mon Sep 17 00:00:00 2001 From: Speng Reb Date: Thu, 24 Jul 2025 13:20:34 +0200 Subject: [PATCH] Support mp4 emotes --- www/js/util.js | 72 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 11 deletions(-) diff --git a/www/js/util.js b/www/js/util.js index f2ab21a7..07cbc9f0 100644 --- a/www/js/util.js +++ b/www/js/util.js @@ -2704,7 +2704,8 @@ function execEmotes(msg) { } CHANNEL.emotes.forEach(function (e) { - msg = msg.replace(e.regex, '$1' + emoteToImg(e).outerHTML); + var el = e.image.endsWith('.mp4') ? emoteToVideo(e) : emoteToImg(e); + msg = msg.replace(e.regex, '$1' + el.outerHTML); }); return msg; @@ -2712,16 +2713,20 @@ function execEmotes(msg) { function execEmotesEfficient(msg) { CHANNEL.badEmotes.forEach(function (e) { - msg = msg.replace(e.regex, '$1' + emoteToImg(e).outerHTML); + var el = e.image.endsWith('.mp4') ? emoteToVideo(e) : emoteToImg(e); + msg = msg.replace(e.regex, '$1' + el.outerHTML); }); + msg = msg.replace(/[^\s]+/g, function (m) { if (CHANNEL.emoteMap.hasOwnProperty(m)) { var e = CHANNEL.emoteMap[m]; - return emoteToImg(e).outerHTML; + var el = e.image.endsWith('.mp4') ? emoteToVideo(e) : emoteToImg(e); + return el.outerHTML; } else { return m; } }); + return msg; } @@ -2733,6 +2738,25 @@ function emoteToImg(e) { return img; } +function emoteToVideo(e) { + var video = document.createElement('video'); + video.className = 'channel-emote'; + video.setAttribute('autoplay', ''); + video.setAttribute('loop', ''); + video.setAttribute('muted', ''); + video.setAttribute('playsinline', ''); + video.muted = true; + video.style.width = '100%'; + video.style.height = '100%'; + + var source = document.createElement('source'); + source.src = e.image; + source.type = 'video/mp4'; + + video.appendChild(source); + return video; +} + function initPm(user) { if ($("#pm-" + user).length > 0) { return $("#pm-" + user); @@ -3065,13 +3089,31 @@ EmoteList.prototype.loadPage = function (page) { hax.className = "emote-preview-hax"; td.appendChild(hax); - var img = document.createElement("img"); - img.src = emote.image; - img.className = "emote-preview"; - img.title = emote.name; - img.onclick = _this.emoteClickCallback.bind(null, emote); + var el; + if (emote.image.endsWith('.mp4')) { + el = document.createElement("video"); + el.className = "emote-preview"; + el.autoplay = true; + el.loop = true; + el.muted = true; + el.playsInline = true; + el.width = 100; + el.height = 100; - td.appendChild(img); + var source = document.createElement("source"); + source.src = emote.image; + source.type = "video/mp4"; + el.appendChild(source); + } else { + el = document.createElement("img"); + el.src = emote.image; + } + + el.className = "emote-preview"; + el.title = emote.name; + el.onclick = _this.emoteClickCallback.bind(null, emote); + + td.appendChild(el); row.appendChild(td); })(this.emotes[i]); } @@ -3206,12 +3248,20 @@ CSEmoteList.prototype.loadPage = function (page) { tdImage.appendChild(urlDisplay); row.appendChild(tdImage); - // Add popover to display the image + // Add popover to display the image or video var $urlDisplay = $(urlDisplay); + var isVideo = emote.image.endsWith('.mp4'); + + var popoverContent = isVideo + ? '' + : ''; + $urlDisplay.popover({ html: true, trigger: "hover", - content: '' + content: popoverContent }); // Change the image for an emote