Settings: a section per plugin, and call the folder Spam
Plugin settings pages were stacked at the bottom of Settings -> Accounts, which put antispam's thresholds and lists under a heading about mail accounts. Each `settings.page` now gets its own entry in the Settings nav: "Antispam filtering" and "Mail filters". Slot gains an optional `title` for this — the host needs a label when it gives a slot an area of its own, and falls back to the plugin name. PluginSlot gains an optional `plugin` filter so a host can render one plugin's bundle rather than every binding for a slot name. Wording: the app calls that folder Spam (i18n `nav.spam`), so the plugin's copy now does too — "filed into Spam", "Move to Spam", "marked as spam". The IMAP special-use stays `junk`, which is what the protocol calls it; only what the user reads changed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SqJYt7jD7oUEkoY68sBZo
This commit is contained in:
@@ -33,7 +33,11 @@ plugin = Plugin(
|
||||
migrations=str(_HERE / "migrations" / "versions"),
|
||||
ui_manifest=UiManifest(
|
||||
slots=[
|
||||
Slot(name="settings.page", bundle=f"{_UI}/settings.js"),
|
||||
Slot(
|
||||
name="settings.page",
|
||||
bundle=f"{_UI}/settings.js",
|
||||
title="Antispam filtering",
|
||||
),
|
||||
# Mounts on every message but renders only for a `banner` verdict —
|
||||
# a spam warning on ordinary mail is worse than no warning at all.
|
||||
Slot(name="message.banner", bundle=f"{_UI}/banner.js"),
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function mount(el, ctx, props) {
|
||||
function render() {
|
||||
const d = busy ? " disabled" : "";
|
||||
el.innerHTML =
|
||||
`<button class="wm-btn-ghost" data-v="spam" title="Move to Junk and teach the filter"${d}>Spam</button>` +
|
||||
`<button class="wm-btn-ghost" data-v="spam" title="Move to Spam and teach the filter"${d}>Spam</button>` +
|
||||
`<button class="wm-btn-ghost" data-v="ham" title="Move back to Inbox and teach the filter"${d}>Not spam</button>`;
|
||||
el.querySelectorAll("[data-v]").forEach((b) =>
|
||||
b.addEventListener("click", (e) => {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default function mount(el, ctx, props) {
|
||||
<strong>Looks like spam</strong>
|
||||
<span class="wm-muted">score ${Number(v.score).toFixed(1)}${why ? ` · ${esc(why)}` : ""}</span>
|
||||
<div class="wm-row">
|
||||
<button class="wm-btn" data-a="junk">Move to Junk</button>
|
||||
<button class="wm-btn" data-a="junk">Move to Spam</button>
|
||||
<button class="wm-btn-ghost" data-a="ham">Not spam</button>
|
||||
<button class="wm-btn-ghost" data-a="trust">Always trust sender</button>
|
||||
</div>
|
||||
|
||||
@@ -78,11 +78,11 @@ export default function mount(el, ctx) {
|
||||
}
|
||||
el.className = "wm-root";
|
||||
el.innerHTML = `
|
||||
<h2 class="wm-h2">Spam filtering</h2>
|
||||
<p class="wm-muted">A second pass over mail your provider already delivered. Nothing is deleted — suspect mail is filed into Junk, and the uncertain middle only gets a warning.</p>
|
||||
<h2 class="wm-h2">Antispam filtering</h2>
|
||||
<p class="wm-muted">A second pass over mail your provider already delivered. Nothing is deleted — suspect mail is filed into Spam, and the uncertain middle only gets a warning.</p>
|
||||
|
||||
<div class="wm-card">
|
||||
<label class="wm-row">Move to Junk at score
|
||||
<label class="wm-row">Move to Spam at score
|
||||
<input class="wm-input" type="number" step="0.5" min="0.5" data-f="move_threshold" value="${settings.move_threshold}">
|
||||
</label>
|
||||
<label class="wm-row">Warn with a banner at score
|
||||
@@ -106,7 +106,7 @@ export default function mount(el, ctx) {
|
||||
|
||||
<div class="wm-card">
|
||||
<strong>Always refuse</strong>
|
||||
<p class="wm-faint">Filed into Junk without asking the engine.</p>
|
||||
<p class="wm-faint">Filed into Spam without asking the engine.</p>
|
||||
<ul class="wm-list">${ruleRows("deny")}</ul>
|
||||
<div class="wm-row"><input class="wm-input" data-new="deny" placeholder="sender@example.com or @example.com"><button class="wm-btn" data-add="deny">Add</button></div>
|
||||
</div>
|
||||
@@ -114,7 +114,7 @@ export default function mount(el, ctx) {
|
||||
<div class="wm-card">
|
||||
<label class="wm-row"><input type="checkbox" data-f="network_checks"${settings.network_checks ? " checked" : ""}> Allow online reputation checks</label>
|
||||
<p class="wm-faint">Off by default. These send hashes of your mail and the links it contains to third-party servers. They also need the modules enabled on the engine itself.</p>
|
||||
<label class="wm-row"><input type="checkbox" data-f="learn_from_provider_junk"${settings.learn_from_provider_junk ? " checked" : ""}> Learn from mail your provider already marked as junk</label>
|
||||
<label class="wm-row"><input type="checkbox" data-f="learn_from_provider_junk"${settings.learn_from_provider_junk ? " checked" : ""}> Learn from mail your provider already marked as spam</label>
|
||||
</div>
|
||||
|
||||
<div class="wm-card"><strong>Activity</strong>${statsBlock()}</div>`;
|
||||
|
||||
@@ -18,6 +18,12 @@ plugin = Plugin(
|
||||
hooks={"message.new": on_message_new},
|
||||
router=router,
|
||||
ui_manifest=UiManifest(
|
||||
slots=[Slot(name="settings.page", bundle="/api/plugins/filters/ui/settings.js")],
|
||||
slots=[
|
||||
Slot(
|
||||
name="settings.page",
|
||||
bundle="/api/plugins/filters/ui/settings.js",
|
||||
title="Mail filters",
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user