d0a2def788
Final options.js split. Three new files:
options-diagnostics.js 245 lines
options-profiles.js 265 lines
options-rules-editors.js 328 lines (adapters + ID normalizers
+ custom part detectors)
options.js: 1852 → 1014 lines (838 extracted, ~45% reduction).
Script-tag order in options.html now (load order matters for
top-level let bindings shared across files, e.g. _configuredScanRoots):
options-cache.js
options-dupe-review.js
options-library-issues.js
options-diagnostics.js
options-profiles.js
options-rules-editors.js
options.js (entry: IIFE bottom, escapeHtml, overlay previews,
element picker, paths)
The picker, overlay-preview, and no-match overlay code stays in
options.js — those are tightly intertwined with multiple settings
panes and not worth further splitting today.
node --check passes on each file individually and on the concatenated
load-order stream. Line count of concat (3144) matches the pre-split
sum exactly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
803 lines
42 KiB
HTML
803 lines
42 KiB
HTML
<!doctype html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>rclone-jav options</title>
|
||
<link rel="stylesheet" href="options.css">
|
||
</head>
|
||
<body>
|
||
<div class="shell">
|
||
<div class="layout">
|
||
|
||
<!-- ============================== SIDEBAR ============================== -->
|
||
<div class="side">
|
||
<div class="brand">
|
||
<strong>rclone-jav</strong>
|
||
<span>Extension settings</span>
|
||
</div>
|
||
<div class="group">
|
||
<div class="gtitle">Scanning</div>
|
||
<div class="item active" data-pane="triggers"><span class="icon">▶</span>Scan Behavior</div>
|
||
<div class="item" data-pane="overlays"><span class="icon">▣</span>Overlays</div>
|
||
</div>
|
||
<div class="group">
|
||
<div class="gtitle">Library</div>
|
||
<div class="item" data-pane="profiles"><span class="icon">☰</span>Profiles</div>
|
||
<div class="item" data-pane="search"><span class="icon">⌕</span>Cache & Scans</div>
|
||
<div class="item" data-pane="maintenance"><span class="icon">≡</span>Library Review</div>
|
||
</div>
|
||
<div class="group">
|
||
<div class="gtitle">Matching</div>
|
||
<div class="item" data-pane="adapters"><span class="icon">⌖</span>Site Extraction</div>
|
||
<div class="item" data-pane="normalizers"><span class="icon">⇄</span>ID Rules</div>
|
||
</div>
|
||
<div class="group">
|
||
<div class="gtitle">System</div>
|
||
<div class="item" data-pane="paths"><span class="icon">⌘</span>Setup</div>
|
||
<div class="item" data-pane="diagnostics"><span class="icon">✓</span>Diagnostics</div>
|
||
<div class="item" data-pane="debug"><span class="icon">⚙</span>Debug Tools</div>
|
||
</div>
|
||
<div class="group">
|
||
<div class="gtitle">Danger</div>
|
||
<div class="item danger" data-pane="deletion"><span class="icon">×</span>Deletion</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============================== MAIN ============================== -->
|
||
<div class="main">
|
||
|
||
<!-- TRIGGERS -->
|
||
<div class="pane active" id="pane-triggers">
|
||
<div class="pane-head">
|
||
<h1>Scan Behavior</h1>
|
||
<div class="pdesc">Choose when rclone-jav checks the current page.</div>
|
||
</div>
|
||
<div id="trigger-summary" class="section-note"></div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Scope</div>
|
||
<div class="setting-list">
|
||
<label><input type="checkbox" id="autoEveryPage"> Auto-check every page load
|
||
<span class="sublabel">Runs on every site. Badge shows "?" when no JAV ID detected.</span></label>
|
||
|
||
<label><input type="checkbox" id="autoKnownSites"> Auto-check on known JAV sites
|
||
<span class="sublabel">Only fires on host patterns listed below.</span></label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Known site patterns</div>
|
||
<div class="help">Comma- or newline-separated. Bare domain matches site + any subdomain (<code>clearjav.com</code> covers <code>www.clearjav.com</code>).</div>
|
||
<textarea id="knownSitePatterns" placeholder="clearjav.com javdb.com" style="resize:none;overflow:hidden;field-sizing:content;min-height:60px;"></textarea>
|
||
<div class="chip-row" style="margin-top:8px;">
|
||
<button id="add-current-site" class="chip-btn" type="button">Add Current Site</button>
|
||
<button id="add-clearjav-site" class="chip-btn" type="button">Add ClearJAV</button>
|
||
<span id="known-site-status" class="muted"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Navigation types</div>
|
||
<div class="setting-list">
|
||
<label><input type="checkbox" id="autoPageLoad"> Full page loads
|
||
<span class="sublabel">Runs when the browser reports the page has finished loading.</span></label>
|
||
<label><input type="checkbox" id="autoSpaNavigation"> SPA and history URL changes
|
||
<span class="sublabel">Runs when a site changes URL without a full reload, including browser back/forward on some sites.</span></label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Manual controls</div>
|
||
<div class="setting-list">
|
||
<label><input type="checkbox" id="toolbarClick"> Toolbar icon popup
|
||
<span class="sublabel">Click the rclone-jav icon to run a check on the active tab.</span></label>
|
||
<label><input type="checkbox" id="contextMenu"> Right-click context menu</label>
|
||
<label><input type="checkbox" id="keyboardShortcut"> Keyboard shortcut (Alt+J)
|
||
<span class="sublabel">Rebind at <code>brave://extensions/shortcuts</code>.</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- OVERLAYS -->
|
||
<div class="pane" id="pane-overlays">
|
||
<div class="pane-head">
|
||
<h1>Overlays</h1>
|
||
<div class="pdesc">In-page toast notifications after auto-trigger scans.</div>
|
||
</div>
|
||
<div id="overlay-summary" class="section-note"></div>
|
||
|
||
<!-- Horizontal tabs -->
|
||
<div class="overlay-tabs">
|
||
<button class="otab active" data-otab="match">✓ Match</button>
|
||
<button class="otab" data-otab="nomatch">✗ No Match</button>
|
||
</div>
|
||
|
||
<!-- MATCH tab -->
|
||
<div class="otab-panel active" id="otab-match">
|
||
<label style="margin-bottom:10px;display:flex;align-items:center;gap:10px;">
|
||
<input type="checkbox" id="showOverlay"> Show overlay on match
|
||
<span class="sublabel" style="margin:0;">Hover to pause countdown. Auto-check only.</span>
|
||
</label>
|
||
|
||
<div class="fieldset">
|
||
<div style="display:flex;gap:14px;align-items:center;flex-wrap:wrap;">
|
||
<div>
|
||
<div style="font-size:11px;color:#888;margin-bottom:4px;">Position</div>
|
||
<div class="radio-group" style="margin:0;">
|
||
<label><input type="radio" name="overlayPosition" value="top-left"> Top-Left</label>
|
||
<label><input type="radio" name="overlayPosition" value="top-right" checked> Top-Right</label>
|
||
<label><input type="radio" name="overlayPosition" value="bottom-left"> Bottom-Left</label>
|
||
<label><input type="radio" name="overlayPosition" value="bottom-right"> Bottom-Right</label>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="font-size:11px;color:#888;margin-bottom:4px;">Duration (sec)</div>
|
||
<input type="number" id="overlayDuration" value="5" min="1" max="60" step="1" style="width:80px;">
|
||
</div>
|
||
</div>
|
||
<label style="margin-top:10px;display:flex;align-items:center;gap:10px;">
|
||
<input type="checkbox" id="overlayGlow"> Subtle glow
|
||
<input type="color" id="overlayGlowColor" value="#6ec1ff" style="width:36px;height:24px;padding:0;cursor:pointer;" title="Glow color">
|
||
</label>
|
||
<div id="glow-detail" style="margin-top:10px;padding:10px;background:#101010;border:1px solid #232323;border-radius:4px;display:grid;grid-template-columns:90px 1fr 50px;gap:8px;align-items:center;font-size:11px;">
|
||
<span style="color:#888;">Blur (soft)</span>
|
||
<input type="range" id="overlayGlowBlur" min="0" max="60" step="1" value="10" style="width:100%;">
|
||
<span id="overlayGlowBlurVal" style="color:#6ec1ff;text-align:right;font-family:Consolas,monospace;">10 px</span>
|
||
<span style="color:#888;">Spread (size)</span>
|
||
<input type="range" id="overlayGlowSpread" min="0" max="40" step="1" value="0" style="width:100%;">
|
||
<span id="overlayGlowSpreadVal" style="color:#6ec1ff;text-align:right;font-family:Consolas,monospace;">0 px</span>
|
||
<span style="color:#888;">Opacity</span>
|
||
<input type="range" id="overlayGlowOpacity" min="0.05" max="1" step="0.05" value="0.35" style="width:100%;">
|
||
<span id="overlayGlowOpacityVal" style="color:#6ec1ff;text-align:right;font-family:Consolas,monospace;">0.35</span>
|
||
</div>
|
||
<div style="margin-top:8px;display:flex;justify-content:flex-end;">
|
||
<button id="overlay-reset" type="button" style="font-size:11px;padding:4px 10px;">Reset</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top:12px;border-top:1px solid #222;padding-top:12px;">
|
||
<div style="font-size:11px;color:#888;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center;">
|
||
<span>Preview <span id="overlay-preview-pos" style="color:#6ec1ff;">— top-right</span></span>
|
||
<button id="overlay-preview-replay" type="button" style="font-size:11px;padding:2px 8px;">Replay</button>
|
||
</div>
|
||
<div id="overlay-preview-stage" style="background:#080808;border:1px dashed #2a2a2a;border-radius:4px;padding:18px;display:flex;justify-content:flex-end;align-items:flex-start;min-height:130px;position:relative;">
|
||
<div id="overlay-preview" style="width:280px;background:#1a1a1a;color:#ddd;border:1px solid #2a2a2a;border-radius:6px;font-size:12px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.55);">
|
||
<div style="padding:6px 10px;background:#1e3a1e;color:#afa;font-weight:600;display:flex;align-items:center;gap:6px;font-size:12px;"><span>✓ IPZZ-860 — 1 hit(s)</span></div>
|
||
<div style="padding:6px;background:#0d0d0d;">
|
||
<div style="background:#161616;border:1px solid #2a2a2a;border-radius:4px;padding:8px 10px;">
|
||
<div style="color:#fff;font-weight:600;font-size:12px;">IPZZ-860 [4K].mkv</div>
|
||
<div style="color:#aaa;font-size:11px;font-family:Consolas,monospace;margin:3px 0;"><span style="color:#555;font-weight:600;">Path:</span> cq:JAV/ClearJAV/...</div>
|
||
<div style="display:flex;align-items:center;gap:8px;font-size:10px;">
|
||
<span style="background:#2a2a1a;color:#ffcc44;padding:1px 6px;border-radius:10px;font-weight:600;letter-spacing:.3px;">TARGET</span>
|
||
<span style="color:#6ec1ff;font-weight:600;">5.93 GiB</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div style="height:3px;background:#222;"><div id="overlay-preview-bar" style="height:100%;background:linear-gradient(90deg,#6ec1ff,#66dd66);transform-origin:left;transform:scaleX(1);"></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- NO MATCH tab -->
|
||
<div class="otab-panel" id="otab-nomatch">
|
||
<label style="margin-bottom:10px;display:flex;align-items:center;gap:10px;">
|
||
<input type="checkbox" id="noMatchOverlay"> Show overlay on no match
|
||
<span class="sublabel" style="margin:0;">Off by default. Auto-check only.</span>
|
||
</label>
|
||
|
||
<div class="fieldset" id="no-match-fieldset">
|
||
<div style="display:flex;gap:14px;align-items:center;flex-wrap:wrap;">
|
||
<div>
|
||
<div style="font-size:11px;color:#888;margin-bottom:4px;">Position</div>
|
||
<div class="radio-group" id="noMatchPositionGroup" style="margin:0;">
|
||
<label><input type="radio" name="noMatchPosition" value="top-left"> Top-Left</label>
|
||
<label><input type="radio" name="noMatchPosition" value="top-right" checked> Top-Right</label>
|
||
<label><input type="radio" name="noMatchPosition" value="bottom-left"> Bottom-Left</label>
|
||
<label><input type="radio" name="noMatchPosition" value="bottom-right"> Bottom-Right</label>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="font-size:11px;color:#888;margin-bottom:4px;">Duration (sec)</div>
|
||
<input type="number" id="noMatchDuration" value="5" min="1" max="60" step="1" style="width:80px;">
|
||
</div>
|
||
</div>
|
||
<label style="margin-top:10px;display:flex;align-items:center;gap:10px;">
|
||
<input type="checkbox" id="noMatchGlow"> Subtle glow
|
||
<input type="color" id="noMatchGlowColor" value="#ff6666" style="width:36px;height:24px;padding:0;cursor:pointer;" title="Glow color">
|
||
</label>
|
||
<div style="margin-top:10px;padding:10px;background:#101010;border:1px solid #232323;border-radius:4px;display:grid;grid-template-columns:90px 1fr 50px;gap:8px;align-items:center;font-size:11px;">
|
||
<span style="color:#888;">Blur (soft)</span>
|
||
<input type="range" id="noMatchGlowBlur" min="0" max="60" step="1" value="10" style="width:100%;">
|
||
<span id="noMatchGlowBlurVal" style="color:#ff6666;text-align:right;font-family:Consolas,monospace;">10 px</span>
|
||
<span style="color:#888;">Spread (size)</span>
|
||
<input type="range" id="noMatchGlowSpread" min="0" max="40" step="1" value="0" style="width:100%;">
|
||
<span id="noMatchGlowSpreadVal" style="color:#ff6666;text-align:right;font-family:Consolas,monospace;">0 px</span>
|
||
<span style="color:#888;">Opacity</span>
|
||
<input type="range" id="noMatchGlowOpacity" min="0.05" max="1" step="0.05" value="0.35" style="width:100%;">
|
||
<span id="noMatchGlowOpacityVal" style="color:#ff6666;text-align:right;font-family:Consolas,monospace;">0.35</span>
|
||
</div>
|
||
<div style="margin-top:8px;display:flex;justify-content:flex-end;">
|
||
<button id="no-match-reset" type="button" style="font-size:11px;padding:4px 10px;">Reset</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="margin-top:12px;border-top:1px solid #222;padding-top:12px;">
|
||
<div style="font-size:11px;color:#888;margin-bottom:8px;display:flex;justify-content:space-between;align-items:center;">
|
||
<span>Preview <span id="no-match-preview-pos" style="color:#ff6666;">— top-right</span></span>
|
||
<button id="no-match-preview-replay" type="button" style="font-size:11px;padding:2px 8px;">Replay</button>
|
||
</div>
|
||
<div id="no-match-preview-stage" style="background:#080808;border:1px dashed #2a2a2a;border-radius:4px;padding:18px;display:flex;justify-content:flex-end;align-items:flex-start;min-height:90px;position:relative;">
|
||
<div id="no-match-preview" style="width:280px;background:#1a1a1a;color:#ddd;border:1px solid #2a2a2a;border-radius:6px;font-size:12px;overflow:hidden;box-shadow:0 6px 20px rgba(0,0,0,.55);">
|
||
<div style="padding:6px 10px;background:#3a1e1e;color:#faa;font-weight:600;font-size:12px;">✗ START-489 — NOT IN LIBRARY</div>
|
||
<div style="padding:8px 12px;background:#0d0d0d;color:#aaa;font-size:11px;font-family:Consolas,monospace;word-break:break-all;"><span style="color:#555;font-weight:600;">Scanned:</span> cq:JAV</div>
|
||
<div style="height:3px;background:#222;"><div id="no-match-preview-bar" style="height:100%;background:linear-gradient(90deg,#ff6666,#ff8c42);transform-origin:left;transform:scaleX(1);"></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- SITE ADAPTERS -->
|
||
<div class="pane" id="pane-adapters">
|
||
<div class="pane-head">
|
||
<h1>Site Extraction</h1>
|
||
<div class="pdesc">For sites where the JAV ID isn't in the page title, point at a DOM element. Selector runs <code>document.querySelector</code> and extracts <code>textContent</code>.</div>
|
||
</div>
|
||
<div id="adapter-summary" class="section-note"></div>
|
||
|
||
<table class="adapters" id="adapters">
|
||
<thead><tr><th>Host pattern</th><th>CSS selector(s)</th><th></th></tr></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
|
||
<div class="fieldset" style="margin-top:12px;">
|
||
<div class="ftitle">Built-in presets</div>
|
||
<div style="font-family:Consolas,monospace;font-size:11px;color:#888;line-height:1.5;word-break:break-all;">
|
||
<div><span style="color:#aaa;">clearjav.com</span> → <code>div.meta-chip > h3.meta-chip__value</code></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="display:flex;gap:8px;margin-top:10px;align-items:center;">
|
||
<button id="add-adapter">+ Add Row</button>
|
||
<button id="pick-element">Pick Element</button>
|
||
<button id="test-active-page">Test Active Page</button>
|
||
<button id="validate-adapters" type="button">Validate Rows</button>
|
||
<span id="picker-status" style="color:#888;font-size:11px;"></span>
|
||
</div>
|
||
|
||
<div id="adapter-test-result" class="fieldset" style="display:none;margin-top:14px;">
|
||
<div class="ftitle">Active page extraction bench</div>
|
||
<div id="adapter-test-output" style="font-family:Consolas,monospace;font-size:11px;color:#aaa;line-height:1.5;word-break:break-all;"></div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ID RULES -->
|
||
<div class="pane" id="pane-normalizers">
|
||
<div class="pane-head">
|
||
<h1>ID Rules</h1>
|
||
<div class="pdesc">Normalize odd IDs and teach rc-jav how multipart filename suffixes should stay distinct.</div>
|
||
</div>
|
||
<div id="normalizer-summary" class="section-note"></div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Built-in ID rules</div>
|
||
<div style="font-size:11px;color:#888;line-height:1.5;">
|
||
<div><code>FC2-?PPV-?(\d{4,})</code> → <code>FC2-PPV-$1</code>
|
||
<span style="color:#666;"> — handles <code>FC2PPV4903171</code>, <code>FC2-PPV4903171</code>, <code>FC2-PPV-4903171</code></span></div>
|
||
<div><code>FC2-(\d{4,})</code> → <code>FC2-PPV-$1</code>
|
||
<span style="color:#666;"> — handles bare site labels like <code>FC2-1841460</code></span></div>
|
||
<div><code>_A</code> / <code>_B</code> multipart suffixes are distinct parts in rc-jav duplicate/cache ID detection.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset" style="margin-top:14px;">
|
||
<div class="ftitle">Test ID extraction</div>
|
||
<div class="help">Paste a page title, DOM text, URL fragment, or filename. Uses the current custom normalizer rows below plus built-in extraction rules.</div>
|
||
<div style="display:grid;grid-template-columns:1fr 120px;gap:8px;align-items:center;">
|
||
<input type="text" id="norm-test-in" placeholder="paste a sample page title or filename">
|
||
<button id="norm-test-run">Test Text</button>
|
||
</div>
|
||
<div id="norm-test-out" style="margin-top:8px;font-family:Consolas,monospace;font-size:12px;color:#aaa;"></div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Custom ID normalizers</div>
|
||
<table class="adapters" id="normalizers">
|
||
<thead><tr><th>Pattern (regex)</th><th>Replacement</th><th></th></tr></thead>
|
||
<tbody></tbody>
|
||
</table>
|
||
|
||
<div style="display:flex;gap:8px;margin-top:10px;align-items:center;">
|
||
<button id="add-normalizer">+ Add Row</button>
|
||
<button id="validate-normalizers" type="button">Validate Regex</button>
|
||
<span id="normalizer-status" class="muted"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Part detectors</div>
|
||
<div class="help">Built-in and custom Python regexes run against the filename stem. Capture group 1 must be the part number or a single part letter. Built-ins are shown here so you can see what is already covered before adding a custom detector.</div>
|
||
<div class="muted" style="margin:0 0 7px;">Built in</div>
|
||
<div id="builtin-part-detectors" class="part-detector-list" style="margin-bottom:12px;"></div>
|
||
<div class="muted" style="margin:0 0 7px;">Custom</div>
|
||
<div id="part-detectors" class="part-detector-list"></div>
|
||
<div class="button-row" style="margin-top:9px;">
|
||
<button id="add-part-detector" type="button">+ Add Detector</button>
|
||
</div>
|
||
<div class="help">Host searches and cache rebuilds receive these saved rules. Direct CLI use can store the same list as <code>part_patterns</code> in <code>config.json</code> or pass repeatable <code>--part-pattern</code>.</div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- CACHE & SCANS -->
|
||
<div class="pane" id="pane-search">
|
||
<div class="pane-head">
|
||
<h1>Cache & Scans</h1>
|
||
<div class="pdesc">Choose lookup mode, inspect cache state, and run cache rebuild jobs.</div>
|
||
</div>
|
||
<div id="search-summary" class="section-note"></div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Lookup mode</div>
|
||
<div class="help">Quick mode bypasses cache and uses <code>rclone --include</code> directly — fastest for single-ID lookups. ~1–2s per call. Disable to use the cache (faster on warm cache, requires <code>--scan</code> to keep fresh).</div>
|
||
<label><input type="checkbox" id="quickMode"> Use --quick mode (live rclone lookup, no cache)</label>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Cache status</div>
|
||
<div class="help">Inspect the current <code>cache.json</code> remotes, scan times, file counts, and skipped filename samples.</div>
|
||
<div class="cache-freshness">
|
||
<label>Stale after
|
||
<input type="number" id="cacheStaleHours" value="24" min="1" max="8760" step="1">
|
||
hours
|
||
</label>
|
||
<span class="sublabel">Used for cache warnings in the extension. Freshness does not change search results.</span>
|
||
</div>
|
||
<div class="button-row">
|
||
<button id="cache-status-run" type="button">Check Cache</button>
|
||
</div>
|
||
<div id="cache-status-results" class="mono-output"></div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Cache rebuild</div>
|
||
<div class="help">Refresh the cache from the configured scan roots. Incremental rebuilds only ask rclone for recently changed files.</div>
|
||
<div class="button-row">
|
||
<select id="cache-rebuild-mode">
|
||
<option value="">Full Rebuild</option>
|
||
<option value="24h">Update last 24h</option>
|
||
<option value="7d">Update last 7d</option>
|
||
</select>
|
||
<button id="cache-rebuild-run" type="button">Rebuild Cache</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Scan job</div>
|
||
<div class="help">Follow the current or last cache scan job and clear old job history after it is no longer useful.</div>
|
||
<div class="button-row">
|
||
<button id="scan-job-clear" type="button" style="margin-left:auto;">Clear Job</button>
|
||
</div>
|
||
<div id="scan-job-results" class="mono-output"></div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- LIBRARY REVIEW -->
|
||
<div class="pane" id="pane-maintenance">
|
||
<div class="pane-head">
|
||
<h1>Library Review</h1>
|
||
<div class="pdesc">Review duplicate groups and fix non-canonical filenames in your library. (Bulk ID Check now opens in its own window from the popup.)</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Duplicate review</div>
|
||
<div class="help">Review cached duplicate groups before acting. Keep/delete suggestions follow rc-jav rules; catalog rows remain reference-only.</div>
|
||
<div class="button-row">
|
||
<button id="dupe-review-run" type="button">Review Cached Duplicates</button>
|
||
</div>
|
||
<div id="dupe-review-results" class="mono-output">Review opens in a focused window so large duplicate groups do not stretch this page.</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Keep ranking</div>
|
||
<div class="help">Controls how rc-jav picks the KEEP file when duplicates are found. Changes take effect immediately — no rescan required.</div>
|
||
<div class="kr-panel">
|
||
<div class="kr-info">
|
||
<strong style="color:#93c5fd">How it works:</strong> Video files in <code>VIP folders</code> win first. <code>.ts</code> files rank below other video containers. After that, files within <code>size tolerance</code> of the largest are treated as equal-size, then ranked by
|
||
<code>format preference</code>. Remaining ties broken by resolution tag, then filename length.
|
||
With tolerance = 0 (default), size always decides first.
|
||
</div>
|
||
<div class="kr-row" style="align-items:flex-start">
|
||
<span class="kr-label" style="padding-top:6px">VIP folders</span>
|
||
<div>
|
||
<div id="kr-vip-list" class="kr-fmt-list"></div>
|
||
<div class="button-row" style="margin-top:6px;">
|
||
<input id="kr-vip-add" type="text" placeholder="ClearJAV or cq:JAV/DirectRips" style="width:220px;">
|
||
<button id="kr-vip-add-btn" type="button">Add VIP Folder</button>
|
||
</div>
|
||
</div>
|
||
<span class="kr-unit" style="padding-top:6px">drag to reorder · top wins first · ClearJAV is the default direct-rip VIP folder</span>
|
||
</div>
|
||
<div class="kr-row">
|
||
<span class="kr-label">Size tolerance</span>
|
||
<input id="kr-tolerance" class="kr-input" type="number" min="0" max="9999" step="1" value="0">
|
||
<span class="kr-unit">MiB — files within this range of the largest are considered equal-size</span>
|
||
</div>
|
||
<div class="kr-row" style="align-items:flex-start">
|
||
<span class="kr-label" style="padding-top:6px">Format preference</span>
|
||
<div id="kr-fmt-list" class="kr-fmt-list">
|
||
<!-- populated by JS -->
|
||
</div>
|
||
<span class="kr-unit" style="padding-top:6px">drag to reorder · top = highest priority</span>
|
||
</div>
|
||
<div class="kr-row">
|
||
<span class="kr-label">Tie-breaks</span>
|
||
<label class="kr-toggle"><input type="checkbox" id="kr-res-tag" checked> Prefer file with resolution tag <code>[1080p]</code></label>
|
||
</div>
|
||
<div class="kr-row">
|
||
<span class="kr-label"></span>
|
||
<label class="kr-toggle"><input type="checkbox" id="kr-longer-name" checked> Prefer longer filename (more metadata)</label>
|
||
</div>
|
||
<div class="kr-save-row">
|
||
<button id="kr-save" type="button">Save Ranking</button>
|
||
<span id="kr-save-status" class="kr-save-status"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Library issues</div>
|
||
<div class="help">Find files with non-canonical names: bracket-wrapped IDs like <code>[REAL-779].mp4</code> and no-hyphen IDs like <code>MVSD312.avi</code>. Rename suggestions are computed from cache — no network required.</div>
|
||
<div class="button-row">
|
||
<button id="library-issues-run" type="button">Review Library Issues</button>
|
||
</div>
|
||
<div id="library-issues-results" class="mono-output"></div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- SETUP -->
|
||
<div class="pane" id="pane-paths">
|
||
<div class="pane-head">
|
||
<h1>Setup</h1>
|
||
<div class="pdesc">Script location and settings backup. Native host registration + extension ID live in Diagnostics.</div>
|
||
</div>
|
||
<div id="paths-summary" class="section-note"></div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">rc-jav script path</div>
|
||
<div class="help">Folder containing <code>rc-jav.py</code>, or full file path. Leave blank for the host default.</div>
|
||
<div class="compact-grid">
|
||
<input type="text" id="rcjavPath" placeholder="D:\DEV\Project\rclone-jav">
|
||
<button id="clear-rcjav-path" type="button">Use Default</button>
|
||
</div>
|
||
<div class="button-row" style="margin-top:8px;">
|
||
<button id="check-rcjav-path" type="button">Check Path</button>
|
||
<span id="path-check-output" class="muted"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="backup-summary" class="section-note"></div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Backup before moving</div>
|
||
<div class="help">Extension settings and native messaging permissions are tied to the extension ID. Export before moving, reloading, or reinstalling. See <code>docs/EXTENSION_ID.md</code> for the stable-ID workflow.</div>
|
||
<div class="button-row">
|
||
<button id="export-settings">Export Settings</button>
|
||
<button id="import-settings">Import Settings</button>
|
||
<input type="file" id="import-file" accept=".json,application/json" style="display:none;">
|
||
<span id="backup-status" style="color:#888;font-size:11px;"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- PROFILES -->
|
||
<div class="pane" id="pane-profiles">
|
||
<div class="pane-head">
|
||
<h1>Library Profiles</h1>
|
||
<div class="pdesc">Named source and target remote sets for switching libraries from the popup.</div>
|
||
</div>
|
||
<div id="profiles-summary" class="section-note"></div>
|
||
|
||
<div id="profiles-list" style="margin-bottom:12px;"></div>
|
||
<div class="button-row">
|
||
<button id="add-profile" type="button">+ Add Profile</button>
|
||
<button id="load-remotes" type="button">Load Remotes</button>
|
||
<span id="profiles-status" class="muted"></span>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DIAGNOSTICS -->
|
||
<div class="pane" id="pane-diagnostics">
|
||
<div class="pane-head">
|
||
<h1>Diagnostics</h1>
|
||
<div class="pdesc">Check setup health, runtime dependencies, native host registration, and recent search behavior.</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="fieldset">
|
||
<div class="ftitle">Setup health</div>
|
||
<div class="help">Quick read on current lookup mode, pause state, active profile, cache freshness, and native host registration.</div>
|
||
<div class="button-row">
|
||
<button id="setup-health-run" type="button">Check Setup Health</button>
|
||
</div>
|
||
<div id="setup-health-results" class="mono-output"></div>
|
||
</div>
|
||
|
||
<div id="native-repair-card" class="fieldset" style="display:none;">
|
||
<div class="ftitle" id="native-repair-title">Native host setup</div>
|
||
<div id="native-repair-results"></div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Runtime</div>
|
||
<div class="help">Verifies Python, rclone, rc-jav, config, cache, and WinCatalog files.</div>
|
||
<div class="button-row">
|
||
<button id="run-diag">Run Diagnostics</button>
|
||
<button id="run-all-diag" type="button">Run All</button>
|
||
</div>
|
||
<div id="diag-results" style="margin-top:14px;"></div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Native host registration</div>
|
||
<div class="help">Checks the manifest, extension ID permission, and Windows registry entries used by Brave/Chrome native messaging.</div>
|
||
<div class="compact-grid" style="margin-bottom:10px;align-items:center;">
|
||
<div style="font-family:Consolas,monospace;font-size:12px;color:#bbb;"><span style="color:#888;">Extension ID: </span><span id="diag-extension-id">—</span></div>
|
||
<button id="diag-copy-extension-id" type="button" style="padding:4px 10px;font-size:11px;">Copy ID</button>
|
||
</div>
|
||
<div class="button-row">
|
||
<button id="host-status-run" type="button">Check Host Registration</button>
|
||
<button id="host-repair-run" type="button">Repair Registration</button>
|
||
<button id="host-verify-run" type="button">Verify Registration</button>
|
||
</div>
|
||
<div id="host-status-results" style="margin-top:14px;"></div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DEBUG TOOLS -->
|
||
<div class="pane" id="pane-debug">
|
||
<div class="pane-head">
|
||
<h1>Debug Tools</h1>
|
||
<div class="pdesc">Standalone diagnostic surfaces moved out of the main Diagnostics pane. Search troubleshooting bench + recent search/page-check activity log. Not part of the maintenance workflow.</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div class="fieldset">
|
||
<div class="ftitle">Search troubleshooting</div>
|
||
<div class="help">Paste an ID, page title, DOM text, URL fragment, or filename. The bench extracts an ID, then compares LIVE and CACHE lookup paths for that ID under the active library profile.</div>
|
||
<textarea id="search-bench-input" placeholder="BLK-474 or paste a page title / DOM text / URL containing an ID"></textarea>
|
||
<div class="button-row" style="margin-top:8px;">
|
||
<button id="search-bench-run" type="button">Test Search</button>
|
||
<button id="search-bench-clear" type="button">Clear</button>
|
||
</div>
|
||
<div id="search-bench-results" class="mono-output"></div>
|
||
</div>
|
||
|
||
<div class="fieldset">
|
||
<div class="ftitle">Recent activity</div>
|
||
<div class="help">Short local history of page checks and popup searches. Stores the extracted ID, outcome, page context, mode, and timing summary. Search-trigger events only — deletion actions are not recorded here.</div>
|
||
<div class="button-row">
|
||
<button id="activity-refresh" type="button">Refresh Activity</button>
|
||
<button id="activity-clear" type="button">Clear Activity</button>
|
||
</div>
|
||
<div class="activity-filters" id="activity-filters" aria-label="Recent activity filters">
|
||
<button class="activity-filter active" type="button" data-activity-filter="all">All</button>
|
||
<button class="activity-filter" type="button" data-activity-filter="hit">Match</button>
|
||
<button class="activity-filter" type="button" data-activity-filter="miss">No Match</button>
|
||
<button class="activity-filter" type="button" data-activity-filter="no_id">No ID</button>
|
||
<button class="activity-filter" type="button" data-activity-filter="other">Other</button>
|
||
</div>
|
||
<div id="activity-results" class="mono-output"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- DELETION -->
|
||
<div class="pane" id="pane-deletion">
|
||
<div class="pane-head">
|
||
<h1 style="color:#faa;">Deletion</h1>
|
||
<div class="pdesc">When enabled, the popup adds a delete button for matched files. Every delete still requires typing the exact filename to confirm.</div>
|
||
</div>
|
||
<div id="deletion-summary" class="section-note danger"></div>
|
||
|
||
<div class="fieldset danger-zone">
|
||
<div class="ftitle">Enable</div>
|
||
<label><input type="checkbox" id="enableDelete"> Enable file deletion from popup</label>
|
||
</div>
|
||
|
||
<div class="fieldset danger-zone">
|
||
<div class="ftitle">Mode</div>
|
||
<div class="radio-group">
|
||
<label class="selected" id="deleteModeTrashLbl"><input type="radio" name="deleteMode" id="deleteModeTrash" value="trash" checked> Move To Trash</label>
|
||
<label id="deleteModePermLbl"><input type="radio" name="deleteMode" id="deleteModePerm" value="permanent"> Permanent Delete</label>
|
||
</div>
|
||
<div class="help">Trash mode runs <code>rclone moveto</code> into the trash dir + <code>YYYY-MM-DD/</code> subdir. Reversible until cleared. Permanent runs <code>rclone deletefile</code> — cloud Drives may still keep a 30-day recycle bin.</div>
|
||
</div>
|
||
|
||
<div class="fieldset danger-zone">
|
||
<div class="ftitle">Trash directory</div>
|
||
<input type="text" id="trashDir" placeholder="cq:personal-files/.rclone-jav-trash">
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button class="primary save-btn">SAVE</button>
|
||
<span class="saved">Saved.</span>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div id="skipped-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="skipped-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="skipped-modal-title">Skipped IDs</div>
|
||
<div class="modal-subtitle" id="skipped-modal-subtitle"></div>
|
||
</div>
|
||
<button id="skipped-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div id="skipped-modal-summary" class="skip-summary"></div>
|
||
<div id="skipped-modal-list"></div>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button id="skipped-modal-copy" type="button">Copy List</button>
|
||
<button id="skipped-modal-done" type="button">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="profile-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="profile-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="profile-modal-title">Library Profile</div>
|
||
<div class="modal-subtitle">Named source and target remotes for popup library switching.</div>
|
||
</div>
|
||
<button id="profile-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="modal-field">
|
||
<label for="profile-modal-name">Profile name</label>
|
||
<input type="text" id="profile-modal-name" placeholder="ClearJAV">
|
||
</div>
|
||
<div class="modal-field">
|
||
<label>Source remotes</label>
|
||
<div id="profile-modal-source" class="prof-remote-group"></div>
|
||
</div>
|
||
<div class="modal-field">
|
||
<label>Target remotes</label>
|
||
<div id="profile-modal-target" class="prof-remote-group"></div>
|
||
</div>
|
||
<div id="profile-modal-status" class="muted"></div>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button id="profile-modal-cancel" type="button">Cancel</button>
|
||
<button id="profile-modal-save" class="primary" type="button">Save Profile</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="dupe-review-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="dupe-review-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="dupe-review-modal-title">Duplicate Review</div>
|
||
<div class="modal-subtitle">Cached duplicate groups and rc-jav keep/delete suggestions.</div>
|
||
</div>
|
||
<button id="dupe-review-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div id="dupe-review-modal-body" class="modal-body"></div>
|
||
<div class="modal-actions">
|
||
<span id="dupe-review-confirm-status" style="font-size:12px;color:#8888aa;flex:1;"></span>
|
||
<button id="dupe-review-execute" type="button" disabled>Execute Deletions (0)</button>
|
||
<button id="dupe-review-export" type="button" disabled>Export JSON</button>
|
||
<button id="dupe-review-modal-done" type="button">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="library-issues-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="library-issues-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="library-issues-modal-title">Library Issues</div>
|
||
<div class="modal-subtitle">Non-canonical filenames detected in cache. Rename to fix.</div>
|
||
</div>
|
||
<button id="library-issues-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div id="library-issues-modal-body" class="modal-body"></div>
|
||
<div class="modal-actions">
|
||
<span id="library-issues-rename-status" style="font-size:12px;color:#8888aa;flex:1;"></span>
|
||
<button id="library-issues-rename-all" type="button" disabled>Rename All</button>
|
||
<button id="library-issues-modal-done" type="button">Close</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="import-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="import-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="import-modal-title">Import Settings</div>
|
||
<div class="modal-subtitle" id="import-modal-subtitle"></div>
|
||
</div>
|
||
<button id="import-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div id="import-modal-body" class="modal-body"></div>
|
||
<div class="modal-actions">
|
||
<button id="import-modal-cancel" type="button">Cancel</button>
|
||
<button id="import-modal-confirm" class="primary" type="button">Import Settings</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="delete-enable-modal" class="modal-backdrop" aria-hidden="true">
|
||
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="delete-enable-modal-title">
|
||
<div class="modal-head">
|
||
<div>
|
||
<div class="modal-title" id="delete-enable-modal-title">Enable Deletion</div>
|
||
<div class="modal-subtitle">This exposes delete controls in the popup.</div>
|
||
</div>
|
||
<button id="delete-enable-modal-close" type="button" title="Close">x</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="modal-confirm">Matched files can be moved to trash or permanently deleted from the popup after this setting is saved. Popup deletion still requires typing the exact filename before rc-jav acts.</div>
|
||
</div>
|
||
<div class="modal-actions">
|
||
<button id="delete-enable-modal-cancel" type="button">Cancel</button>
|
||
<button id="delete-enable-modal-confirm" class="primary" type="button">Enable Deletion</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script src="options-cache.js"></script>
|
||
<script src="options-dupe-review.js"></script>
|
||
<script src="options-library-issues.js"></script>
|
||
<script src="options-diagnostics.js"></script>
|
||
<script src="options-profiles.js"></script>
|
||
<script src="options-rules-editors.js"></script>
|
||
<script src="options.js"></script>
|
||
</body>
|
||
</html>
|