- Content script: base href check via absolute URL; scope to listing container - Popup: fallback to background-assisted collection when no receiver exists - Background: expose collect.fromTab to run injection + collection - Add debug logging for visibility
		
			
				
	
	
		
			145 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { applyFilters } from "../lib/filters.js";
 | 
						|
 | 
						|
const els = {
 | 
						|
  fType: document.getElementById('f-type'),
 | 
						|
  fTypeRe: document.getElementById('f-type-re'),
 | 
						|
  fName: document.getElementById('f-name'),
 | 
						|
  fNameRe: document.getElementById('f-name-re'),
 | 
						|
  fSizeMin: document.getElementById('f-size-min'),
 | 
						|
  fSizeMax: document.getElementById('f-size-max'),
 | 
						|
  fDateFrom: document.getElementById('f-date-from'),
 | 
						|
  fDateTo: document.getElementById('f-date-to'),
 | 
						|
  fCase: document.getElementById('f-case'),
 | 
						|
  btnRefresh: document.getElementById('btn-refresh'),
 | 
						|
  btnCopy: document.getElementById('btn-copy'),
 | 
						|
  btnSend: document.getElementById('btn-send'),
 | 
						|
  rpcEndpoint: document.getElementById('rpc-endpoint'),
 | 
						|
  rpcSecret: document.getElementById('rpc-secret'),
 | 
						|
  count: document.getElementById('count'),
 | 
						|
  status: document.getElementById('status'),
 | 
						|
  openOptions: document.getElementById('open-options'),
 | 
						|
  preview: document.getElementById('preview'),
 | 
						|
};
 | 
						|
 | 
						|
let allItems = [];
 | 
						|
 | 
						|
function getFilters() {
 | 
						|
  return {
 | 
						|
    type: els.fType.value,
 | 
						|
    name: els.fName.value,
 | 
						|
    typeRegex: els.fTypeRe.checked,
 | 
						|
    nameRegex: els.fNameRe.checked,
 | 
						|
    sizeMin: els.fSizeMin.value,
 | 
						|
    sizeMax: els.fSizeMax.value,
 | 
						|
    dateFrom: els.fDateFrom.value,
 | 
						|
    dateTo: els.fDateTo.value,
 | 
						|
    caseSensitive: els.fCase.checked,
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
async function getActiveTabId() {
 | 
						|
  const tabs = await browser.tabs.query({ active: true, currentWindow: true });
 | 
						|
  return tabs[0]?.id;
 | 
						|
}
 | 
						|
 | 
						|
async function refresh() {
 | 
						|
  els.status.textContent = '';
 | 
						|
  try {
 | 
						|
    const tabId = await getActiveTabId();
 | 
						|
    if (!tabId) throw new Error('No active tab');
 | 
						|
    let items = [];
 | 
						|
    try {
 | 
						|
      items = await browser.tabs.sendMessage(tabId, { type: 'collectLinks' });
 | 
						|
    } catch (e) {
 | 
						|
      // Fallback: ask background to inject and collect
 | 
						|
      const res = await browser.runtime.sendMessage({ type: 'collect.fromTab', tabId });
 | 
						|
      if (res?.ok) items = res.items || [];
 | 
						|
      else throw new Error(res?.error || e?.message || 'collect failed');
 | 
						|
    }
 | 
						|
    allItems = items || [];
 | 
						|
    updateCount();
 | 
						|
  } catch (e) {
 | 
						|
    els.status.textContent = String(e?.message || e);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function filtered() {
 | 
						|
  return applyFilters(allItems, getFilters());
 | 
						|
}
 | 
						|
 | 
						|
function updateCount() {
 | 
						|
  els.count.textContent = String(filtered().length);
 | 
						|
  renderPreview();
 | 
						|
}
 | 
						|
 | 
						|
async function copyLinks() {
 | 
						|
  const urls = filtered().map(i => i.url).join('\n');
 | 
						|
  await navigator.clipboard.writeText(urls);
 | 
						|
  els.status.textContent = `Copied ${filtered().length} link(s) to clipboard.`;
 | 
						|
}
 | 
						|
 | 
						|
async function sendToAria2() {
 | 
						|
  const endpoint = els.rpcEndpoint.value.trim();
 | 
						|
  const secret = els.rpcSecret.value.trim();
 | 
						|
  const uris = filtered().map(i => i.url);
 | 
						|
  if (!endpoint) { els.status.textContent = 'Please set aria2 endpoint.'; return; }
 | 
						|
  if (uris.length === 0) { els.status.textContent = 'No links to send.'; return; }
 | 
						|
 | 
						|
  // Persist settings
 | 
						|
  await browser.storage.local.set({ aria2: { endpoint, secret } });
 | 
						|
  els.status.textContent = 'Sending to aria2…';
 | 
						|
 | 
						|
  const res = await browser.runtime.sendMessage({
 | 
						|
    type: 'aria2.send',
 | 
						|
    payload: { endpoint, secret, uris }
 | 
						|
  });
 | 
						|
  if (res?.ok) {
 | 
						|
    els.status.textContent = `Sent ${uris.length} link(s) to aria2.`;
 | 
						|
  } else {
 | 
						|
    els.status.textContent = `Error: ${res?.error || 'unknown'}`;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
async function restoreSettings() {
 | 
						|
  const { aria2 } = await browser.storage.local.get('aria2');
 | 
						|
  if (aria2) {
 | 
						|
    if (aria2.endpoint) els.rpcEndpoint.value = aria2.endpoint;
 | 
						|
    if (aria2.secret) els.rpcSecret.value = aria2.secret;
 | 
						|
  } else {
 | 
						|
    els.rpcEndpoint.value = 'http://localhost:6800/jsonrpc';
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
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
 | 
						|
  ].forEach(el => el.addEventListener('input', updateCount));
 | 
						|
}
 | 
						|
 | 
						|
document.addEventListener('DOMContentLoaded', async () => {
 | 
						|
  wire();
 | 
						|
  await restoreSettings();
 | 
						|
  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);
 | 
						|
  }
 | 
						|
}
 |