diff --git a/src/aviaclientcategory.js b/src/aviaclientcategory.js index 36b9fea..fe7af8b 100644 --- a/src/aviaclientcategory.js +++ b/src/aviaclientcategory.js @@ -1,34 +1,34 @@ (function(){ -if(window.__AVIA_CATEGORY_SETTINGS__) return; -window.__AVIA_CATEGORY_SETTINGS__ = true; + if(window.__AVIA_CATEGORY_SETTINGS__) return; + window.__AVIA_CATEGORY_SETTINGS__ = true; -function inject(){ + function inject(){ - if(document.getElementById('avia-cloned-settings')) return; + if(document.getElementById('avia-cloned-settings')) return; - const spans = [...document.querySelectorAll('span')]; - const target = spans.find(s => s.textContent.trim() === "User Settings"); - if(!target) return; + const spans = [...document.querySelectorAll('span')]; + const target = spans.find(s => s.textContent.trim() === "User Settings"); + if(!target) return; - const container = target.closest('.d_flex.flex-d_column'); - if(!container) return; + const container = target.closest('.d_flex.flex-d_column'); + if(!container) return; - const clone = container.cloneNode(true); - clone.id = "avia-cloned-settings"; + const clone = container.cloneNode(true); + clone.id = "avia-cloned-settings"; - const header = clone.querySelector('span'); - if(header) header.textContent = "AVIA CLIENT SETTINGS"; + const header = clone.querySelector('span'); + if(header) header.textContent = "AVIA CLIENT SETTINGS"; - const list = clone.querySelector('.d_flex.flex-d_column.gap_var\\(--gap-s\\)'); - if(list) list.innerHTML = ""; + const list = clone.querySelector('.d_flex.flex-d_column.gap_var\\(--gap-s\\)'); + if(list) list.innerHTML = ""; - container.parentNode.insertBefore(clone, container.nextSibling); -} + container.parentNode.insertBefore(clone, container.nextSibling); + } -new MutationObserver(() => { - inject(); -}).observe(document.body, { childList: true, subtree: true }); + new MutationObserver(() => { + inject(); + }).observe(document.body, { childList: true, subtree: true }); -inject(); + inject(); -})(); \ No newline at end of file +})(); diff --git a/src/aviafavsystem.js b/src/aviafavsystem.js index 3b1a4fb..ea277f9 100644 --- a/src/aviafavsystem.js +++ b/src/aviafavsystem.js @@ -1,349 +1,349 @@ (function () { -if (window.__AVIA_FAVORITES_LOADED__) return; -window.__AVIA_FAVORITES_LOADED__ = true; + if (window.__AVIA_FAVORITES_LOADED__) return; + window.__AVIA_FAVORITES_LOADED__ = true; -const STORAGE_KEY = "avia_favorites"; + const STORAGE_KEY = "avia_favorites"; -const getFavorites = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]"); -const setFavorites = (data) => localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); + const getFavorites = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]"); + const setFavorites = (data) => localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); -function extractYouTubeID(url) { - const reg = /(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([^&?/]+)/; - const match = url.match(reg); - return match ? match[1] : null; -} - -function toggleFavoritesPanel() { - - let panel = document.getElementById("avia-favorites-panel"); - if (panel) { - panel.style.display = panel.style.display === "none" ? "flex" : "none"; - return; + function extractYouTubeID(url) { + const reg = /(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([^&?/]+)/; + const match = url.match(reg); + return match ? match[1] : null; } - panel = document.createElement("div"); - panel.id = "avia-favorites-panel"; + function toggleFavoritesPanel() { - Object.assign(panel.style, { - position: "fixed", - bottom: "40px", - right: "40px", - width: "640px", - height: "580px", - background: "#1e1e1e", - color: "#fff", - borderRadius: "20px", - boxShadow: "0 12px 35px rgba(0,0,0,0.45)", - zIndex: 999999, - display: "flex", - flexDirection: "column", - overflow: "hidden", - border: "1px solid rgba(255,255,255,0.08)" - }); + let panel = document.getElementById("avia-favorites-panel"); + if (panel) { + panel.style.display = panel.style.display === "none" ? "flex" : "none"; + return; + } - const header = document.createElement("div"); - header.textContent = "Favorites"; - Object.assign(header.style, { - padding: "18px", - fontWeight: "600", - fontSize: "16px", - background: "rgba(255,255,255,0.04)", - borderBottom: "1px solid rgba(255,255,255,0.08)", - cursor: "move", - position: "relative", - userSelect: "none" - }); + panel = document.createElement("div"); + panel.id = "avia-favorites-panel"; - const close = document.createElement("div"); - close.textContent = "✕"; - Object.assign(close.style, { - position: "absolute", - right: "18px", - top: "16px", - cursor: "pointer" - }); - close.onclick = () => panel.style.display = "none"; - header.appendChild(close); + Object.assign(panel.style, { + position: "fixed", + bottom: "40px", + right: "40px", + width: "640px", + height: "580px", + background: "#1e1e1e", + color: "#fff", + borderRadius: "20px", + boxShadow: "0 12px 35px rgba(0,0,0,0.45)", + zIndex: 999999, + display: "flex", + flexDirection: "column", + overflow: "hidden", + border: "1px solid rgba(255,255,255,0.08)" + }); - const inputRow = document.createElement("div"); - Object.assign(inputRow.style, { - display: "flex", - gap: "8px", - padding: "14px 18px" - }); + const header = document.createElement("div"); + header.textContent = "Favorites"; + Object.assign(header.style, { + padding: "18px", + fontWeight: "600", + fontSize: "16px", + background: "rgba(255,255,255,0.04)", + borderBottom: "1px solid rgba(255,255,255,0.08)", + cursor: "move", + position: "relative", + userSelect: "none" + }); - const urlInput = document.createElement("input"); - urlInput.placeholder = "Paste link..."; - Object.assign(urlInput.style, { - flex: "2", - padding: "10px", - borderRadius: "10px", - border: "none", - outline: "none" - }); - - const titleInput = document.createElement("input"); - titleInput.placeholder = "Optional title..."; - Object.assign(titleInput.style, { - flex: "1", - padding: "10px", - borderRadius: "10px", - border: "none", - outline: "none" - }); - - const addBtn = document.createElement("button"); - addBtn.textContent = "Add"; - Object.assign(addBtn.style, { - padding: "10px 16px", - borderRadius: "10px", - border: "none", - cursor: "pointer" - }); - - inputRow.appendChild(urlInput); - inputRow.appendChild(titleInput); - inputRow.appendChild(addBtn); - - const grid = document.createElement("div"); - Object.assign(grid.style, { - flex: "1", - minHeight: "0", - overflowY: "auto", - padding: "18px", - display: "grid", - gridTemplateColumns: "repeat(auto-fill, 120px)", - gap: "14px", - alignContent: "start" - }); - - panel.appendChild(header); - panel.appendChild(inputRow); - panel.appendChild(grid); - document.body.appendChild(panel); - - let isDragging = false, offsetX, offsetY; - - header.addEventListener("mousedown", e => { - isDragging = true; - offsetX = e.clientX - panel.offsetLeft; - offsetY = e.clientY - panel.offsetTop; - }); - - document.addEventListener("mouseup", () => isDragging = false); - - document.addEventListener("mousemove", e => { - if (!isDragging) return; - panel.style.left = (e.clientX - offsetX) + "px"; - panel.style.top = (e.clientY - offsetY) + "px"; - panel.style.right = "auto"; - panel.style.bottom = "auto"; - }); - - function showToast(card) { - const toast = document.createElement("div"); - toast.textContent = "Copied to clipboard"; - Object.assign(toast.style, { + const close = document.createElement("div"); + close.textContent = "✕"; + Object.assign(close.style, { position: "absolute", - bottom: "6px", - left: "50%", - transform: "translateX(-50%)", - background: "rgba(0,0,0,0.85)", - padding: "6px 10px", - borderRadius: "8px", - fontSize: "11px", - opacity: "0", - transition: "opacity 0.2s", - pointerEvents: "none" + right: "18px", + top: "16px", + cursor: "pointer" }); - card.appendChild(toast); - requestAnimationFrame(() => toast.style.opacity = "1"); - setTimeout(() => { - toast.style.opacity = "0"; - setTimeout(() => toast.remove(), 200); - }, 2000); - } + close.onclick = () => panel.style.display = "none"; + header.appendChild(close); - function fallbackCopy(text) { - const textarea = document.createElement("textarea"); - textarea.value = text; - textarea.style.position = "fixed"; - textarea.style.opacity = "0"; - document.body.appendChild(textarea); - textarea.focus(); - textarea.select(); - try { document.execCommand("copy"); } catch {} - document.body.removeChild(textarea); - } + const inputRow = document.createElement("div"); + Object.assign(inputRow.style, { + display: "flex", + gap: "8px", + padding: "14px 18px" + }); - function render() { + const urlInput = document.createElement("input"); + urlInput.placeholder = "Paste link..."; + Object.assign(urlInput.style, { + flex: "2", + padding: "10px", + borderRadius: "10px", + border: "none", + outline: "none" + }); - grid.innerHTML = ""; - const favorites = getFavorites(); + const titleInput = document.createElement("input"); + titleInput.placeholder = "Optional title..."; + Object.assign(titleInput.style, { + flex: "1", + padding: "10px", + borderRadius: "10px", + border: "none", + outline: "none" + }); - favorites.forEach(item => { + const addBtn = document.createElement("button"); + addBtn.textContent = "Add"; + Object.assign(addBtn.style, { + padding: "10px 16px", + borderRadius: "10px", + border: "none", + cursor: "pointer" + }); - const card = document.createElement("div"); - Object.assign(card.style, { - position: "relative", - width: "120px", - height: "120px", - borderRadius: "14px", - overflow: "hidden", - background: "rgba(255,255,255,0.05)", - cursor: "pointer", - display: "flex", - alignItems: "center", - justifyContent: "center" - }); + inputRow.appendChild(urlInput); + inputRow.appendChild(titleInput); + inputRow.appendChild(addBtn); - const remove = document.createElement("div"); - remove.textContent = "✕"; - Object.assign(remove.style, { + const grid = document.createElement("div"); + Object.assign(grid.style, { + flex: "1", + minHeight: "0", + overflowY: "auto", + padding: "18px", + display: "grid", + gridTemplateColumns: "repeat(auto-fill, 120px)", + gap: "14px", + alignContent: "start" + }); + + panel.appendChild(header); + panel.appendChild(inputRow); + panel.appendChild(grid); + document.body.appendChild(panel); + + let isDragging = false, offsetX, offsetY; + + header.addEventListener("mousedown", e => { + isDragging = true; + offsetX = e.clientX - panel.offsetLeft; + offsetY = e.clientY - panel.offsetTop; + }); + + document.addEventListener("mouseup", () => isDragging = false); + + document.addEventListener("mousemove", e => { + if (!isDragging) return; + panel.style.left = (e.clientX - offsetX) + "px"; + panel.style.top = (e.clientY - offsetY) + "px"; + panel.style.right = "auto"; + panel.style.bottom = "auto"; + }); + + function showToast(card) { + const toast = document.createElement("div"); + toast.textContent = "Copied to clipboard"; + Object.assign(toast.style, { position: "absolute", - top: "6px", - right: "8px", - fontSize: "12px", - cursor: "pointer", - background: "rgba(0,0,0,0.6)", - padding: "2px 6px", - borderRadius: "6px", - zIndex: 2 + bottom: "6px", + left: "50%", + transform: "translateX(-50%)", + background: "rgba(0,0,0,0.85)", + padding: "6px 10px", + borderRadius: "8px", + fontSize: "11px", + opacity: "0", + transition: "opacity 0.2s", + pointerEvents: "none" }); + card.appendChild(toast); + requestAnimationFrame(() => toast.style.opacity = "1"); + setTimeout(() => { + toast.style.opacity = "0"; + setTimeout(() => toast.remove(), 200); + }, 2000); + } - remove.onclick = (e) => { - e.stopPropagation(); - setFavorites(favorites.filter(f => f.url !== item.url)); - render(); - }; + function fallbackCopy(text) { + const textarea = document.createElement("textarea"); + textarea.value = text; + textarea.style.position = "fixed"; + textarea.style.opacity = "0"; + document.body.appendChild(textarea); + textarea.focus(); + textarea.select(); + try { document.execCommand("copy"); } catch {} + document.body.removeChild(textarea); + } - card.appendChild(remove); + function render() { - let mediaAdded = false; + grid.innerHTML = ""; + const favorites = getFavorites(); - const ytID = extractYouTubeID(item.url); - if (ytID) { - const img = new Image(); - img.src = `https://img.youtube.com/vi/${ytID}/hqdefault.jpg`; - Object.assign(img.style, { width:"100%", height:"100%", objectFit:"cover" }); - card.appendChild(img); - mediaAdded = true; - } + favorites.forEach(item => { - if (!mediaAdded) { - const ext = item.url.split(".").pop().split("?")[0].toLowerCase(); - const isVideo = ["mp4","webm","mov","gifv"].includes(ext); + const card = document.createElement("div"); + Object.assign(card.style, { + position: "relative", + width: "120px", + height: "120px", + borderRadius: "14px", + overflow: "hidden", + background: "rgba(255,255,255,0.05)", + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "center" + }); - if (isVideo) { - const video = document.createElement("video"); - video.src = item.url.replace(".gifv",".mp4"); - video.autoplay = true; - video.loop = true; - video.muted = true; - video.playsInline = true; - Object.assign(video.style, { width:"100%", height:"100%", objectFit:"cover" }); - video.onerror = fallback; - card.appendChild(video); - } else { - const img = new Image(); - img.src = item.url; - Object.assign(img.style, { width:"100%", height:"100%", objectFit:"cover" }); - img.onerror = fallback; - card.appendChild(img); - } - } + const remove = document.createElement("div"); + remove.textContent = "✕"; + Object.assign(remove.style, { + position: "absolute", + top: "6px", + right: "8px", + fontSize: "12px", + cursor: "pointer", + background: "rgba(0,0,0,0.6)", + padding: "2px 6px", + borderRadius: "6px", + zIndex: 2 + }); + + remove.onclick = (e) => { + e.stopPropagation(); + setFavorites(favorites.filter(f => f.url !== item.url)); + render(); + }; - function fallback() { - card.innerHTML = ""; card.appendChild(remove); - const text = document.createElement("div"); - text.textContent = item.title || item.url; - Object.assign(text.style, { - padding:"8px", - fontSize:"11px", - textAlign:"center", - wordBreak:"break-word" - }); - card.appendChild(text); - } - if (item.title) { - const titleOverlay = document.createElement("div"); - titleOverlay.textContent = item.title; - Object.assign(titleOverlay.style, { - position:"absolute", - bottom:"0", - width:"100%", - background:"rgba(0,0,0,0.6)", - fontSize:"11px", - padding:"4px", - textAlign:"center", - whiteSpace:"nowrap", - overflow:"hidden", - textOverflow:"ellipsis" - }); - card.appendChild(titleOverlay); - } + let mediaAdded = false; - card.onclick = () => { - const doToast = () => showToast(card); - if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(item.url) - .then(doToast) - .catch(() => { - fallbackCopy(item.url); - doToast(); - }); - } else { - fallbackCopy(item.url); - doToast(); + const ytID = extractYouTubeID(item.url); + if (ytID) { + const img = new Image(); + img.src = `https://img.youtube.com/vi/${ytID}/hqdefault.jpg`; + Object.assign(img.style, { width:"100%", height:"100%", objectFit:"cover" }); + card.appendChild(img); + mediaAdded = true; } - }; - grid.appendChild(card); - }); + if (!mediaAdded) { + const ext = item.url.split(".").pop().split("?")[0].toLowerCase(); + const isVideo = ["mp4","webm","mov","gifv"].includes(ext); + + if (isVideo) { + const video = document.createElement("video"); + video.src = item.url.replace(".gifv",".mp4"); + video.autoplay = true; + video.loop = true; + video.muted = true; + video.playsInline = true; + Object.assign(video.style, { width:"100%", height:"100%", objectFit:"cover" }); + video.onerror = fallback; + card.appendChild(video); + } else { + const img = new Image(); + img.src = item.url; + Object.assign(img.style, { width:"100%", height:"100%", objectFit:"cover" }); + img.onerror = fallback; + card.appendChild(img); + } + } + + function fallback() { + card.innerHTML = ""; + card.appendChild(remove); + const text = document.createElement("div"); + text.textContent = item.title || item.url; + Object.assign(text.style, { + padding:"8px", + fontSize:"11px", + textAlign:"center", + wordBreak:"break-word" + }); + card.appendChild(text); + } + + if (item.title) { + const titleOverlay = document.createElement("div"); + titleOverlay.textContent = item.title; + Object.assign(titleOverlay.style, { + position:"absolute", + bottom:"0", + width:"100%", + background:"rgba(0,0,0,0.6)", + fontSize:"11px", + padding:"4px", + textAlign:"center", + whiteSpace:"nowrap", + overflow:"hidden", + textOverflow:"ellipsis" + }); + card.appendChild(titleOverlay); + } + + card.onclick = () => { + const doToast = () => showToast(card); + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(item.url) + .then(doToast) + .catch(() => { + fallbackCopy(item.url); + doToast(); + }); + } else { + fallbackCopy(item.url); + doToast(); + } + }; + + grid.appendChild(card); + }); + } + + addBtn.onclick = () => { + const url = urlInput.value.trim(); + const title = titleInput.value.trim(); + if (!url) return; + const favorites = getFavorites(); + if (favorites.some(f => f.url === url)) return; + favorites.push({ url, title, addedAt: Date.now() }); + setFavorites(favorites); + urlInput.value = ""; + titleInput.value = ""; + render(); + }; + + render(); } - addBtn.onclick = () => { - const url = urlInput.value.trim(); - const title = titleInput.value.trim(); - if (!url) return; - const favorites = getFavorites(); - if (favorites.some(f => f.url === url)) return; - favorites.push({ url, title, addedAt: Date.now() }); - setFavorites(favorites); - urlInput.value = ""; - titleInput.value = ""; - render(); - }; + function injectButton() { - render(); -} + if (document.getElementById("avia-favorites-btn")) return; -function injectButton() { + const gifSpan = [...document.querySelectorAll("span.material-symbols-outlined")] + .find(s => s.textContent.trim() === "gif"); - if (document.getElementById("avia-favorites-btn")) return; + if (!gifSpan) return; - const gifSpan = [...document.querySelectorAll("span.material-symbols-outlined")] - .find(s => s.textContent.trim() === "gif"); + const wrapper = gifSpan.closest("div.flex-sh_0"); + if (!wrapper) return; - if (!gifSpan) return; + const clone = wrapper.cloneNode(true); + clone.id = "avia-favorites-btn"; + clone.querySelector("span.material-symbols-outlined").textContent = "star"; + clone.querySelector("button").onclick = toggleFavoritesPanel; - const wrapper = gifSpan.closest("div.flex-sh_0"); - if (!wrapper) return; + wrapper.parentElement.insertBefore(clone, wrapper.nextSibling); + } - const clone = wrapper.cloneNode(true); - clone.id = "avia-favorites-btn"; - clone.querySelector("span.material-symbols-outlined").textContent = "star"; - clone.querySelector("button").onclick = toggleFavoritesPanel; + new MutationObserver(injectButton) + .observe(document.body, { childList: true, subtree: true }); - wrapper.parentElement.insertBefore(clone, wrapper.nextSibling); -} - -new MutationObserver(injectButton) -.observe(document.body, { childList: true, subtree: true }); - -injectButton(); + injectButton(); })(); diff --git a/src/aviaversion.js b/src/aviaversion.js index 1396b7c..31114ce 100644 --- a/src/aviaversion.js +++ b/src/aviaversion.js @@ -1,41 +1,40 @@ (function () { -if (window.__AVIA_VERSION_PATCH__) return; -window.__AVIA_VERSION_PATCH__ = true; + if (window.__AVIA_VERSION_PATCH__) return; + window.__AVIA_VERSION_PATCH__ = true; -function patchVersion() { + function patchVersion() { - document - .querySelectorAll("span.lh_1rem.fs_0\\.75rem.ls_0\\.03125rem.fw_500") - .forEach(el => { + document + .querySelectorAll("span.lh_1rem.fs_0\\.75rem.ls_0\\.03125rem.fw_500") + .forEach(el => { - if (el.dataset.aviaPatched) return; + if (el.dataset.aviaPatched) return; - const match = el.textContent.match(/Stoat for Desktop\s+([0-9.]+)/); + const match = el.textContent.match(/Stoat for Desktop\s+([0-9.]+)/); - if (!match) return; + if (!match) return; - const stoatVersion = match[1]; + const stoatVersion = match[1]; - el.dataset.aviaPatched = "true"; + el.dataset.aviaPatched = "true"; - el.innerHTML = ` - Avia Client Desktop
- - Based on Stoat ${stoatVersion} - - `; - }); + el.innerHTML = ` +Avia Client Desktop
+ + Based on Stoat ${stoatVersion} + +`; + }); + } -} + const observer = new MutationObserver(patchVersion); -const observer = new MutationObserver(patchVersion); + observer.observe(document.body, { + childList: true, + subtree: true + }); -observer.observe(document.body, { - childList: true, - subtree: true -}); - -patchVersion(); + patchVersion(); })(); diff --git a/src/inject.js b/src/inject.js index 7c52184..981248a 100644 --- a/src/inject.js +++ b/src/inject.js @@ -243,15 +243,15 @@ const appearanceBtn = Array.from(document.querySelectorAll('a')).find(a => a.textContent.trim() === 'Appearance'); if (!appearanceBtn) return; -const aviaHeader = [...document.querySelectorAll('span')] - .find(s => s.textContent.trim() === "AVIA CLIENT SETTINGS"); -if (!aviaHeader) return; + const aviaHeader = [...document.querySelectorAll('span')] + .find(s => s.textContent.trim() === "AVIA CLIENT SETTINGS"); + if (!aviaHeader) return; -const aviaContainer = aviaHeader.closest('.d_flex.flex-d_column'); -if (!aviaContainer) return; + const aviaContainer = aviaHeader.closest('.d_flex.flex-d_column'); + if (!aviaContainer) return; -const targetParent = aviaContainer.querySelector('.d_flex.flex-d_column.gap_var\\(--gap-s\\)'); -if (!targetParent) return; + const targetParent = aviaContainer.querySelector('.d_flex.flex-d_column.gap_var\\(--gap-s\\)'); + if (!targetParent) return; if (!document.getElementById('stoat-fake-linktree')) { const linktreeBtn = appearanceBtn.cloneNode(true); @@ -305,7 +305,8 @@ if (!targetParent) return; document.getElementById('stoat-fake-loadfont') || document.getElementById('stoat-fake-stoatserver') || document.getElementById('stoat-fake-linktree'); -targetParent.appendChild(quickCssBtn); } + targetParent.appendChild(quickCssBtn); + } } function applyQuickCSS(css) { diff --git a/src/pluginsupport.js b/src/pluginsupport.js index 2c1671a..fe8f98a 100644 --- a/src/pluginsupport.js +++ b/src/pluginsupport.js @@ -518,4 +518,4 @@ if (plugin.enabled) queuePlugin(plugin); }); -})(); +})(); \ No newline at end of file diff --git a/src/themes.js b/src/themes.js index ebf5330..0c3b584 100644 --- a/src/themes.js +++ b/src/themes.js @@ -1,12 +1,12 @@ (function () { -if (window.__AVIA_THEMES_LOADED__) return; -window.__AVIA_THEMES_LOADED__ = true; + if (window.__AVIA_THEMES_LOADED__) return; + window.__AVIA_THEMES_LOADED__ = true; -const STORAGE_KEY = "avia_themes"; -let editingTheme = null; + const STORAGE_KEY = "avia_themes"; + let editingTheme = null; -const TEMPLATE = `/* + const TEMPLATE = `/* @name Whatever name here @author Whatever Author Here @version 1.0 @@ -15,367 +15,367 @@ const TEMPLATE = `/* `; -const getThemes = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]"); -const setThemes = (data) => localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); + const getThemes = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]"); + const setThemes = (data) => localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); -function parseMeta(css){ - const name = css.match(/@name\s+(.+)/)?.[1] || "Unknown Theme"; - const author = css.match(/@author\s+(.+)/)?.[1] || "Unknown"; - const version = css.match(/@version\s+(.+)/)?.[1] || "1.0"; - const rawDescription = css.match(/@description\s+(.+)/)?.[1] || "No Description Available"; - const description = rawDescription.trim() === "*/" ? "No Description Available" : rawDescription; - return {name,author,version,description}; -} - -function applyThemes(){ - document.querySelectorAll(".avia-theme-style").forEach(e=>e.remove()); - const themes = getThemes(); - themes.forEach(theme=>{ - if(!theme.enabled) return; - const style=document.createElement("style"); - style.className="avia-theme-style"; - style.textContent=theme.css; - document.head.appendChild(style); - }); -} - -function styleBtn(btn, bg) { - Object.assign(btn.style, { - padding: "5px 12px", - borderRadius: "8px", - border: "none", - background: bg || "rgba(255,255,255,0.08)", - color: "#fff", - cursor: "pointer", - fontSize: "12px", - whiteSpace: "nowrap", - fontWeight: "500" - }); - btn.onmouseenter = () => btn.style.opacity = "0.75"; - btn.onmouseleave = () => btn.style.opacity = "1"; -} - -function makeDraggable(panel, handle){ - let dragging=false,offsetX,offsetY; - handle.addEventListener("mousedown",e=>{ - dragging=true; - offsetX=e.clientX-panel.offsetLeft; - offsetY=e.clientY-panel.offsetTop; - document.body.style.userSelect="none"; - }); - document.addEventListener("mouseup",()=>{dragging=false;document.body.style.userSelect="";}); - document.addEventListener("mousemove",e=>{ - if(!dragging) return; - panel.style.left=(e.clientX-offsetX)+"px"; - panel.style.top=(e.clientY-offsetY)+"px"; - panel.style.right="auto"; - panel.style.bottom="auto"; - }); -} - -function openThemeEditor(theme){ - editingTheme = theme; - let panel = document.getElementById('avia-theme-editor'); - if(panel){ - panel.style.display="flex"; - panel.querySelector("textarea").value = theme.css; - return; + function parseMeta(css){ + const name = css.match(/@name\s+(.+)/)?.[1] || "Unknown Theme"; + const author = css.match(/@author\s+(.+)/)?.[1] || "Unknown"; + const version = css.match(/@version\s+(.+)/)?.[1] || "1.0"; + const rawDescription = css.match(/@description\s+(.+)/)?.[1] || "No Description Available"; + const description = rawDescription.trim() === "*/" ? "No Description Available" : rawDescription; + return {name,author,version,description}; } - panel=document.createElement("div"); - panel.id="avia-theme-editor"; - Object.assign(panel.style,{ - position:"fixed", - bottom:"24px", - right:"24px", - width:"420px", - height:"340px", - background:"var(--md-sys-color-surface,#1e1e1e)", - color:"var(--md-sys-color-on-surface,#fff)", - borderRadius:"16px", - boxShadow:"0 8px 28px rgba(0,0,0,0.35)", - zIndex:999999, - display:"flex", - flexDirection:"column", - overflow:"hidden", - border:"1px solid rgba(255,255,255,0.08)", - backdropFilter:"blur(12px)" - }); - const header=document.createElement("div"); - header.textContent="Theme Editor"; - Object.assign(header.style,{ - padding:"14px 16px", - fontWeight:"600", - fontSize:"14px", - background:"var(--md-sys-color-surface-container,rgba(255,255,255,0.04))", - borderBottom:"1px solid rgba(255,255,255,0.08)", - cursor:"move" - }); - makeDraggable(panel,header); - const close=document.createElement("div"); - close.textContent="✕"; - Object.assign(close.style,{ - position:"absolute", - right:"16px", - top:"12px", - cursor:"pointer", - opacity:"0.6", - fontSize:"15px", - lineHeight:"1", - padding:"2px 4px" - }); - close.onmouseenter=()=>close.style.opacity="1"; - close.onmouseleave=()=>close.style.opacity="0.6"; - close.onclick=()=>panel.style.display="none"; - const textarea=document.createElement("textarea"); - Object.assign(textarea.style,{ - flex:"1", - border:"none", - outline:"none", - resize:"none", - padding:"16px", - background:"transparent", - color:"inherit", - fontFamily:"monospace", - fontSize:"13px" - }); - textarea.value=theme.css; - textarea.addEventListener("input",()=>{ - const themes=getThemes(); - const t=themes.find(x=>x.id===editingTheme.id); - if(!t) return; - t.css=textarea.value; - setThemes(themes); - applyThemes(); - if(window.__avia_refresh_themes_panel){window.__avia_refresh_themes_panel();} - }); - panel.appendChild(header); - panel.appendChild(close); - panel.appendChild(textarea); - document.body.appendChild(panel); -} -function toggleThemesPanel(){ - let panel=document.getElementById("avia-themes-panel"); - if(panel){ - panel.style.display = panel.style.display==="none"?"flex":"none"; - return; + function applyThemes(){ + document.querySelectorAll(".avia-theme-style").forEach(e=>e.remove()); + const themes = getThemes(); + themes.forEach(theme=>{ + if(!theme.enabled) return; + const style=document.createElement("style"); + style.className="avia-theme-style"; + style.textContent=theme.css; + document.head.appendChild(style); + }); } - panel=document.createElement("div"); - panel.id="avia-themes-panel"; - Object.assign(panel.style,{ - position:"fixed", - bottom:"40px", - right:"40px", - width:"500px", - height:"460px", - background:"var(--md-sys-color-surface,#1e1e1e)", - color:"var(--md-sys-color-on-surface,#fff)", - borderRadius:"16px", - boxShadow:"0 8px 28px rgba(0,0,0,0.35)", - zIndex:999999, - display:"flex", - flexDirection:"column", - overflow:"hidden", - border:"1px solid rgba(255,255,255,0.08)", - backdropFilter:"blur(12px)" - }); - const header=document.createElement("div"); - header.textContent="Themes"; - Object.assign(header.style,{ - padding:"14px 16px", - fontWeight:"600", - fontSize:"14px", - background:"var(--md-sys-color-surface-container,rgba(255,255,255,0.04))", - borderBottom:"1px solid rgba(255,255,255,0.08)", - cursor:"move" - }); - makeDraggable(panel,header); + function styleBtn(btn, bg) { + Object.assign(btn.style, { + padding: "5px 12px", + borderRadius: "8px", + border: "none", + background: bg || "rgba(255,255,255,0.08)", + color: "#fff", + cursor: "pointer", + fontSize: "12px", + whiteSpace: "nowrap", + fontWeight: "500" + }); + btn.onmouseenter = () => btn.style.opacity = "0.75"; + btn.onmouseleave = () => btn.style.opacity = "1"; + } - const close=document.createElement("div"); - close.textContent="✕"; - Object.assign(close.style,{ - position:"absolute", - right:"16px", - top:"12px", - cursor:"pointer", - opacity:"0.6", - fontSize:"15px", - lineHeight:"1", - padding:"2px 4px" - }); - close.onmouseenter=()=>close.style.opacity="1"; - close.onmouseleave=()=>close.style.opacity="0.6"; - close.onclick=()=>panel.style.display="none"; + function makeDraggable(panel, handle){ + let dragging=false,offsetX,offsetY; + handle.addEventListener("mousedown",e=>{ + dragging=true; + offsetX=e.clientX-panel.offsetLeft; + offsetY=e.clientY-panel.offsetTop; + document.body.style.userSelect="none"; + }); + document.addEventListener("mouseup",()=>{dragging=false;document.body.style.userSelect="";}); + document.addEventListener("mousemove",e=>{ + if(!dragging) return; + panel.style.left=(e.clientX-offsetX)+"px"; + panel.style.top=(e.clientY-offsetY)+"px"; + panel.style.right="auto"; + panel.style.bottom="auto"; + }); + } - const btnRow=document.createElement("div"); - Object.assign(btnRow.style,{ - display:"flex", - gap:"8px", - padding:"12px 16px", - borderBottom:"1px solid rgba(255,255,255,0.08)", - flex:"0 0 auto" - }); - - const importBtn=document.createElement("button"); - importBtn.textContent="Import Theme"; - styleBtn(importBtn); - importBtn.style.flex="1"; - importBtn.style.padding="8px 12px"; - - const newBtn=document.createElement("button"); - newBtn.textContent="+ New"; - styleBtn(newBtn); - newBtn.style.flex="1"; - newBtn.style.padding="8px 12px"; - - btnRow.appendChild(importBtn); - btnRow.appendChild(newBtn); - - const list=document.createElement("div"); - Object.assign(list.style,{ - flex:"1", - overflowY:"auto", - padding:"16px", - display:"flex", - flexDirection:"column", - gap:"8px" - }); - - panel.appendChild(header); - panel.appendChild(close); - panel.appendChild(btnRow); - panel.appendChild(list); - document.body.appendChild(panel); - - function render(){ - list.innerHTML=""; - const themes=getThemes(); - - if(themes.length === 0){ - const empty=document.createElement("div"); - empty.textContent="No themes yet. Import or create one above."; - Object.assign(empty.style,{opacity:"0.4",fontSize:"13px"}); - list.appendChild(empty); + function openThemeEditor(theme){ + editingTheme = theme; + let panel = document.getElementById('avia-theme-editor'); + if(panel){ + panel.style.display="flex"; + panel.querySelector("textarea").value = theme.css; return; } + panel=document.createElement("div"); + panel.id="avia-theme-editor"; + Object.assign(panel.style,{ + position:"fixed", + bottom:"24px", + right:"24px", + width:"420px", + height:"340px", + background:"var(--md-sys-color-surface,#1e1e1e)", + color:"var(--md-sys-color-on-surface,#fff)", + borderRadius:"16px", + boxShadow:"0 8px 28px rgba(0,0,0,0.35)", + zIndex:999999, + display:"flex", + flexDirection:"column", + overflow:"hidden", + border:"1px solid rgba(255,255,255,0.08)", + backdropFilter:"blur(12px)" + }); + const header=document.createElement("div"); + header.textContent="Theme Editor"; + Object.assign(header.style,{ + padding:"14px 16px", + fontWeight:"600", + fontSize:"14px", + background:"var(--md-sys-color-surface-container,rgba(255,255,255,0.04))", + borderBottom:"1px solid rgba(255,255,255,0.08)", + cursor:"move" + }); + makeDraggable(panel,header); + const close=document.createElement("div"); + close.textContent="✕"; + Object.assign(close.style,{ + position:"absolute", + right:"16px", + top:"12px", + cursor:"pointer", + opacity:"0.6", + fontSize:"15px", + lineHeight:"1", + padding:"2px 4px" + }); + close.onmouseenter=()=>close.style.opacity="1"; + close.onmouseleave=()=>close.style.opacity="0.6"; + close.onclick=()=>panel.style.display="none"; + const textarea=document.createElement("textarea"); + Object.assign(textarea.style,{ + flex:"1", + border:"none", + outline:"none", + resize:"none", + padding:"16px", + background:"transparent", + color:"inherit", + fontFamily:"monospace", + fontSize:"13px" + }); + textarea.value=theme.css; + textarea.addEventListener("input",()=>{ + const themes=getThemes(); + const t=themes.find(x=>x.id===editingTheme.id); + if(!t) return; + t.css=textarea.value; + setThemes(themes); + applyThemes(); + if(window.__avia_refresh_themes_panel){window.__avia_refresh_themes_panel();} + }); + panel.appendChild(header); + panel.appendChild(close); + panel.appendChild(textarea); + document.body.appendChild(panel); + } - themes.forEach(theme=>{ - const meta=parseMeta(theme.css); + function toggleThemesPanel(){ + let panel=document.getElementById("avia-themes-panel"); + if(panel){ + panel.style.display = panel.style.display==="none"?"flex":"none"; + return; + } + panel=document.createElement("div"); + panel.id="avia-themes-panel"; + Object.assign(panel.style,{ + position:"fixed", + bottom:"40px", + right:"40px", + width:"500px", + height:"460px", + background:"var(--md-sys-color-surface,#1e1e1e)", + color:"var(--md-sys-color-on-surface,#fff)", + borderRadius:"16px", + boxShadow:"0 8px 28px rgba(0,0,0,0.35)", + zIndex:999999, + display:"flex", + flexDirection:"column", + overflow:"hidden", + border:"1px solid rgba(255,255,255,0.08)", + backdropFilter:"blur(12px)" + }); - const card=document.createElement("div"); - Object.assign(card.style,{ - display:"flex", - justifyContent:"space-between", - alignItems:"center", - padding:"10px 12px", - borderRadius:"10px", - background:"rgba(255,255,255,0.04)", - border:"1px solid rgba(255,255,255,0.06)", - marginBottom:"0" + const header=document.createElement("div"); + header.textContent="Themes"; + Object.assign(header.style,{ + padding:"14px 16px", + fontWeight:"600", + fontSize:"14px", + background:"var(--md-sys-color-surface-container,rgba(255,255,255,0.04))", + borderBottom:"1px solid rgba(255,255,255,0.08)", + cursor:"move" + }); + makeDraggable(panel,header); + + const close=document.createElement("div"); + close.textContent="✕"; + Object.assign(close.style,{ + position:"absolute", + right:"16px", + top:"12px", + cursor:"pointer", + opacity:"0.6", + fontSize:"15px", + lineHeight:"1", + padding:"2px 4px" + }); + close.onmouseenter=()=>close.style.opacity="1"; + close.onmouseleave=()=>close.style.opacity="0.6"; + close.onclick=()=>panel.style.display="none"; + + const btnRow=document.createElement("div"); + Object.assign(btnRow.style,{ + display:"flex", + gap:"8px", + padding:"12px 16px", + borderBottom:"1px solid rgba(255,255,255,0.08)", + flex:"0 0 auto" + }); + + const importBtn=document.createElement("button"); + importBtn.textContent="Import Theme"; + styleBtn(importBtn); + importBtn.style.flex="1"; + importBtn.style.padding="8px 12px"; + + const newBtn=document.createElement("button"); + newBtn.textContent="+ New"; + styleBtn(newBtn); + newBtn.style.flex="1"; + newBtn.style.padding="8px 12px"; + + btnRow.appendChild(importBtn); + btnRow.appendChild(newBtn); + + const list=document.createElement("div"); + Object.assign(list.style,{ + flex:"1", + overflowY:"auto", + padding:"16px", + display:"flex", + flexDirection:"column", + gap:"8px" + }); + + panel.appendChild(header); + panel.appendChild(close); + panel.appendChild(btnRow); + panel.appendChild(list); + document.body.appendChild(panel); + + function render(){ + list.innerHTML=""; + const themes=getThemes(); + + if(themes.length === 0){ + const empty=document.createElement("div"); + empty.textContent="No themes yet. Import or create one above."; + Object.assign(empty.style,{opacity:"0.4",fontSize:"13px"}); + list.appendChild(empty); + return; + } + + themes.forEach(theme=>{ + const meta=parseMeta(theme.css); + + const card=document.createElement("div"); + Object.assign(card.style,{ + display:"flex", + justifyContent:"space-between", + alignItems:"center", + padding:"10px 12px", + borderRadius:"10px", + background:"rgba(255,255,255,0.04)", + border:"1px solid rgba(255,255,255,0.06)", + marginBottom:"0" + }); + + const left=document.createElement("div"); + Object.assign(left.style,{display:"flex",alignItems:"center",gap:"10px"}); + + const dot=document.createElement("div"); + Object.assign(dot.style,{ + width:"10px", + height:"10px", + borderRadius:"50%", + flexShrink:"0", + background: theme.enabled ? "#4dff88" : "#777", + boxShadow: theme.enabled ? "0 0 6px #4dff88" : "none" + }); + + const info=document.createElement("div"); + info.innerHTML=`
${meta.name}
${meta.author} • v${meta.version}
${meta.description}
`; + + left.appendChild(dot); + left.appendChild(info); + + const controls=document.createElement("div"); + Object.assign(controls.style,{display:"flex",gap:"6px"}); + + const toggle=document.createElement("button"); + toggle.textContent=theme.enabled?"Disable":"Enable"; + styleBtn(toggle); + toggle.onclick=()=>{ + theme.enabled=!theme.enabled; + setThemes(themes); + applyThemes(); + render(); + }; + + const edit=document.createElement("button"); + edit.textContent="Edit"; + styleBtn(edit, "rgba(100,160,255,0.15)"); + edit.onclick=()=>openThemeEditor(theme); + + const del=document.createElement("button"); + del.textContent="✕"; + styleBtn(del, "rgba(255,80,80,0.15)"); + del.onclick=()=>{ + const updated=themes.filter(t=>t.id!==theme.id); + setThemes(updated); + applyThemes(); + render(); + }; + + controls.appendChild(toggle); + controls.appendChild(edit); + controls.appendChild(del); + card.appendChild(left); + card.appendChild(controls); + list.appendChild(card); }); + } - const left=document.createElement("div"); - Object.assign(left.style,{display:"flex",alignItems:"center",gap:"10px"}); + window.__avia_refresh_themes_panel = render; - const dot=document.createElement("div"); - Object.assign(dot.style,{ - width:"10px", - height:"10px", - borderRadius:"50%", - flexShrink:"0", - background: theme.enabled ? "#4dff88" : "#777", - boxShadow: theme.enabled ? "0 0 6px #4dff88" : "none" - }); - - const info=document.createElement("div"); - info.innerHTML=`
${meta.name}
${meta.author} • v${meta.version}
${meta.description}
`; - - left.appendChild(dot); - left.appendChild(info); - - const controls=document.createElement("div"); - Object.assign(controls.style,{display:"flex",gap:"6px"}); - - const toggle=document.createElement("button"); - toggle.textContent=theme.enabled?"Disable":"Enable"; - styleBtn(toggle); - toggle.onclick=()=>{ - theme.enabled=!theme.enabled; + importBtn.onclick=()=>{ + const input=document.createElement("input"); + input.type="file"; + input.accept=".css,.txt"; + input.onchange=async()=>{ + const file=input.files[0]; + if(!file) return; + const css=await file.text(); + const themes=getThemes(); + themes.push({id:crypto.randomUUID(),css,enabled:true}); setThemes(themes); applyThemes(); render(); }; + input.click(); + }; - const edit=document.createElement("button"); - edit.textContent="Edit"; - styleBtn(edit, "rgba(100,160,255,0.15)"); - edit.onclick=()=>openThemeEditor(theme); - - const del=document.createElement("button"); - del.textContent="✕"; - styleBtn(del, "rgba(255,80,80,0.15)"); - del.onclick=()=>{ - const updated=themes.filter(t=>t.id!==theme.id); - setThemes(updated); - applyThemes(); - render(); - }; - - controls.appendChild(toggle); - controls.appendChild(edit); - controls.appendChild(del); - card.appendChild(left); - card.appendChild(controls); - list.appendChild(card); - }); - } - - window.__avia_refresh_themes_panel = render; - - importBtn.onclick=()=>{ - const input=document.createElement("input"); - input.type="file"; - input.accept=".css,.txt"; - input.onchange=async()=>{ - const file=input.files[0]; - if(!file) return; - const css=await file.text(); + newBtn.onclick=()=>{ const themes=getThemes(); - themes.push({id:crypto.randomUUID(),css,enabled:true}); + themes.push({id:crypto.randomUUID(),css:TEMPLATE,enabled:true}); setThemes(themes); applyThemes(); render(); }; - input.click(); - }; - newBtn.onclick=()=>{ - const themes=getThemes(); - themes.push({id:crypto.randomUUID(),css:TEMPLATE,enabled:true}); - setThemes(themes); - applyThemes(); render(); - }; + } - render(); -} + function injectButton(){ + if(document.getElementById("avia-themes-btn")) return; + const appearanceBtn=[...document.querySelectorAll("a")].find(a=>a.textContent.trim()==="Appearance"); + const quickCSS=document.getElementById("stoat-fake-quickcss"); + if(!appearanceBtn || !quickCSS) return; + const clone=appearanceBtn.cloneNode(true); + clone.id="avia-themes-btn"; + const text=[...clone.querySelectorAll("div")].find(d=>d.children.length===0); + if(text) text.textContent="(Avia) Themes"; + clone.onclick=toggleThemesPanel; + quickCSS.parentElement.insertBefore(clone, quickCSS.nextSibling); + } -function injectButton(){ - if(document.getElementById("avia-themes-btn")) return; - const appearanceBtn=[...document.querySelectorAll("a")].find(a=>a.textContent.trim()==="Appearance"); - const quickCSS=document.getElementById("stoat-fake-quickcss"); - if(!appearanceBtn || !quickCSS) return; - const clone=appearanceBtn.cloneNode(true); - clone.id="avia-themes-btn"; - const text=[...clone.querySelectorAll("div")].find(d=>d.children.length===0); - if(text) text.textContent="(Avia) Themes"; - clone.onclick=toggleThemesPanel; - quickCSS.parentElement.insertBefore(clone, quickCSS.nextSibling); -} - -new MutationObserver(injectButton).observe(document.body,{childList:true,subtree:true}); -injectButton(); -applyThemes(); + new MutationObserver(injectButton).observe(document.body,{childList:true,subtree:true}); + injectButton(); + applyThemes(); })();