From fc3e6685042ee1476877a807f8f788230df8acd4 Mon Sep 17 00:00:00 2001 From: type-two Date: Wed, 8 Jul 2026 09:22:06 +1000 Subject: [PATCH] feat: Prompt Mode / DL Mode split in the popup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DL Mode button: one click harvests everything on screen (click ⋮ -> hover Download -> click 1K, verified per tile), click again to stop after current tile; no queue involved, no server reporting for manual runs - Prompt Mode = the existing queue runner, relabelled - harvestActive synced to storage so the popup button reflects state Co-Authored-By: Claude Fable 5 --- content.js | 28 ++++++++++++++++++++++++---- popup.html | 7 ++++--- popup.js | 25 +++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/content.js b/content.js index 0ce71cb..bb9101b 100644 --- a/content.js +++ b/content.js @@ -551,8 +551,26 @@ function findMenuItem(re) { return leaf.length ? (leaf[0].closest('[role="menuitem"], li, button') || leaf[0]) : null; } +let harvestAbort = false; + +// DL Mode from the popup: harvest what's on screen right now, no queue involved. +chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { + if (msg.type === 'startHarvest') { + if (generationInProgress) { log('info', 'DL mode: busy with a task — stop Prompt Mode first.'); sendResponse({ ok: false }); return; } + log('system', 'DL mode ON: downloading everything on screen (1K originals)…'); + executeHarvest({ id: 'manual_' + Date.now(), kind: 'harvest', category: 'harvest', manual: true }); + sendResponse({ ok: true }); + } else if (msg.type === 'stopHarvest') { + harvestAbort = true; + log('system', 'DL mode: stopping after the current tile…'); + sendResponse({ ok: true }); + } +}); + async function executeHarvest(task) { generationInProgress = true; + harvestAbort = false; + chrome.storage.local.set({ harvestActive: true, status: 'working' }); let got = 0, missed = 0, skipped = 0; try { await waitForAgentReady(30000); @@ -561,7 +579,7 @@ async function executeHarvest(task) { await bg({ type: 'harvestRouting', on: true }); window.scrollTo(0, 0); await sleep(800); let idle = 0; - while (idle < 3 && got + missed < 500) { + while (idle < 3 && !harvestAbort && got + missed < 500) { const tile = [...document.querySelectorAll('a[href*="/edit/"]')] .find(t => visible(t) && !seen.has(t.href.split('#')[0])); if (!tile) { // nothing new in view — page down (grid may virtualize) @@ -614,13 +632,15 @@ async function executeHarvest(task) { await bg({ type: 'pressEscape' }); await sleep(300); // ensure menus are closed before the next tile await sleep(1200 + Math.random() * 1200); // pace — don't machine-gun the account } - log('success', `Harvest pass done: ${got} downloaded, ${missed} missed, ${skipped} skipped → Downloads/flowrinse/harvest/`); - await reportCompletion(task.id, 'success', null, [`downloaded:${got}`, `missed:${missed}`]); + log('success', `Harvest ${harvestAbort ? 'stopped' : 'done'}: ${got} downloaded, ${missed} missed → flowrinse/harvest/ under the browser download dir.`); + if (!task.manual) await reportCompletion(task.id, 'success', null, [`downloaded:${got}`, `missed:${missed}`]); } catch (err) { log('error', `Harvest pass failed after ${got}: ${err.message}`); - await reportCompletion(task.id, 'failed', err.message, [`downloaded:${got}`]); + if (!task.manual) await reportCompletion(task.id, 'failed', err.message, [`downloaded:${got}`]); } finally { await bg({ type: 'harvestRouting', on: false }); + harvestAbort = false; + chrome.storage.local.set({ harvestActive: false, status: settings.isRunning ? 'running' : 'idle' }); window.scrollTo(0, 0); generationInProgress = false; scheduleNext(); diff --git a/popup.html b/popup.html index 7cb60df..50dd613 100644 --- a/popup.html +++ b/popup.html @@ -32,9 +32,10 @@ - -
- + +
+ +