feat(theme): apply new color palette and polish UI

- Add theme variables and restyle popup/options using Primary 3 as background and Primary 2 as surfaces; accents use Primary 1.\n- Move Save to a footer section on the options page; add responsive layout and button variants.\n- Update icon build defaults to use Primary 2 for add-on and Primary 1 for toolbar icons.\n- Add build-and-commit helper to run build, stage generated assets, commit, and optionally push.\n- Add npm scripts: build:commit and build:commit:push.
This commit is contained in:
Jordan Wages 2025-08-24 00:39:20 -05:00
commit 982a16d86e
6 changed files with 285 additions and 26 deletions

View file

@ -7,6 +7,8 @@
"dev": "web-ext run --start-url https://archive.org --source-dir .", "dev": "web-ext run --start-url https://archive.org --source-dir .",
"build:icons": "node scripts/build-icons.js", "build:icons": "node scripts/build-icons.js",
"build": "npm run build:icons && web-ext build -o -a dist", "build": "npm run build:icons && web-ext build -o -a dist",
"build:commit": "node scripts/build-and-commit.js",
"build:commit:push": "PUSH=true node scripts/build-and-commit.js --push",
"lint": "echo 'Add ESLint config to enable' && exit 0", "lint": "echo 'Add ESLint config to enable' && exit 0",
"format": "echo 'Add Prettier config to enable' && exit 0", "format": "echo 'Add Prettier config to enable' && exit 0",
"test": "echo 'No tests yet' && exit 0", "test": "echo 'No tests yet' && exit 0",

101
scripts/build-and-commit.js Normal file
View file

@ -0,0 +1,101 @@
#!/usr/bin/env node
/*
Build + commit (+ optional push) helper.
- Runs the existing build (`npm run build`)
- Stages generated assets (icons by default; optionally dist with INCLUDE_DIST=true)
- Commits with a conventional message including the package version
- If `--push` or `PUSH=true`, pushes to the current branch's upstream
Notes:
- Respects .gitignore (dist is ignored unless INCLUDE_DIST=true)
- Safe no-op when there is nothing to commit
*/
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const REPO = path.join(__dirname, '..');
const PKG_PATH = path.join(REPO, 'package.json');
function run(cmd, args, opts = {}) {
const res = spawnSync(cmd, args, { stdio: 'inherit', ...opts });
if (res.error) throw res.error;
return res.status || 0;
}
function runOut(cmd, args, opts = {}) {
const res = spawnSync(cmd, args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], ...opts });
if (res.error) throw res.error;
return { code: res.status || 0, out: (res.stdout || '').trim(), err: (res.stderr || '').trim() };
}
function ensureGit() {
const { code } = runOut('git', ['--version']);
if (code !== 0) {
console.error('git not found in PATH');
process.exit(1);
}
}
function pkgVersion() {
const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
return pkg.version || '0.0.0';
}
function main() {
ensureGit();
// 1) Build (icons + xpi)
console.log('• Running build…');
const codeBuild = run('npm', ['run', 'build'], { cwd: REPO });
if (codeBuild !== 0) process.exit(codeBuild);
// 2) Stage generated assets
const includeDist = String(process.env.INCLUDE_DIST || '').toLowerCase() === 'true';
console.log('• Staging generated assets…');
// Always stage icons (tracked or untracked)
run('git', ['add', 'icons/icon-*.png'], { cwd: REPO });
if (includeDist) {
// dist is ignored; force add if requested
run('git', ['add', '-f', 'dist'], { cwd: REPO });
}
// 3) Check if anything is staged
const { out: staged } = runOut('git', ['diff', '--cached', '--name-only'], { cwd: REPO });
if (!staged) {
console.log('✓ Nothing to commit. Up to date.');
return;
}
// 4) Commit
const version = pkgVersion();
const msg = `chore(build): update generated assets (v${version})`;
console.log(`• Committing: ${msg}`);
const codeCommit = run('git', ['commit', '-m', msg], { cwd: REPO });
if (codeCommit !== 0) process.exit(codeCommit);
// 5) Optional push
const shouldPush = process.argv.includes('--push') || String(process.env.PUSH || '').toLowerCase() === 'true';
if (!shouldPush) {
console.log('✓ Commit created. Skipping push (enable with --push or PUSH=true).');
return;
}
console.log('• Pushing to upstream…');
// If upstream exists, push; else set upstream to origin/<branch>
const { code: upCode } = runOut('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], { cwd: REPO });
if (upCode === 0) {
const codePush = run('git', ['push'], { cwd: REPO });
if (codePush !== 0) process.exit(codePush);
} else {
const { out: branch } = runOut('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: REPO });
const codePush = run('git', ['push', '-u', 'origin', branch], { cwd: REPO });
if (codePush !== 0) process.exit(codePush);
}
console.log('✓ Pushed.');
}
main();

View file

@ -3,9 +3,13 @@
Generates extension and toolbar PNG icons from the base SVG with transparent Generates extension and toolbar PNG icons from the base SVG with transparent
background and configurable stroke colors. Requires ImageMagick (`magick`). background and configurable stroke colors. Requires ImageMagick (`magick`).
Config via environment variables (optional): Theme defaults (aligned with project palette):
ICON_COLOR_ADDON hex color for add-on icons (48/96/128). Default: #111827 Primary 2 (deep): #223544 add-on icon strokes (default)
ICON_COLOR_TOOLBAR hex color for toolbar icons (16/32). Default: #111827 Primary 1 (light): #5AC3D6 toolbar icon strokes (default)
Override via environment variables (optional):
ICON_COLOR_ADDON hex color for add-on icons (48/96/128). Default: #223544
ICON_COLOR_TOOLBAR hex color for toolbar icons (16/32). Default: #5AC3D6
Usage: Usage:
node scripts/build-icons.js node scripts/build-icons.js
@ -21,8 +25,8 @@ const SRC_SVG = path.join(ICONS_DIR, 'file-search.svg');
const ADDON_SIZES = [48, 96, 128]; const ADDON_SIZES = [48, 96, 128];
const TOOLBAR_SIZES = [16, 32]; const TOOLBAR_SIZES = [16, 32];
const COLOR_ADDON = process.env.ICON_COLOR_ADDON || '#111827'; const COLOR_ADDON = process.env.ICON_COLOR_ADDON || '#223544';
const COLOR_TOOLBAR = process.env.ICON_COLOR_TOOLBAR || '#111827'; const COLOR_TOOLBAR = process.env.ICON_COLOR_TOOLBAR || '#5AC3D6';
function ensureMagick() { function ensureMagick() {
// Prefer calling binaries directly to avoid shell init output polluting stdout. // Prefer calling binaries directly to avoid shell init output polluting stdout.

View file

@ -19,12 +19,7 @@
<label>Secret <input id="rpc-secret" type="password" placeholder="your-token" /></label> <label>Secret <input id="rpc-secret" type="password" placeholder="your-token" /></label>
</div> </div>
<div class="row actions"> <div class="row actions">
<button id="btn-save">Save</button> <button id="btn-test" class="btn-outline">Test Connection</button>
<button id="btn-reset">Reset</button>
<button id="btn-test">Test Connection</button>
</div>
<div class="row">
<output id="status"></output>
</div> </div>
</section> </section>
@ -48,6 +43,16 @@
<label>Base directory <input id="per-page-dir-base" placeholder="/aria2/data" /></label> <label>Base directory <input id="per-page-dir-base" placeholder="/aria2/data" /></label>
</div> </div>
</section> </section>
<section class="footer-actions">
<div class="row actions">
<button id="btn-save" class="btn-primary">Save</button>
<button id="btn-reset" class="btn-danger">Reset</button>
</div>
<div class="row">
<output id="status"></output>
</div>
</section>
</main> </main>
<script type="module" src="index.js"></script> <script type="module" src="index.js"></script>
</body> </body>

View file

@ -1,9 +1,67 @@
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 16px; } :root {
header h1 { margin: 0 0 12px; font-size: 18px; } --c-primary-1: #5AC3D6;
section { margin: 12px 0; } --c-primary-2: #223544;
--c-primary-3: #4E6D84;
--c-emph-1: #F5A623;
--c-emph-2: #D94E87;
--c-emph-3: #49C46D;
--bg: var(--c-primary-3);
--surface: var(--c-primary-2);
--text: #EAF2F7;
--muted: rgba(255,255,255,0.75);
--border: rgba(255,255,255,0.18);
--input-bg: rgba(255,255,255,0.06);
--input-border: rgba(255,255,255,0.22);
--link: var(--c-primary-1);
--focus: var(--c-primary-1);
}
body {
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
margin: 16px;
background: var(--bg);
color: var(--text);
}
header h1 { margin: 0 0 12px; font-size: 18px; color: var(--text); }
main {
display: grid;
gap: 12px;
}
@media (min-width: 820px) {
main { grid-template-columns: 1fr 1fr; }
.footer-actions { grid-column: 1 / -1; }
}
section {
margin: 0;
background: var(--surface);
padding: 12px;
border-radius: 10px;
border: 1px solid var(--border);
}
.row { display: flex; align-items: center; gap: 8px; margin: 8px 0; flex-wrap: wrap; } .row { display: flex; align-items: center; gap: 8px; margin: 8px 0; flex-wrap: wrap; }
label { font-size: 14px; } label { font-size: 14px; }
label input { margin-left: 6px; min-width: 360px; } label input { margin-left: 6px; min-width: 360px; }
button { font-size: 13px; padding: 6px 12px; }
#status { font-size: 13px; white-space: pre-wrap; }
input, select {
background: var(--input-bg);
color: var(--text);
border: 1px solid var(--input-border);
border-radius: 8px;
padding: 6px 8px;
}
input::placeholder { color: var(--muted); }
input:focus, select:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
button { font-size: 13px; padding: 8px 14px; border-radius: 8px; cursor: pointer; border: 1px solid transparent; }
button:hover { filter: brightness(1.05); }
.btn-primary { background: var(--c-primary-1); color: #11343C; }
.btn-outline { background: transparent; color: var(--text); border-color: var(--input-border); }
.btn-danger { background: var(--c-emph-2); color: #fff; }
#status { font-size: 13px; white-space: pre-wrap; color: var(--muted); }

View file

@ -1,14 +1,103 @@
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 10px; } :root {
header h1 { font-size: 14px; margin: 0 0 8px; } --c-primary-1: #5AC3D6; /* accent light */
section { margin-bottom: 10px; } --c-primary-2: #223544; /* deep surface */
.row { display: flex; align-items: center; gap: 8px; margin: 6px 0; flex-wrap: wrap; } --c-primary-3: #4E6D84; /* app background */
label { font-size: 12px; } --c-emph-1: #F5A623; /* amber */
--c-emph-2: #D94E87; /* pink */
--c-emph-3: #49C46D; /* green */
--bg: var(--c-primary-3);
--surface: var(--c-primary-2);
--text: #EAF2F7;
--muted: rgba(255,255,255,0.75);
--border: rgba(255,255,255,0.18);
--input-bg: rgba(255,255,255,0.06);
--input-border: rgba(255,255,255,0.22);
--link: var(--c-primary-1);
--focus: var(--c-primary-1);
}
body {
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
margin: 10px;
background: var(--bg);
color: var(--text);
}
header h1 {
font-size: 14px;
margin: 0 0 8px;
color: var(--text);
}
section {
margin-bottom: 10px;
background: var(--surface);
padding: 8px;
border-radius: 8px;
border: 1px solid var(--border);
}
.row {
display: flex;
align-items: center;
gap: 8px;
margin: 6px 0;
flex-wrap: wrap;
}
label { font-size: 12px; color: var(--text); }
label input { margin-left: 6px; } label input { margin-left: 6px; }
.chk { align-items: center; } .chk { align-items: center; }
button { font-size: 12px; padding: 4px 10px; }
input, select {
background: var(--input-bg);
color: var(--text);
border: 1px solid var(--input-border);
border-radius: 6px;
padding: 4px 6px;
}
input::placeholder { color: var(--muted); }
input:focus, select:focus { outline: 2px solid var(--focus); outline-offset: 1px; }
button {
font-size: 12px;
padding: 6px 12px;
background: var(--c-primary-1);
color: #11343C;
border: 1px solid transparent;
border-radius: 6px;
cursor: pointer;
}
button:hover { filter: brightness(1.05); }
button:active { transform: translateY(0.5px); }
#count { font-weight: bold; margin: 0 4px; } #count { font-weight: bold; margin: 0 4px; }
#status { font-size: 12px; white-space: pre-wrap; } #status { font-size: 12px; white-space: pre-wrap; color: var(--muted); }
.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; } .link {
#preview li { font-size: 12px; padding: 4px 6px; border-bottom: 1px solid #eee; } font-size: 12px;
margin-left: auto;
text-decoration: underline;
cursor: pointer;
color: var(--link);
}
.preview ul, #preview {
list-style: none;
padding: 0;
margin: 6px 0;
max-height: 160px;
overflow: auto;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--input-bg);
}
#preview li {
font-size: 12px;
padding: 4px 6px;
border-bottom: 1px solid rgba(255,255,255,0.08);
}
#preview li:last-child { border-bottom: 0; } #preview li:last-child { border-bottom: 0; }