diff --git a/content.js b/content.js index 14b3bcc..e167c8a 100644 --- a/content.js +++ b/content.js @@ -69,13 +69,13 @@ function injectStyleOnce() { width: 520px; height: 520px; overflow: auto; - padding: 10px; - border-radius: 10px; - border: 1px solid #b04a00; - background: #fff6e8; - color: #2b2014; + padding: 0; + border-radius: 12px; + border: 1px solid #9b3b0c; + background: radial-gradient(circle at 20% 10%, #2b2b2b, #151515 60%); + color: #f5efe6; font-size: 12px; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); + box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35); z-index: 2147483647; } #${HUD_PANEL_ID}[data-${DATA_PREFIX}-hidden="true"] { @@ -83,17 +83,24 @@ function injectStyleOnce() { } .${DATA_PREFIX}-hud-title { font-weight: 700; - margin: 0 0 8px; + margin: 0; + padding: 12px 14px; text-transform: uppercase; - font-size: 11px; - letter-spacing: 0.4px; + font-size: 12px; + letter-spacing: 0.6px; + background: linear-gradient(90deg, #e35b14, #c9490e); + border-bottom: 2px solid #b2410e; + color: #fff8ee; + } + .${DATA_PREFIX}-hud-body { + padding: 10px 12px 14px; } .${DATA_PREFIX}-channel { - margin: 6px 0; + margin: 8px 0; padding: 6px 8px; - border-radius: 8px; - background: #fffaf0; - border: 1px solid #e2d7be; + border-radius: 10px; + background: rgba(15, 15, 15, 0.55); + border: 1px solid #2a2a2a; } .${DATA_PREFIX}-channel-header { display: flex; @@ -102,6 +109,10 @@ function injectStyleOnce() { gap: 8px; cursor: pointer; font-weight: 700; + color: #ffd8b0; + text-transform: uppercase; + letter-spacing: 0.5px; + font-size: 11px; } .${DATA_PREFIX}-channel-header::before { content: "▸"; @@ -115,7 +126,7 @@ function injectStyleOnce() { .${DATA_PREFIX}-video-list { margin: 6px 0 0; padding-left: 18px; - border-left: 2px solid #f0d8b4; + border-left: 2px solid #3a2c22; } .${DATA_PREFIX}-hud-item { display: grid; @@ -125,21 +136,35 @@ function injectStyleOnce() { margin: 6px 0; padding: 6px; border-radius: 8px; - background: #fffaf0; - border: 1px solid #e2d7be; + background: #232323; + border: 1px solid #3a2c22; } .${DATA_PREFIX}-hud-thumb { width: 64px; height: 36px; object-fit: cover; border-radius: 4px; - background: #eee2cc; + background: #2a2a2a; } .${DATA_PREFIX}-hud-link { - color: #5a2b00; + color: #ffb26a; text-decoration: none; font-weight: 700; } + .${DATA_PREFIX}-hud-actions { + display: flex; + justify-content: flex-end; + margin-bottom: 8px; + } + .${DATA_PREFIX}-hud-clear { + padding: 6px 10px; + border: 1px solid #4a3a2a; + border-radius: 8px; + background: transparent; + color: #f5efe6; + font-size: 11px; + cursor: pointer; + } .${DATA_PREFIX}-hud-link:hover { text-decoration: underline; } @@ -244,11 +269,26 @@ function process(root = document) { if (!video) return; - const titleEl = video.querySelector("#video-title"); - const title = titleEl?.textContent?.trim() ?? "(no title)"; - const url = titleEl?.href ?? ""; - const thumbImg = video.querySelector("ytd-thumbnail img"); + const linkEl = + video.querySelector('a[href^="/watch"]') || + video.querySelector("#video-title-link") || + video.querySelector("#video-title"); + const title = + linkEl?.getAttribute("title") || + linkEl?.textContent?.trim() || + "(no title)"; + const rawUrl = linkEl?.getAttribute("href") || ""; + const url = rawUrl.startsWith("http") + ? rawUrl + : rawUrl + ? new URL(rawUrl, location.origin).toString() + : ""; + const thumbImg = + video.querySelector("ytd-thumbnail img") || + video.querySelector("yt-img-shadow img") || + video.querySelector("img#img"); const thumb = + thumbImg?.currentSrc || thumbImg?.getAttribute("src") || thumbImg?.getAttribute("data-thumb") || thumbImg?.getAttribute("data-src") || @@ -278,6 +318,13 @@ function process(root = document) { thumb }); hudDirty = true; + } else { + // Fill missing metadata as it becomes available. + if (!existing.title && title) existing.title = title; + if (!existing.url && url) existing.url = url; + if (!existing.thumb && thumb) existing.thumb = thumb; + if (!existing.channelLabel && channel) existing.channelLabel = channel; + if (!existing.channelUrl && channelUrl) existing.channelUrl = channelUrl; } } @@ -548,6 +595,19 @@ function renderHudPanel(panel) { title.textContent = "Hidden member-only videos"; panel.appendChild(title); + const body = document.createElement("div"); + body.className = `${DATA_PREFIX}-hud-body`; + panel.appendChild(body); + + const actions = document.createElement("div"); + actions.className = `${DATA_PREFIX}-hud-actions`; + const clearBtn = document.createElement("button"); + clearBtn.className = `${DATA_PREFIX}-hud-clear`; + clearBtn.textContent = "Clear archive"; + clearBtn.addEventListener("click", () => clearArchive()); + actions.appendChild(clearBtn); + body.appendChild(actions); + const groups = new Map(); for (const meta of sharedIndex.values()) { if (!meta.hidden) continue; @@ -563,7 +623,7 @@ function renderHudPanel(panel) { if (groups.size === 0) { const empty = document.createElement("div"); empty.textContent = "No hidden member-only videos."; - panel.appendChild(empty); + body.appendChild(empty); return; } @@ -604,11 +664,16 @@ function renderHudPanel(panel) { list.appendChild(item); }); - panel.appendChild(details); + body.appendChild(details); details.appendChild(list); } } +function clearArchive() { + sharedIndex.clear(); + chrome.storage.local.set({ [STORAGE_KEY]: [] }, () => updateHudDot()); +} + /* ---------------- initial + observer ---------------- */ process(); diff --git a/popup.html b/popup.html index fe98ba7..e062510 100644 --- a/popup.html +++ b/popup.html @@ -33,13 +33,16 @@
-
- Archive settings -
- - -
-
+
+ Archive settings +
+ + +
+
+ +
+
@@ -61,10 +64,13 @@

-
- Whitelisted creators - -
+
+ Whitelisted creators + +
+ +
+
For non-technical users
diff --git a/popup.js b/popup.js index 5e8e67f..792ace6 100644 --- a/popup.js +++ b/popup.js @@ -5,6 +5,8 @@ const addBtn = document.getElementById("addBtn"); const maxInput = document.getElementById("maxInput"); const saveMaxBtn = document.getElementById("saveMaxBtn"); const addError = document.getElementById("addError"); +const clearArchiveBtn = document.getElementById("clearArchiveBtn"); +const clearWhitelistBtn = document.getElementById("clearWhitelistBtn"); const list = document.getElementById("channelList"); const debugToggle = document.getElementById("debugToggle"); const resetBtn = document.getElementById("resetBtn"); @@ -110,9 +112,19 @@ function saveMaxArchive() { chrome.storage.local.set({ maxArchive: value }, loadChannels); } +function clearArchive() { + chrome.storage.local.set({ memberOnlyHidden: [] }, loadChannels); +} + +function clearWhitelist() { + chrome.storage.local.set({ whitelist: [] }, loadChannels); +} + // Wire UI events. addBtn.onclick = addChannel; saveMaxBtn.onclick = saveMaxArchive; +clearArchiveBtn.onclick = clearArchive; +clearWhitelistBtn.onclick = clearWhitelist; debugToggle.onchange = e => setDebug(e.target.checked); resetBtn.onclick = resetDefaults; loadChannels();