Enhance popup and HUD functionality: add clear archive and whitelist buttons, improve styling and layout
This commit is contained in:
parent
49bbce95ea
commit
88abb559d1
113
content.js
113
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();
|
||||
|
||||
@ -39,6 +39,9 @@
|
||||
<input id="maxInput" type="number" placeholder="Max archived (-1 = unlimited)" />
|
||||
<button id="saveMaxBtn">Save max</button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button id="clearArchiveBtn" class="ghost">Clear archive</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- Settings -->
|
||||
@ -64,6 +67,9 @@
|
||||
<details class="section" open>
|
||||
<summary>Whitelisted creators</summary>
|
||||
<ul id="channelList"></ul>
|
||||
<div class="row">
|
||||
<button id="clearWhitelistBtn" class="ghost">Clear whitelist</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="section explain">
|
||||
|
||||
12
popup.js
12
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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user