diff --git a/desktop/app.js b/desktop/app.js index e4d43c8..bc67687 100644 --- a/desktop/app.js +++ b/desktop/app.js @@ -132,6 +132,13 @@ const el = { mobileMembersBtn: document.getElementById("mobile-members-btn"), overlay: document.getElementById("overlay"), utilitySidebar: document.getElementById("utility-sidebar"), + + // GIF Picker + gifBtn: document.getElementById("gif-btn"), + gifPicker: document.getElementById("gif-picker"), + gifPickerClose: document.getElementById("gif-picker-close"), + gifSearchInput: document.getElementById("gif-search-input"), + gifResults: document.getElementById("gif-results"), }; // --- API Helpers --- @@ -222,6 +229,18 @@ function escapeHtml(s) { .replaceAll("'", "'"); } +function formatMessageBody(body) { + const escaped = escapeHtml(body); + // Detect GIF URLs (simple regex for demo) + const urlRegex = /(https?:\/\/[^\s]+(?:\.gif|\/giphy\.gif)[^\s]*)/gi; + if (urlRegex.test(body)) { + return escaped.replace(urlRegex, (url) => { + return `
`; + }); + } + return escaped; +} + function formatDate(isoString) { const d = new Date(isoString); const now = new Date(); @@ -423,7 +442,7 @@ function renderMessages(messages) { const displayName = m.author_display_name || "Unknown User"; if (isGrouped) { - row.innerHTML = `
${escapeHtml(m.body)}
`; + row.innerHTML = `
${formatMessageBody(m.body)}
`; } else { row.innerHTML = `
${shortName(displayName)}
@@ -432,7 +451,7 @@ function renderMessages(messages) { ${escapeHtml(displayName)} ${formatDate(m.created_at)} -
${escapeHtml(m.body)}
+
${formatMessageBody(m.body)}
`; } @@ -1435,6 +1454,84 @@ async function init() { } }; + // --- GIF Picker Logic --- + const GIPHY_API_KEY = "dc6zaTOxFJmzC"; // Public beta key + + el.gifBtn.onclick = () => { + el.gifPicker.classList.remove("hidden"); + searchGifs(""); // Initial trending search + }; + + el.gifPickerClose.onclick = () => { + el.gifPicker.classList.add("hidden"); + }; + + let searchTimeout = null; + el.gifSearchInput.oninput = () => { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + searchGifs(el.gifSearchInput.value); + }, 500); + }; + + async function searchGifs(query) { + el.gifResults.innerHTML = '
Searching...
'; + const endpoint = query + ? `https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_API_KEY}&q=${encodeURIComponent(query)}&limit=20` + : `https://api.giphy.com/v1/gifs/trending?api_key=${GIPHY_API_KEY}&limit=20`; + + try { + const res = await fetch(endpoint); + const data = await res.json(); + renderGifs(data.data); + } catch (err) { + el.gifResults.innerHTML = '
Error loading GIFs
'; + } + } + + function renderGifs(gifs) { + el.gifResults.innerHTML = ""; + if (!gifs || gifs.length === 0) { + el.gifResults.innerHTML = '
No GIFs found
'; + return; + } + + gifs.forEach(gif => { + const imgUrl = gif.images.fixed_height.url; + const item = document.createElement("div"); + item.className = "gif-item"; + item.innerHTML = ``; + item.onclick = () => { + sendGif(imgUrl); + el.gifPicker.classList.add("hidden"); + el.gifSearchInput.value = ""; + }; + el.gifResults.appendChild(item); + }); + } + + async function sendGif(url) { + try { + if (state.selectedTextChannelId) { + await api(`/channels/${state.selectedTextChannelId}/messages`, { + method: "POST", + body: JSON.stringify({ body: url }), + }); + } else if (state.selectedDmUserId) { + await api(`/dms/${state.selectedDmUserId}/messages`, { + method: "POST", + body: JSON.stringify({ body: url }), + }); + } + const messages = state.selectedTextChannelId + ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) + : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); + renderMessages(messages); + } catch (err) { + console.error("Failed to send GIF", err); + } + } + try { state.me = await api("/me"); if (state.me && state.me.display_name) { diff --git a/desktop/index.html b/desktop/index.html index a1957ac..c0b54c6 100644 --- a/desktop/index.html +++ b/desktop/index.html @@ -138,6 +138,9 @@
+
@@ -157,6 +160,24 @@ + `; } @@ -1414,6 +1433,84 @@ async function init() { } }; + // --- GIF Picker Logic --- + const GIPHY_API_KEY = "dc6zaTOxFJmzC"; // Public beta key + + el.gifBtn.onclick = () => { + el.gifPicker.classList.remove("hidden"); + searchGifs(""); // Initial trending search + }; + + el.gifPickerClose.onclick = () => { + el.gifPicker.classList.add("hidden"); + }; + + let searchTimeout = null; + el.gifSearchInput.oninput = () => { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + searchGifs(el.gifSearchInput.value); + }, 500); + }; + + async function searchGifs(query) { + el.gifResults.innerHTML = '
Searching...
'; + const endpoint = query + ? `https://api.giphy.com/v1/gifs/search?api_key=${GIPHY_API_KEY}&q=${encodeURIComponent(query)}&limit=20` + : `https://api.giphy.com/v1/gifs/trending?api_key=${GIPHY_API_KEY}&limit=20`; + + try { + const res = await fetch(endpoint); + const data = await res.json(); + renderGifs(data.data); + } catch (err) { + el.gifResults.innerHTML = '
Error loading GIFs
'; + } + } + + function renderGifs(gifs) { + el.gifResults.innerHTML = ""; + if (!gifs || gifs.length === 0) { + el.gifResults.innerHTML = '
No GIFs found
'; + return; + } + + gifs.forEach(gif => { + const imgUrl = gif.images.fixed_height.url; + const item = document.createElement("div"); + item.className = "gif-item"; + item.innerHTML = ``; + item.onclick = () => { + sendGif(imgUrl); + el.gifPicker.classList.add("hidden"); + el.gifSearchInput.value = ""; + }; + el.gifResults.appendChild(item); + }); + } + + async function sendGif(url) { + try { + if (state.selectedTextChannelId) { + await api(`/channels/${state.selectedTextChannelId}/messages`, { + method: "POST", + body: JSON.stringify({ body: url }), + }); + } else if (state.selectedDmUserId) { + await api(`/dms/${state.selectedDmUserId}/messages`, { + method: "POST", + body: JSON.stringify({ body: url }), + }); + } + const messages = state.selectedTextChannelId + ? await api(`/channels/${state.selectedTextChannelId}/messages?limit=100`) + : await api(`/dms/${state.selectedDmUserId}/messages?limit=100`); + renderMessages(messages); + } catch (err) { + console.error("Failed to send GIF", err); + } + } + try { state.me = await api("/me"); if (state.me && state.me.display_name) { diff --git a/static/index.html b/static/index.html index e13e17c..f9a274a 100644 --- a/static/index.html +++ b/static/index.html @@ -138,6 +138,9 @@
+
@@ -157,6 +160,24 @@ +