diff --git a/static/emoji-resolver.js b/static/emoji-resolver.js new file mode 100644 index 0000000..e628b85 --- /dev/null +++ b/static/emoji-resolver.js @@ -0,0 +1,117 @@ +// Emoji Resolver Module - Handles mapping emoji names to correct filenames +(function() { + 'use strict'; + + // Cache for emoji name -> filename mapping + let emojiMap = null; + let loadPromise = null; + + // Load emoji mapping from API + async function loadEmojiMap() { + if (emojiMap) return emojiMap; + if (loadPromise) return loadPromise; + + loadPromise = fetch('/api/custom-emojis') + .then(response => response.json()) + .then(data => { + if (!Array.isArray(data)) { + console.error('Invalid emoji data received'); + return new Map(); + } + emojiMap = new Map(data.map(emoji => [emoji.name, emoji.filename])); + return emojiMap; + }) + .catch(err => { + console.error('Failed to load emoji map:', err); + emojiMap = new Map(); + return emojiMap; + }); + + return loadPromise; + } + + // Get the correct emoji filename for a given name + function getEmojiFilename(emojiName) { + if (!emojiMap) return null; + return emojiMap.get(emojiName); + } + + // Update a single emoji image element + function updateEmojiImage(img) { + const emojiName = img.getAttribute('data-emoji-name'); + if (!emojiName) return; + + const filename = getEmojiFilename(emojiName); + if (filename) { + // Found the correct filename, update src + img.src = `/emojis/${filename}`; + // Remove placeholder class if present + img.classList.remove('emoji-placeholder'); + // Remove the error handler since we have the correct path + img.onerror = null; + } else { + // Emoji not found in map, try common extensions as fallback + // This handles newly added emojis that aren't in the cached map yet + img.src = `/emojis/${emojiName}.png`; + img.onerror = function() { + this.onerror = null; + this.src = `/emojis/${emojiName}.gif`; + }; + img.classList.remove('emoji-placeholder'); + } + } + + // Update all emoji images on the page + function updateAllEmojiImages() { + const images = document.querySelectorAll('img[data-emoji-name]'); + images.forEach(updateEmojiImage); + } + + // Initialize on DOM ready + async function initialize() { + // Load the emoji map + await loadEmojiMap(); + // Update all existing emoji images + updateAllEmojiImages(); + + // Set up a MutationObserver to handle dynamically added content + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (node.nodeType === Node.ELEMENT_NODE) { + // Check if the added node is an emoji image + if (node.tagName === 'IMG' && node.getAttribute('data-emoji-name')) { + updateEmojiImage(node); + } + // Also check descendants + const images = node.querySelectorAll?.('img[data-emoji-name]'); + images?.forEach(updateEmojiImage); + } + }); + }); + }); + + // Start observing the document body for changes + observer.observe(document.body, { + childList: true, + subtree: true + }); + } + + // Export to global scope + window.EmojiResolver = { + loadEmojiMap, + getEmojiFilename, + updateEmojiImage, + updateAllEmojiImages, + initialize + }; + + // Auto-initialize when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initialize); + } else { + // DOM is already ready + initialize(); + } +})(); \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 20f19f6..89a78e3 100644 --- a/templates/base.html +++ b/templates/base.html @@ -31,6 +31,9 @@ + + +