Files
portage/firefox/dashboard.html
T
2026-06-08 20:17:33 -04:00

221 lines
13 KiB
HTML

<!DOCTYPE html>
<!--
Portage by pvrz
https://github.com/pvrzz/Portage/
File Name: dashboard.html
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<script src="theme.js"></script>
<title>Portage</title>
</head>
<body>
<div class="toast-wrap" id="toasts"></div>
<div class="shell">
<header class="topbar">
<div class="brandmark">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M8 18V6"/><path d="m4 10 4-4 4 4"/><path d="M16 6v12"/><path d="m12 14 4 4 4-4"/>
</svg>
</div>
<div>
<h1>Portage</h1>
<div class="sub">A universal browser data swap — any browser to any browser</div>
</div>
<span class="srcbadge" id="srcBadge">This browser</span>
<div class="spacer"></div>
<div class="theme-wrap">
<button class="icon-btn" id="themeBtn" title="Theme" aria-label="Theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 0 0 0 20z" fill="currentColor" stroke="none"/></svg>
</button>
<div class="theme-pop hidden" id="themePop">
<div class="tg">
<label>Appearance</label>
<div class="pills">
<button class="pill" data-mode="system"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="3" rx="2"/><path d="M8 21h8"/><path d="M12 17v4"/></svg>System</button>
<button class="pill" data-mode="light"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M6.3 17.7l-1.4 1.4M19.1 4.9l-1.4 1.4"/></svg>Light</button>
<button class="pill" data-mode="dark"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>Dark</button>
</div>
</div>
<div class="tg">
<label>Accent color</label>
<div class="accent-row">
<button class="pill" id="accentDefault" style="flex:1">Default · monochrome</button>
<button class="swatch" id="accentSwatch" title="Pick a custom color">
<input type="color" id="accentInput" value="#4f46e5">
<span class="swatch-preview" id="accentPreview"></span>
</button>
</div>
</div>
</div>
</div>
<div class="seg" id="modeSeg">
<button data-mode="export" class="active">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 16V4"/><path d="m6 10 6-6 6 6"/><path d="M4 20h16"/></svg>
Export
</button>
<button data-mode="import">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v12"/><path d="m6 10 6 6 6-6"/><path d="M4 20h16"/></svg>
Import
</button>
</div>
</header>
<section id="exportPanel">
<div class="hero">
<div class="hero-copy">
<h2 id="exHeroTitle">Scan this browser, then carry your data across</h2>
<p>Portage gathers your bookmarks, history, cookies, tabs, sessions and reading list into one portable JSON bundle, and writes your extension list to a separate checklist file. Because it's just JSON, you can import it into <b>any</b> browser running Portage — Chrome ↔ Firefox, or the same browser on a new machine or profile. Nothing leaves your machine, and the data is wiped from memory the moment you export.</p>
</div>
<button class="btn btn-primary" id="scan">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
<span id="scanLabel">Scan my browser</span>
</button>
</div>
<section class="enc-panel" id="encPanel">
<div class="enc-head">
<div class="card-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
</div>
<div class="enc-titles">
<h3>Encrypt this bundle <span class="badge-rec">Recommended</span></h3>
<div class="desc">AES-256-GCM with PBKDF2. The file is unreadable on disk without your passphrase.</div>
</div>
<label class="switch" title="Toggle encryption"><input type="checkbox" id="encToggle" checked><span class="track"></span></label>
</div>
<div class="enc-body" id="encBody">
<div class="field">
<label for="encPass">Passphrase</label>
<div class="pass-row">
<input class="input" type="password" id="encPass" placeholder="Enter a strong passphrase" autocomplete="new-password" spellcheck="false">
<button class="reveal" id="encReveal" type="button" title="Show or hide" aria-label="Show or hide passphrase">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg>
</button>
</div>
<div class="strength" style="margin-top:10px;">
<div class="strength-bar"><i id="encStrengthBar"></i></div>
<span class="strength-label" id="encStrengthLabel"></span>
</div>
</div>
<div class="field">
<label for="encPass2">Confirm passphrase</label>
<div class="pass-row">
<input class="input" type="password" id="encPass2" placeholder="Re-enter to confirm" autocomplete="new-password" spellcheck="false" style="padding-right:12px;">
</div>
</div>
<div class="enc-note">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
<span>There is no recovery. If you lose this passphrase, nobody — including you — can open the bundle.</span>
</div>
</div>
</section>
<div class="scanbar-wrap hidden" id="scanbarWrap">
<div class="scanbar-label"><span id="scanStage">Preparing…</span><span id="scanPct" class="mono">0%</span></div>
<div class="scanbar"><i id="scanFill"></i></div>
</div>
<div class="statstrip hidden" id="exStats">
<div class="s"><span class="n mono" id="totItems">0</span><span class="l">Total items</span></div>
<div class="s"><span class="n mono" id="totMigratable">0</span><span class="l">Migratable</span></div>
<div class="s"><span class="n mono" id="totSize">0 KB</span><span class="l">Bundle size</span></div>
<div class="s"><span class="n mono" id="totSelected">0</span><span class="l">Selected</span></div>
</div>
<div class="section-title">Your data</div>
<div class="grid" id="exportGrid"></div>
<div class="callout" style="margin-top:20px;">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
<div>
<h4>Your bundle can contain cookies and session tokens</h4>
<p>Keep encryption on (above) so the <code>.portage.json</code> is unreadable on disk. Portage holds your data only in this page's memory and <b>wipes it after export</b> — it's never written to extension storage. Either way, delete the file once you've imported.</p>
</div>
</div>
</section>
<section id="importPanel" class="hidden">
<div id="loadStep">
<div class="dropzone" id="dropzone">
<div class="dz-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m17 8-5-5-5 5"/><path d="M12 3v12"/></svg>
</div>
<h3>Drop a <span class="mono">.portage.json</span> bundle here</h3>
<p>…or click to choose a bundle exported from any browser — Chrome, Firefox, or the same one. Encrypted bundles will ask for your passphrase.</p>
<input type="file" id="file" accept=".json,application/json" hidden>
</div>
</div>
<div id="reviewStep" class="hidden">
<div class="hero">
<div class="hero-copy">
<h2 id="bundleTitle">Bundle loaded</h2>
<p id="bundleMeta" class="mono"></p>
</div>
<div style="display:flex;gap:8px;">
<button class="btn btn-ghost" id="reset">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/></svg>
Load another
</button>
<button class="btn btn-primary" id="importBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 4v12"/><path d="m6 10 6 6 6-6"/><path d="M4 20h16"/></svg>
Import selected
</button>
</div>
</div>
<div class="scanbar-wrap hidden" id="impbarWrap">
<div class="scanbar-label"><span id="impStage">Importing…</span><span id="impPct" class="mono">0%</span></div>
<div class="scanbar"><i id="impFill"></i></div>
</div>
<div class="statstrip">
<div class="s"><span class="n mono" id="imItems">0</span><span class="l">In bundle</span></div>
<div class="s"><span class="n mono" id="imSelected">0</span><span class="l">Selected</span></div>
<div class="s"><span class="n mono" id="imImported">0</span><span class="l">Imported</span></div>
<div class="s"><span class="n mono" id="imSkipped">0</span><span class="l">Skipped / failed</span></div>
</div>
<div class="section-title">What's in this bundle</div>
<div class="grid" id="importGrid"></div>
</div>
</section>
<footer class="footer">
<a href="https://github.com/pvrzz/Portage/" target="_blank" rel="noopener noreferrer">
<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.52 11.52 0 0 1 12 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222 0 1.606-.014 2.898-.014 3.293 0 .322.216.694.825.576C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
github.com/pvrzz/Portage
</a>
<span class="sep">·</span>
<span>developed by <a href="https://pvrz.lol/" target="_blank" rel="noopener noreferrer">pvrz</a>
<span class="heart" title="made with love"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.29 1.51 4.04 3 5.5l7 7Z"/></svg></span>
</span>
</footer>
</div>
<div class="actionbar" id="actionbar">
<div class="actionbar-inner">
<div class="summary">Ready to export <b id="abItems">0</b> items across <b id="abCats">0</b> categories.</div>
<div class="spacer"></div>
<button class="btn btn-ghost" id="copyJson">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
Copy JSON
</button>
<button class="btn btn-primary" id="export">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
Export bundle
</button>
</div>
</div>
<script src="dashboard.js"></script>
</body>
</html>