Merge pull request #92 from wagesj45/codex/add-delete-and-archive-actions

Add delete and archive actions
This commit is contained in:
Jordan Wages 2025-07-15 22:39:10 -05:00 committed by GitHub
commit 52ea120534
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 16 additions and 5 deletions

View file

@ -17,7 +17,7 @@ message meets a specified criterion.
- **Markdown conversion** optionally convert HTML bodies to Markdown before sending them to the AI service. - **Markdown conversion** optionally convert HTML bodies to Markdown before sending them to the AI service.
- **Debug logging** optional colorized logs help troubleshoot interactions with the AI service. - **Debug logging** optional colorized logs help troubleshoot interactions with the AI service.
- **Light/Dark themes** automatically match Thunderbird's appearance with optional manual override. - **Light/Dark themes** automatically match Thunderbird's appearance with optional manual override.
- **Automatic rules** create rules that tag, move, copy, mark read/unread or flag/unflag messages based on AI classification. Rules can optionally apply only to unread messages. - **Automatic rules** create rules that tag, move, copy, delete, archive, mark read/unread or flag/unflag messages based on AI classification. Rules can optionally apply only to unread messages.
- **Rule ordering** drag rules to prioritize them and optionally stop processing after a match. - **Rule ordering** drag rules to prioritize them and optionally stop processing after a match.
- **Context menu** apply AI rules from the message list or the message display action button. - **Context menu** apply AI rules from the message list or the message display action button.
- **Status icons** toolbar icons show when classification is in progress and briefly display success or error states. - **Status icons** toolbar icons show when classification is in progress and briefly display success or error states.
@ -70,7 +70,7 @@ Sortana is implemented entirely with standard WebExtension scripts—no custom e
1. Open the add-on's options and set the URL of your classification service. 1. Open the add-on's options and set the URL of your classification service.
2. Use the **Classification Rules** section to add a criterion and optional 2. Use the **Classification Rules** section to add a criterion and optional
actions such as tagging or moving a message when it matches. Drag rules to actions such as tagging, moving, copying, deleting or archiving a message when it matches. Drag rules to
reorder them, check *Only apply to unread messages* to skip read mail, and reorder them, check *Only apply to unread messages* to skip read mail, and
check *Stop after match* to halt further processing. check *Stop after match* to halt further processing.
3. Save your settings. New mail will be evaluated automatically using the 3. Save your settings. New mail will be evaluated automatically using the
@ -102,7 +102,7 @@ Here are some useful and fun example criteria you can use in your filters. Filte
For when you're ready to filter based on vibes. For when you're ready to filter based on vibes.
You can define as many filters as you'd like, each using a different prompt and You can define as many filters as you'd like, each using a different prompt and
triggering tags, moves, copies, read/unread changes or flag updates based on the model's classification. triggering tags, moves, copies, deletes, archives, read/unread changes or flag updates based on the model's classification.
## Required Permissions ## Required Permissions

View file

@ -22,6 +22,8 @@
,"action.read": { "message": "read" } ,"action.read": { "message": "read" }
,"action.flag": { "message": "flag" } ,"action.flag": { "message": "flag" }
,"action.copy": { "message": "copy" } ,"action.copy": { "message": "copy" }
,"action.delete": { "message": "delete" }
,"action.archive": { "message": "archive" }
,"param.markRead": { "message": "mark read" } ,"param.markRead": { "message": "mark read" }
,"param.markUnread": { "message": "mark unread" } ,"param.markUnread": { "message": "mark unread" }
,"param.flag": { "message": "flag" } ,"param.flag": { "message": "flag" }

View file

@ -243,6 +243,10 @@ async function processMessage(id) {
await messenger.messages.update(id, { read: !!act.read }); await messenger.messages.update(id, { read: !!act.read });
} else if (act.type === 'flag') { } else if (act.type === 'flag') {
await messenger.messages.update(id, { flagged: !!act.flagged }); await messenger.messages.update(id, { flagged: !!act.flagged });
} else if (act.type === 'delete') {
await messenger.messages.delete([id]);
} else if (act.type === 'archive') {
await messenger.messages.archive([id]);
} }
} }
if (rule.stopProcessing) { if (rule.stopProcessing) {

View file

@ -171,7 +171,7 @@ document.addEventListener('DOMContentLoaded', async () => {
const typeWrapper = document.createElement('div'); const typeWrapper = document.createElement('div');
typeWrapper.className = 'select is-small mr-2'; typeWrapper.className = 'select is-small mr-2';
const typeSelect = document.createElement('select'); const typeSelect = document.createElement('select');
['tag','move','copy','junk','read','flag'].forEach(t => { ['tag','move','copy','junk','read','flag','delete','archive'].forEach(t => {
const opt = document.createElement('option'); const opt = document.createElement('option');
opt.value = t; opt.value = t;
opt.textContent = t; opt.textContent = t;
@ -242,6 +242,8 @@ document.addEventListener('DOMContentLoaded', async () => {
sel.value = String(action.flagged ?? true); sel.value = String(action.flagged ?? true);
wrap.appendChild(sel); wrap.appendChild(sel);
paramSpan.appendChild(wrap); paramSpan.appendChild(wrap);
} else if (typeSelect.value === 'delete' || typeSelect.value === 'archive') {
paramSpan.appendChild(document.createElement('span'));
} }
} }
@ -373,6 +375,9 @@ document.addEventListener('DOMContentLoaded', async () => {
if (type === 'flag') { if (type === 'flag') {
return { type, flagged: row.querySelector('.flag-select').value === 'true' }; return { type, flagged: row.querySelector('.flag-select').value === 'true' };
} }
if (type === 'delete' || type === 'archive') {
return { type };
}
return { type }; return { type };
}); });
const stopProcessing = ruleEl.querySelector('.stop-processing')?.checked; const stopProcessing = ruleEl.querySelector('.stop-processing')?.checked;