Skip to content

Commit

Permalink
Add initial column support for Supernova
Browse files Browse the repository at this point in the history
Issue: #35
  • Loading branch information
moisseev committed May 27, 2024
1 parent 7ef6edd commit 7743060
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"ignorePatterns": ["**/vendor/i18n.js"],
"parserOptions": {
"ecmaVersion": 8
"ecmaVersion": 9
},
"plugins": [
"@stylistic",
Expand Down
6 changes: 6 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"spamnessColumnToolTip.label": {
"message": "Click to sort by Rspamd spam score"
},
"spamnessIconColumn.label": {
"message": "Spam visual [Rspamd]"
},
"spamnessInstalled.columnGroup.label": {
"message": "Displaying the 'Spam score' column"
},
Expand Down Expand Up @@ -124,6 +127,9 @@
"spamnessOptions.columnDisplayGroup.note": {
"message": "The feature is incompatible with this Thunderbird version. Supported versions: 78.0 - 110.*."
},
"spamnessOptions.columnDisplayGroup.note-cc": {
"message": "This feature is experimental in this Thunderbird version. The radio buttons affect the default column visibility. Disabling/enabling the extension or restarting Thunderbird is required for the changes to take effect."
},
"spamnessOptions.captionDisplayMessageGroup.label": {
"message": "Message display"
},
Expand Down
6 changes: 6 additions & 0 deletions _locales/ru/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
"spamnessColumnToolTip.label": {
"message": "Сортировать по оценке"
},
"spamnessIconColumn.label": {
"message": "Индикатор спама [Rspamd]"
},
"spamnessInstalled.columnGroup.label": {
"message": "Отображение колонки 'Оценка спама [Rspamd]'"
},
Expand Down Expand Up @@ -120,6 +123,9 @@
"spamnessOptions.columnDisplayGroup.note": {
"message": "Функция несовместима с этой версией Thunderbird. Поддерживаемые версии: 78.0 - 110.*."
},
"spamnessOptions.columnDisplayGroup.note-cc": {
"message": "В данной версии Thunderbird это экспериментальная функция. Радиокнопки управляют видимостью столбцов по умолчанию. Для применения изменений необходимо отключить/включить расширение или перезапустить Thunderbird."
},
"spamnessOptions.captionDisplayMessageGroup.label": {
"message": "Настройки отображения сообщения"
},
Expand Down
69 changes: 68 additions & 1 deletion experiments/scoreColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
var {ExtensionCommon} = ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm");
var {ExtensionSupport} = ChromeUtils.import("resource:///modules/ExtensionSupport.jsm");
var Services = globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services;
var [majorVersion] = Services.appinfo.platformVersion.split(".", 1);
var [majorVersion, minorVersion] = Services.appinfo.platformVersion.split(".", 2).map((v) => parseInt(v, 10));
/* eslint-enable no-var */

const RspamdSpamnessColumn = {};
// Thunderbird Supernova with custom column handlers support
const SupernovaCC = majorVersion > 115 || (majorVersion === 115 && minorVersion >= 10);
const ThreadPaneColumns = SupernovaCC
? ChromeUtils.importESModule("chrome://messenger/content/thread-pane-columns.mjs").ThreadPaneColumns
: null;

// eslint-disable-next-line no-var
var scoreColumn = class extends ExtensionCommon.ExtensionAPI {
Expand Down Expand Up @@ -90,6 +95,60 @@ var scoreColumn = class extends ExtensionCommon.ExtensionAPI {
return Services.prefs.getCharPref(prefName);
},
init() {
function getScore(hdr) {
const score = libCommon.getScoreByHdr(hdr, localStorage.header, true);
return (isNaN(score)) ? "" : score.toFixed(2);
}

function getImageId(hdr) {
const score = libCommon.getScoreByHdr(hdr, localStorage.header, true);
if (localStorage["display-columnImageOnlyForPositive"] && score <= 0)
return "";
return libCommon.getImageSrc(score, true);
}

function addCustomColumn(id, properties) {
ThreadPaneColumns.addCustomColumn(id, {
name: context.extension.localeData.localizeMessage("spamnessColumn.label"),
sortCallback: (hdr) => getScore(hdr) * 1e4 + 1e8,
sortable: true,
...properties
});
}

if (SupernovaCC) {
const iconCellDefinitions = [];
[{alt: "H", name: "ham"}, {alt: "S", name: "spam"}].forEach((c) => {
for (let i = 0; i < 5; i++) {
iconCellDefinitions.push({
alt: c.alt,
id: c.name + i,
title: c.name,
url: extension.getURL("images/" + c.name + i + ".png")
});
}
});

addCustomColumn("spamIconCol", {
hidden: (localStorage["display-column"] === "text"),
icon: true,
iconCallback: getImageId,
iconCellDefinitions: iconCellDefinitions,
iconHeaderUrl: extension.getURL("images/icon12.svg"),
name: context.extension.localeData.localizeMessage("spamnessIconColumn.label"),
resizable: false,
textCallback: true
});

addCustomColumn("spamScoreCol", {
hidden: (localStorage["display-column"] === "image"),
name: context.extension.localeData.localizeMessage("spamnessColumn.label"),
textCallback: getScore
});

return;
}

if (majorVersion > 110) return;

// Listen for the main Thunderbird windows opening.
Expand Down Expand Up @@ -146,6 +205,9 @@ var scoreColumn = class extends ExtensionCommon.ExtensionAPI {
}
});
},
refreshCustomColumn(id) {
ThreadPaneColumns.refreshCustomColumn(id);
},
savePrefFile() {
Services.prefs.savePrefFile(null);
},
Expand All @@ -164,6 +226,11 @@ var scoreColumn = class extends ExtensionCommon.ExtensionAPI {

// eslint-disable-next-line class-methods-use-this
close() {
if (SupernovaCC) {
["spamIconCol", "spamScoreCol"].forEach((c) => ThreadPaneColumns.removeCustomColumn(c));
return;
}

if (majorVersion > 110) return;

libExperiments.removeElements([
Expand Down
10 changes: 10 additions & 0 deletions experiments/scoreColumn.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
"type": "function",
"parameters": []
},
{
"name": "refreshCustomColumn",
"type": "function",
"parameters": [
{
"name": "id",
"type": "string"
}
]
},
{
"name": "setLocalStorage",
"type": "function",
Expand Down
12 changes: 12 additions & 0 deletions images/icon12.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"gecko": {
"id": "[email protected]",
"strict_min_version": "78.0",
"strict_max_version": "116.*"
"strict_max_version": "127.*"
}
},
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"default_locale": "en",
"version": "2.0.0a15",
"version": "2.0.0a16",
"author": "Alexander Moisseev ([email protected])",
"homepage_url": "https://github.com/moisseev/rspamd-spamness",
"icons": {
Expand Down
2 changes: 1 addition & 1 deletion options/options.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ label {
display: flex;
flex-direction: column;
}
#column-display-note {
.column-display-note {
color: black;
background-color: #ffe900;
border-radius: 4px;
Expand Down
3 changes: 2 additions & 1 deletion options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
<form>
<fieldset id="column-display-fieldset">
<legend class="groupbox-title">__MSG_spamnessOptions.captionDisplayColumnGroup.label__</legend>
<div id="column-display-note" hidden>__MSG_spamnessOptions.columnDisplayGroup.note__</div>
<div class="column-display-note" id="column-display-note" hidden>__MSG_spamnessOptions.columnDisplayGroup.note__</div>
<div class="column-display-note" id="column-display-note-cc" hidden>__MSG_spamnessOptions.columnDisplayGroup.note-cc__</div>
<div role="radiogroup">
<p>
<input type="radio" name="columnDisplay" id="columnDisplay_both" value="both">
Expand Down
46 changes: 40 additions & 6 deletions options/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,43 @@

"use strict";

let SupernovaCC = null;
let majorVersion = null;
let minorVersion = null;

async function init() {
browser.runtime.getBrowserInfo().then((browserInfo) => {
const [majorVersion] = browserInfo.version.split(".", 1);
if (majorVersion > 110) {
document.querySelector("#column-display-fieldset").disabled = true;
document.querySelector("#column-display-note").removeAttribute("hidden");
// Add timeout to a promise
function promiseTimeout(promise, timeout, exception) {
let timer = null;
const timeoutPromise = new Promise((_, reject) => {
timer = setTimeout(() => reject(exception), timeout);
});
return Promise.race([promise, timeoutPromise])
.finally(() => clearTimeout(timer));
}

const timeoutError = Symbol("promise timeout");
try {
// In Thunderbird 78, the promise never resolves in this script but works in background.js
const browserInfo = await promiseTimeout(messenger.runtime.getBrowserInfo(), 100, timeoutError);
[majorVersion, minorVersion] = browserInfo.version.split(".", 2).map((v) => parseInt(v, 10));
// Thunderbird Supernova with custom column handlers support
SupernovaCC = majorVersion > 115 || (majorVersion === 115 && minorVersion >= 10);
} catch (e) {
if (e === timeoutError) {
libBackground.error("Timeout occurred while fetching browser info.");
} else {
// Throw other errors
throw e;
}
});
}

if (SupernovaCC) {
document.querySelector("#column-display-note-cc").removeAttribute("hidden");
} else if (majorVersion > 110) {
document.querySelector("#column-display-fieldset").disabled = true;
document.querySelector("#column-display-note").removeAttribute("hidden");
}

const localStorage = await browser.storage.local.get(libBackground.defaultOptions.keys);

Expand Down Expand Up @@ -61,6 +90,11 @@ async function saveOptions(e) {
"display-columnImageOnlyForPositive": document.querySelector("#columnImageOnlyForPositive").checked
});

if (SupernovaCC &&
localStorage["display-columnImageOnlyForPositive"] !==
document.querySelector("#columnImageOnlyForPositive").checked)
browser.scoreColumn.refreshCustomColumn("spamIconCol");

if (!localStorage["trainingButtons-enabled"] && document.querySelector("#trainingButtons-enabled").checked) {
browser.runtime.sendMessage({method: "addTrainButtonsToNormalWindows"});
} else if (localStorage["trainingButtons-enabled"] && !document.querySelector("#trainingButtons-enabled").checked) {
Expand Down
10 changes: 5 additions & 5 deletions scripts/libCommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ var libCommon = {
]
};

libCommon.getImageSrc = function (normalized) {
libCommon.getImageSrc = function (normalized, id) {
let img = null;
let level = null;
if (isNaN(normalized)) {
img = "images/symbol-null.png";
img = "symbol-null";
} else if (normalized < 0) {
level = Math.round(Math.log(Math.abs(normalized) + 1));
level = (level >= 5) ? 4 : level;
img = "images/ham" + level + ".png";
img = "ham" + level;
} else {
level = Math.round(Math.log(normalized + 1));
level = (level >= 5) ? 4 : level;
img = "images/spam" + level + ".png";
img = "spam" + level;
}
return img;
return id ? img : "images/" + img + ".png";
};

libCommon.getUserHeaders = function (header) {
Expand Down

0 comments on commit 7743060

Please sign in to comment.