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;
|
width: 520px;
|
||||||
height: 520px;
|
height: 520px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 10px;
|
padding: 0;
|
||||||
border-radius: 10px;
|
border-radius: 12px;
|
||||||
border: 1px solid #b04a00;
|
border: 1px solid #9b3b0c;
|
||||||
background: #fff6e8;
|
background: radial-gradient(circle at 20% 10%, #2b2b2b, #151515 60%);
|
||||||
color: #2b2014;
|
color: #f5efe6;
|
||||||
font-size: 12px;
|
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;
|
z-index: 2147483647;
|
||||||
}
|
}
|
||||||
#${HUD_PANEL_ID}[data-${DATA_PREFIX}-hidden="true"] {
|
#${HUD_PANEL_ID}[data-${DATA_PREFIX}-hidden="true"] {
|
||||||
@ -83,17 +83,24 @@ function injectStyleOnce() {
|
|||||||
}
|
}
|
||||||
.${DATA_PREFIX}-hud-title {
|
.${DATA_PREFIX}-hud-title {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin: 0 0 8px;
|
margin: 0;
|
||||||
|
padding: 12px 14px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
letter-spacing: 0.4px;
|
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 {
|
.${DATA_PREFIX}-channel {
|
||||||
margin: 6px 0;
|
margin: 8px 0;
|
||||||
padding: 6px 8px;
|
padding: 6px 8px;
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
background: #fffaf0;
|
background: rgba(15, 15, 15, 0.55);
|
||||||
border: 1px solid #e2d7be;
|
border: 1px solid #2a2a2a;
|
||||||
}
|
}
|
||||||
.${DATA_PREFIX}-channel-header {
|
.${DATA_PREFIX}-channel-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -102,6 +109,10 @@ function injectStyleOnce() {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
color: #ffd8b0;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
.${DATA_PREFIX}-channel-header::before {
|
.${DATA_PREFIX}-channel-header::before {
|
||||||
content: "▸";
|
content: "▸";
|
||||||
@ -115,7 +126,7 @@ function injectStyleOnce() {
|
|||||||
.${DATA_PREFIX}-video-list {
|
.${DATA_PREFIX}-video-list {
|
||||||
margin: 6px 0 0;
|
margin: 6px 0 0;
|
||||||
padding-left: 18px;
|
padding-left: 18px;
|
||||||
border-left: 2px solid #f0d8b4;
|
border-left: 2px solid #3a2c22;
|
||||||
}
|
}
|
||||||
.${DATA_PREFIX}-hud-item {
|
.${DATA_PREFIX}-hud-item {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -125,21 +136,35 @@ function injectStyleOnce() {
|
|||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #fffaf0;
|
background: #232323;
|
||||||
border: 1px solid #e2d7be;
|
border: 1px solid #3a2c22;
|
||||||
}
|
}
|
||||||
.${DATA_PREFIX}-hud-thumb {
|
.${DATA_PREFIX}-hud-thumb {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #eee2cc;
|
background: #2a2a2a;
|
||||||
}
|
}
|
||||||
.${DATA_PREFIX}-hud-link {
|
.${DATA_PREFIX}-hud-link {
|
||||||
color: #5a2b00;
|
color: #ffb26a;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: 700;
|
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 {
|
.${DATA_PREFIX}-hud-link:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
@ -244,11 +269,26 @@ function process(root = document) {
|
|||||||
|
|
||||||
if (!video) return;
|
if (!video) return;
|
||||||
|
|
||||||
const titleEl = video.querySelector("#video-title");
|
const linkEl =
|
||||||
const title = titleEl?.textContent?.trim() ?? "(no title)";
|
video.querySelector('a[href^="/watch"]') ||
|
||||||
const url = titleEl?.href ?? "";
|
video.querySelector("#video-title-link") ||
|
||||||
const thumbImg = video.querySelector("ytd-thumbnail img");
|
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 =
|
const thumb =
|
||||||
|
thumbImg?.currentSrc ||
|
||||||
thumbImg?.getAttribute("src") ||
|
thumbImg?.getAttribute("src") ||
|
||||||
thumbImg?.getAttribute("data-thumb") ||
|
thumbImg?.getAttribute("data-thumb") ||
|
||||||
thumbImg?.getAttribute("data-src") ||
|
thumbImg?.getAttribute("data-src") ||
|
||||||
@ -278,6 +318,13 @@ function process(root = document) {
|
|||||||
thumb
|
thumb
|
||||||
});
|
});
|
||||||
hudDirty = true;
|
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";
|
title.textContent = "Hidden member-only videos";
|
||||||
panel.appendChild(title);
|
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();
|
const groups = new Map();
|
||||||
for (const meta of sharedIndex.values()) {
|
for (const meta of sharedIndex.values()) {
|
||||||
if (!meta.hidden) continue;
|
if (!meta.hidden) continue;
|
||||||
@ -563,7 +623,7 @@ function renderHudPanel(panel) {
|
|||||||
if (groups.size === 0) {
|
if (groups.size === 0) {
|
||||||
const empty = document.createElement("div");
|
const empty = document.createElement("div");
|
||||||
empty.textContent = "No hidden member-only videos.";
|
empty.textContent = "No hidden member-only videos.";
|
||||||
panel.appendChild(empty);
|
body.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,11 +664,16 @@ function renderHudPanel(panel) {
|
|||||||
list.appendChild(item);
|
list.appendChild(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.appendChild(details);
|
body.appendChild(details);
|
||||||
details.appendChild(list);
|
details.appendChild(list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearArchive() {
|
||||||
|
sharedIndex.clear();
|
||||||
|
chrome.storage.local.set({ [STORAGE_KEY]: [] }, () => updateHudDot());
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------- initial + observer ---------------- */
|
/* ---------------- initial + observer ---------------- */
|
||||||
|
|
||||||
process();
|
process();
|
||||||
|
|||||||
@ -39,6 +39,9 @@
|
|||||||
<input id="maxInput" type="number" placeholder="Max archived (-1 = unlimited)" />
|
<input id="maxInput" type="number" placeholder="Max archived (-1 = unlimited)" />
|
||||||
<button id="saveMaxBtn">Save max</button>
|
<button id="saveMaxBtn">Save max</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<button id="clearArchiveBtn" class="ghost">Clear archive</button>
|
||||||
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
@ -64,6 +67,9 @@
|
|||||||
<details class="section" open>
|
<details class="section" open>
|
||||||
<summary>Whitelisted creators</summary>
|
<summary>Whitelisted creators</summary>
|
||||||
<ul id="channelList"></ul>
|
<ul id="channelList"></ul>
|
||||||
|
<div class="row">
|
||||||
|
<button id="clearWhitelistBtn" class="ghost">Clear whitelist</button>
|
||||||
|
</div>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div class="section explain">
|
<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 maxInput = document.getElementById("maxInput");
|
||||||
const saveMaxBtn = document.getElementById("saveMaxBtn");
|
const saveMaxBtn = document.getElementById("saveMaxBtn");
|
||||||
const addError = document.getElementById("addError");
|
const addError = document.getElementById("addError");
|
||||||
|
const clearArchiveBtn = document.getElementById("clearArchiveBtn");
|
||||||
|
const clearWhitelistBtn = document.getElementById("clearWhitelistBtn");
|
||||||
const list = document.getElementById("channelList");
|
const list = document.getElementById("channelList");
|
||||||
const debugToggle = document.getElementById("debugToggle");
|
const debugToggle = document.getElementById("debugToggle");
|
||||||
const resetBtn = document.getElementById("resetBtn");
|
const resetBtn = document.getElementById("resetBtn");
|
||||||
@ -110,9 +112,19 @@ function saveMaxArchive() {
|
|||||||
chrome.storage.local.set({ maxArchive: value }, loadChannels);
|
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.
|
// Wire UI events.
|
||||||
addBtn.onclick = addChannel;
|
addBtn.onclick = addChannel;
|
||||||
saveMaxBtn.onclick = saveMaxArchive;
|
saveMaxBtn.onclick = saveMaxArchive;
|
||||||
|
clearArchiveBtn.onclick = clearArchive;
|
||||||
|
clearWhitelistBtn.onclick = clearWhitelist;
|
||||||
debugToggle.onchange = e => setDebug(e.target.checked);
|
debugToggle.onchange = e => setDebug(e.target.checked);
|
||||||
resetBtn.onclick = resetDefaults;
|
resetBtn.onclick = resetDefaults;
|
||||||
loadChannels();
|
loadChannels();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user