Merge pull request #76 from wagesj45/codex/rework-project-iconography-and-update-readme

Update icons and options UI
This commit is contained in:
Jordan Wages 2025-07-08 00:41:00 -05:00 committed by GitHub
commit cd5ef92e0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 103 additions and 19 deletions

View file

@ -66,3 +66,10 @@ text extracted from all text parts.
properties. Any legacy `aiReasonCache` data is merged into `aiCache` the first properties. Any legacy `aiReasonCache` data is merged into `aiCache` the first
time the add-on loads after an update. time the add-on loads after an update.
### Icon Set Usage
Toolbar and menu icons reside under `resources/img` and are provided in 16, 32
and 64 pixel variants. When changing these icons, pass a dictionary mapping the
sizes to the paths in `browserAction.setIcon` or `messageDisplayAction.setIcon`.
Use `resources/svg/svg2img.ps1` to regenerate PNGs from the SVG sources.

View file

@ -141,3 +141,5 @@ Sortana builds upon knowledge gained from open-source projects. In particular,
how Thunderbird's WebExtension and experiment APIs can be extended. Their code how Thunderbird's WebExtension and experiment APIs can be extended. Their code
provided invaluable guidance during development. provided invaluable guidance during development.
- Icons from [cc0-icons.jonh.eu](https://cc0-icons.jonh.eu/) are used under the CC0 license.

View file

@ -28,6 +28,25 @@ let altTextImages = false;
let collapseWhitespace = false; let collapseWhitespace = false;
let TurndownService = null; let TurndownService = null;
const ICONS = {
logo: "resources/img/logo.png",
circledots: {
16: "resources/img/circledots-16.png",
32: "resources/img/circledots-32.png",
64: "resources/img/circledots-64.png"
},
circle: {
16: "resources/img/circle-16.png",
32: "resources/img/circle-32.png",
64: "resources/img/circle-64.png"
},
average: {
16: "resources/img/average-16.png",
32: "resources/img/average-32.png",
64: "resources/img/average-64.png"
}
};
function setIcon(path) { function setIcon(path) {
if (browser.browserAction) { if (browser.browserAction) {
browser.browserAction.setIcon({ path }); browser.browserAction.setIcon({ path });
@ -38,9 +57,9 @@ function setIcon(path) {
} }
function updateActionIcon() { function updateActionIcon() {
let path = "resources/img/brain.png"; let path = ICONS.logo;
if (processing || queuedCount > 0) { if (processing || queuedCount > 0) {
path = "resources/img/busy.png"; path = ICONS.circledots;
} }
setIcon(path); setIcon(path);
} }
@ -201,7 +220,7 @@ async function applyAiRules(idsInput) {
t.mean += delta / t.count; t.mean += delta / t.count;
t.m2 += delta * (elapsed - t.mean); t.m2 += delta * (elapsed - t.mean);
await storage.local.set({ classifyStats: t }); await storage.local.set({ classifyStats: t });
showTransientIcon("resources/img/done.png"); showTransientIcon(ICONS.circle);
} catch (e) { } catch (e) {
processing = false; processing = false;
const elapsed = Date.now() - currentStart; const elapsed = Date.now() - currentStart;
@ -215,7 +234,7 @@ async function applyAiRules(idsInput) {
t.m2 += delta * (elapsed - t.mean); t.m2 += delta * (elapsed - t.mean);
await storage.local.set({ classifyStats: t }); await storage.local.set({ classifyStats: t });
logger.aiLog("failed to apply AI rules", { level: 'error' }, e); logger.aiLog("failed to apply AI rules", { level: 'error' }, e);
showTransientIcon("resources/img/error.png"); showTransientIcon(ICONS.average);
} }
}); });
} }
@ -250,7 +269,7 @@ async function clearCacheForMessages(idsInput) {
} }
if (keys.length) { if (keys.length) {
await AiClassifier.removeCacheEntries(keys); await AiClassifier.removeCacheEntries(keys);
showTransientIcon("resources/img/done.png"); showTransientIcon(ICONS.circle);
} }
} }
@ -340,33 +359,61 @@ async function clearCacheForMessages(idsInput) {
id: "apply-ai-rules-list", id: "apply-ai-rules-list",
title: "Apply AI Rules", title: "Apply AI Rules",
contexts: ["message_list"], contexts: ["message_list"],
icons: {
16: "resources/img/eye-16.png",
32: "resources/img/eye-32.png",
64: "resources/img/eye-64.png"
}
}); });
browser.menus.create({ browser.menus.create({
id: "apply-ai-rules-display", id: "apply-ai-rules-display",
title: "Apply AI Rules", title: "Apply AI Rules",
contexts: ["message_display_action"], contexts: ["message_display_action"],
icons: {
16: "resources/img/eye-16.png",
32: "resources/img/eye-32.png",
64: "resources/img/eye-64.png"
}
}); });
browser.menus.create({ browser.menus.create({
id: "clear-ai-cache-list", id: "clear-ai-cache-list",
title: "Clear AI Cache", title: "Clear AI Cache",
contexts: ["message_list"], contexts: ["message_list"],
icons: {
16: "resources/img/trash-16.png",
32: "resources/img/trash-32.png",
64: "resources/img/trash-64.png"
}
}); });
browser.menus.create({ browser.menus.create({
id: "clear-ai-cache-display", id: "clear-ai-cache-display",
title: "Clear AI Cache", title: "Clear AI Cache",
contexts: ["message_display_action"], contexts: ["message_display_action"],
icons: {
16: "resources/img/trash-16.png",
32: "resources/img/trash-32.png",
64: "resources/img/trash-64.png"
}
}); });
browser.menus.create({ browser.menus.create({
id: "view-ai-reason-list", id: "view-ai-reason-list",
title: "View Reasoning", title: "View Reasoning",
contexts: ["message_list"], contexts: ["message_list"],
icons: { "16": "resources/img/brain.png" } icons: {
16: "resources/img/clipboarddata-16.png",
32: "resources/img/clipboarddata-32.png",
64: "resources/img/clipboarddata-64.png"
}
}); });
browser.menus.create({ browser.menus.create({
id: "view-ai-reason-display", id: "view-ai-reason-display",
title: "View Reasoning", title: "View Reasoning",
contexts: ["message_display_action"], contexts: ["message_display_action"],
icons: { "16": "resources/img/brain.png" } icons: {
16: "resources/img/clipboarddata-16.png",
32: "resources/img/clipboarddata-32.png",
64: "resources/img/clipboarddata-64.png"
}
}); });
browser.menus.onClicked.addListener(async (info, tab) => { browser.menus.onClicked.addListener(async (info, tab) => {

View file

@ -22,7 +22,7 @@
"default_icon": "resources/img/logo32.png" "default_icon": "resources/img/logo32.png"
}, },
"message_display_action": { "message_display_action": {
"default_icon": "resources/img/brain.png", "default_icon": "resources/img/logo.png",
"default_title": "Details", "default_title": "Details",
"default_label": "Details", "default_label": "Details",
"default_popup": "details.html" "default_popup": "details.html"

View file

@ -44,18 +44,25 @@
<div class="level-left"> <div class="level-left">
<div class="tabs" id="main-tabs"> <div class="tabs" id="main-tabs">
<ul> <ul>
<li class="is-active" data-tab="settings"><a>Settings</a></li> <li class="is-active" data-tab="settings"><a><span class="icon is-small"><img src="../resources/svg/settings.svg" alt=""></span><span>Settings</span></a></li>
<li data-tab="rules"><a>Rules</a></li> <li data-tab="rules"><a><span class="icon is-small"><img src="../resources/svg/clipboarddata.svg" alt=""></span><span>Rules</span></a></li>
<li data-tab="maintenance"><a>Maintenance</a></li> <li data-tab="maintenance"><a><span class="icon is-small"><img src="../resources/svg/gear.svg" alt=""></span><span>Maintenance</span></a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="level-right"> <div class="level-right">
<button class="button is-primary" id="save" disabled>Save</button> <button class="button is-primary" id="save" disabled>
<span class="icon is-small"><img src="../resources/svg/flag.svg" alt=""></span>
<span>Save</span>
</button>
</div> </div>
</div> </div>
<div id="settings-tab" class="tab-content"> <div id="settings-tab" class="tab-content">
<h2 class="title is-4">
<span class="icon is-small"><img src="../resources/svg/settings.svg" alt=""></span>
<span>Settings</span>
</h2>
<div class="field"> <div class="field">
<label class="label" for="endpoint">Endpoint</label> <label class="label" for="endpoint">Endpoint</label>
<div class="control"> <div class="control">
@ -88,8 +95,14 @@
</div> </div>
<div class="buttons"> <div class="buttons">
<button class="button is-danger" id="reset-system">Reset to default</button> <button class="button is-danger" id="reset-system">
<button class="button" id="toggle-advanced" type="button">Advanced</button> <span class="icon is-small"><img src="../resources/svg/reply.svg" alt=""></span>
<span>Reset to default</span>
</button>
<button class="button" id="toggle-advanced" type="button">
<span class="icon is-small"><img src="../resources/svg/gear.svg" alt=""></span>
<span>Advanced</span>
</button>
</div> </div>
<div id="advanced-options" class="mt-4 is-hidden"> <div id="advanced-options" class="mt-4 is-hidden">
@ -188,13 +201,19 @@
</div> </div>
<div id="rules-tab" class="tab-content is-hidden"> <div id="rules-tab" class="tab-content is-hidden">
<h2 class="title is-4">Classification Rules</h2> <h2 class="title is-4">
<span class="icon is-small"><img src="../resources/svg/clipboarddata.svg" alt=""></span>
<span>Classification Rules</span>
</h2>
<div id="rules-container"></div> <div id="rules-container"></div>
<button class="button is-link" id="add-rule" type="button">Add Rule</button> <button class="button is-link" id="add-rule" type="button">Add Rule</button>
</div> </div>
<div id="maintenance-tab" class="tab-content is-hidden"> <div id="maintenance-tab" class="tab-content is-hidden">
<h2 class="title is-4">Maintenance</h2> <h2 class="title is-4">
<span class="icon is-small"><img src="../resources/svg/gear.svg" alt=""></span>
<span>Maintenance</span>
</h2>
<table class="table is-fullwidth"> <table class="table is-fullwidth">
<tbody> <tbody>
<tr><th>Rule count</th><td id="rule-count"></td></tr> <tr><th>Rule count</th><td id="rule-count"></td></tr>
@ -206,7 +225,10 @@
<tr><th>Total run time</th><td id="total-time">--:--:--</td></tr> <tr><th>Total run time</th><td id="total-time">--:--:--</td></tr>
</tbody> </tbody>
</table> </table>
<button class="button is-danger" id="clear-cache" type="button">Clear Cache</button> <button class="button is-danger" id="clear-cache" type="button">
<span class="icon is-small"><img src="../resources/svg/trash.svg" alt=""></span>
<span>Clear Cache</span>
</button>
<div class="field mt-4"> <div class="field mt-4">
<label class="label">Data categories</label> <label class="label">Data categories</label>
<div class="control"> <div class="control">
@ -217,10 +239,16 @@
</div> </div>
<div class="field is-grouped mt-4"> <div class="field is-grouped mt-4">
<p class="control"> <p class="control">
<button class="button" id="export-data" type="button">Export Data</button> <button class="button" id="export-data" type="button">
<span class="icon is-small"><img src="../resources/svg/download.svg" alt=""></span>
<span>Export Data</span>
</button>
</p> </p>
<p class="control"> <p class="control">
<button class="button" id="import-data" type="button">Import Data</button> <button class="button" id="import-data" type="button">
<span class="icon is-small"><img src="../resources/svg/upload.svg" alt=""></span>
<span>Import Data</span>
</button>
<input class="is-hidden" type="file" id="import-file" accept="application/json"> <input class="is-hidden" type="file" id="import-file" accept="application/json">
</p> </p>
</div> </div>