diff --git a/src/viewer/index.js b/src/viewer/index.js
index 570132f..b8d8698 100644
--- a/src/viewer/index.js
+++ b/src/viewer/index.js
@@ -4,6 +4,7 @@
*/
const STORAGE_KEY = 'goon_videos';
+const TAGGED_KEY = 'goon_tagged';
const findBtn = document.getElementById('find-btn');
const clearBtn = document.getElementById('clear-btn');
@@ -20,27 +21,30 @@ function setStatus(msg) {
console.log('[goon]', msg);
}
-/** Load the current video list from storage. */
+/** Load the current video list and tags from storage. */
function loadVideos() {
- return chrome.storage.local.get(STORAGE_KEY).then(data => data[STORAGE_KEY] || []);
+ return chrome.storage.local.get([STORAGE_KEY, TAGGED_KEY]).then(data => ({
+ urls: data[STORAGE_KEY] || [],
+ tags: data[TAGGED_KEY] || [],
+ }));
}
-/** Render the video list UI from stored URLs. */
-function renderList(urls) {
+/** Render the video list UI from stored {url, label} objects. */
+function renderList(items) {
listEl.innerHTML = '';
- if (!urls || urls.length === 0) {
+ if (!items || items.length === 0) {
listEl.style.display = 'none';
return;
}
listEl.style.display = 'block';
- for (const url of urls) {
- const item = document.createElement('a');
- item.className = 'video-item';
- item.href = url;
- item.textContent = url;
- item.target = '_blank';
- listEl.appendChild(item);
+ for (const item of items) {
+ const link = document.createElement('a');
+ link.className = 'video-item';
+ link.href = item.url;
+ link.textContent = item.label ? `${item.label}: ${item.url}` : item.url;
+ link.target = '_blank';
+ listEl.appendChild(link);
}
// Copy all URLs button
@@ -48,6 +52,7 @@ function renderList(urls) {
copyBtn.className = 'copy-btn';
copyBtn.textContent = 'Copy All URLs';
copyBtn.addEventListener('click', () => {
+ const urls = items.map(v => v.url);
navigator.clipboard.writeText(urls.join('\n')).then(() => {
copyBtn.textContent = 'Copied!';
setTimeout(() => { copyBtn.textContent = 'Copy All URLs'; }, 1500);
@@ -59,9 +64,10 @@ function renderList(urls) {
/** Show the main button row. */
function showActions() {
btnRow.style.display = 'flex';
- loadVideos().then(urls => {
+ loadVideos().then(({ urls, tags }) => {
if (urls.length > 0) {
- renderList(urls);
+ const items = urls.map((url, i) => ({ url, label: tags[i] }));
+ renderList(items);
setStatus(`Using ${urls.length} video(s) from last search.`);
} else {
setStatus('');
@@ -69,82 +75,85 @@ function showActions() {
});
}
-/* === "Find Videos" — scan the current tab === */
+/* === "Find Videos" — scan up to 4 tabs === */
findBtn.addEventListener('click', async () => {
- setStatus('Scanning current tab…');
+ setStatus('Scanning tabs…');
- const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
- const tab = tabs[0];
- if (!tab || !tab.url) {
- setStatus('Cannot access the current tab.');
+ // Get all tabs in the current window
+ const allTabs = await chrome.tabs.query({ currentWindow: true });
+
+ // Filter out chrome/system pages
+ const validTabs = allTabs.filter(t =>
+ t.url &&
+ !t.url.startsWith('chrome://') &&
+ !t.url.startsWith('chrome-extension://') &&
+ !t.url.startsWith('edge://') &&
+ !t.url.startsWith('about:') &&
+ !t.url.startsWith('view-source:')
+ );
+
+ if (validTabs.length === 0) {
+ setStatus('No browsable tabs found.');
return;
}
- // Skip chrome-internal pages
- if (tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://')
- || tab.url.startsWith('edge://') || tab.url.startsWith('about:')
- || tab.url.startsWith('view-source:')) {
- setStatus('This page cannot be scanned.');
- return;
- }
+ // Limit to 4 tabs
+ const tabsToScan = validTabs.slice(0, 4);
+ setStatus(`Scanning ${tabsToScan.length} tab(s)…`);
try {
- // Check the main frame first, then iframes
- const results = await chrome.scripting.executeScript({
- target: { tabId: tab.id, allFrames: true },
- func: () => {
- // Count both