diff --git a/manifest.json b/manifest.json index 24ccff6..30c8cd2 100644 --- a/manifest.json +++ b/manifest.json @@ -14,7 +14,8 @@ "permissions": [ "storage", "clipboardWrite", - "activeTab" + "activeTab", + "contextMenus" ], "host_permissions": [ "https://archive.org/*", diff --git a/src/background/index.js b/src/background/index.js index 217075e..93cec10 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -17,3 +17,33 @@ browser.runtime.onMessage.addListener(async (msg, sender) => { } }); +// Context menu to collect links on archive.org /download/* pages +browser.runtime.onInstalled.addListener(() => { + try { + browser.contextMenus.create({ + id: 'aolg-collect', + title: 'Collect archive.org links', + contexts: ['page'], + documentUrlPatterns: ['https://archive.org/download/*'] + }); + } catch (e) { + // ignore if already exists or not supported + } +}); + +browser.contextMenus.onClicked.addListener(async (info, tab) => { + if (info.menuItemId !== 'aolg-collect' || !tab?.id) return; + try { + const items = await browser.tabs.sendMessage(tab.id, { type: 'collectLinks' }); + const count = (items || []).length; + await browser.storage.local.set({ + lastCollected: { tabId: tab.id, url: tab.url, time: Date.now(), count }, + lastItems: items + }); + try { await browser.action.setBadgeBackgroundColor({ color: '#3b82f6', tabId: tab.id }); } catch (e) {} + try { await browser.action.setBadgeText({ text: count ? String(count) : '', tabId: tab.id }); } catch (e) {} + try { if (browser.action.openPopup) await browser.action.openPopup(); } catch (e) {} + } catch (e) { + // Swallow errors; context menu is best-effort + } +}); diff --git a/src/popup/index.html b/src/popup/index.html index 52fef09..3dca231 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -32,9 +32,15 @@
0 matches + Options
+
+

Preview

+ +
+

aria2 RPC

@@ -55,4 +61,3 @@ - diff --git a/src/popup/index.js b/src/popup/index.js index 33869c3..201dbcd 100644 --- a/src/popup/index.js +++ b/src/popup/index.js @@ -17,6 +17,8 @@ const els = { rpcSecret: document.getElementById('rpc-secret'), count: document.getElementById('count'), status: document.getElementById('status'), + openOptions: document.getElementById('open-options'), + preview: document.getElementById('preview'), }; let allItems = []; @@ -59,6 +61,7 @@ function filtered() { function updateCount() { els.count.textContent = String(filtered().length); + renderPreview(); } async function copyLinks() { @@ -103,6 +106,7 @@ function wire() { els.btnRefresh.addEventListener('click', refresh); els.btnCopy.addEventListener('click', copyLinks); els.btnSend.addEventListener('click', sendToAria2); + els.openOptions.addEventListener('click', (e) => { e.preventDefault(); browser.runtime.openOptionsPage(); }); [ els.fType, els.fTypeRe, els.fName, els.fNameRe, els.fSizeMin, els.fSizeMax, els.fDateFrom, els.fDateTo, els.fCase @@ -115,3 +119,19 @@ document.addEventListener('DOMContentLoaded', async () => { await refresh(); }); +function renderPreview() { + if (!els.preview) return; + const items = filtered(); + const max = 50; + els.preview.innerHTML = ''; + for (const it of items.slice(0, max)) { + const li = document.createElement('li'); + li.textContent = it.name || it.url; + els.preview.appendChild(li); + } + if (items.length > max) { + const li = document.createElement('li'); + li.textContent = `…and ${items.length - max} more`; + els.preview.appendChild(li); + } +} diff --git a/src/popup/styles.css b/src/popup/styles.css index b010d4b..f659c54 100644 --- a/src/popup/styles.css +++ b/src/popup/styles.css @@ -8,4 +8,7 @@ label input { margin-left: 6px; } button { font-size: 12px; padding: 4px 10px; } #count { font-weight: bold; margin: 0 4px; } #status { font-size: 12px; white-space: pre-wrap; } - +.link { font-size: 12px; margin-left: auto; text-decoration: underline; cursor: pointer; } +.preview ul, #preview { list-style: none; padding: 0; margin: 6px 0; max-height: 160px; overflow: auto; border: 1px solid #ddd; border-radius: 4px; } +#preview li { font-size: 12px; padding: 4px 6px; border-bottom: 1px solid #eee; } +#preview li:last-child { border-bottom: 0; }