Fix folder handling for TB 121

This commit is contained in:
Ximi1970
2023-12-16 19:11:50 +01:00
parent 2cb5a2e656
commit 3e0a0474f3
17 changed files with 322 additions and 325 deletions

View File

@@ -13,7 +13,7 @@ depends=(
'qt6-wayland'
'gnome-shell-extension-appindicator'
'thunderbird>=91'
'thunderbird<121'
'thunderbird<122'
)
makedepends=(
'git'

View File

@@ -13,7 +13,7 @@ depends=(
'qt6-wayland'
'kstatusnotifieritem'
'thunderbird>=91'
'thunderbird<121'
'thunderbird<122'
)
makedepends=(
'git'

View File

@@ -12,7 +12,7 @@ depends=(
'qt6-base'
'qt6-wayland'
'thunderbird>=91'
'thunderbird<121'
'thunderbird<122'
)
makedepends=(
'git'

View File

@@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 4.1.16), zip, g++, libx11-dev, qt5-qmake, qtbase5-d
Package: systray-x-gnome
Architecture: any
Depends: ${shlibs:Depends}, gnome-shell-extension-appindicator, thunderbird (>= 1:91), thunderbird (< 1:121)
Depends: ${shlibs:Depends}, gnome-shell-extension-appindicator, thunderbird (>= 1:91), thunderbird (< 1:122)
Description: SysTray-X is a system tray extension for Thunderbird (GNOME).
This version is optimized for the GNOME desktop.
The add-on uses the WebExtension API's to control an external system

View File

@@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 4.1.16), zip, g++, libx11-dev, qt5-qmake, qtbase5-d
Package: systray-x
Architecture: any
Depends: ${shlibs:Depends}, thunderbird (>= 1:91), thunderbird (< 1:121)
Depends: ${shlibs:Depends}, thunderbird (>= 1:91), thunderbird (< 1:122)
Description: SysTray-X is a system tray extension for Thunderbird (KDE).
This version is optimized for the KDE desktop.
The add-on uses the WebExtension API's to control an external system

View File

@@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 4.1.16), zip, g++, libx11-dev, qt5-qmake, qtbase5-d
Package: systray-x-minimal
Architecture: any
Depends: ${shlibs:Depends}, thunderbird (>= 1:91), thunderbird (< 1:121)
Depends: ${shlibs:Depends}, thunderbird (>= 1:91), thunderbird (< 1:122)
Description: SysTray-X is a system tray extension for Thunderbird (non-GNOME,non-KDE).
This version is for non-KDE and non-GNOME desktops.
The add-on uses the WebExtension API's to control an external system

View File

@@ -43,10 +43,10 @@ BuildRequires: libqt5-qtx11extras-devel
BuildRequires: pkgconfig(x11)
%if 0%{?fedora_version}
Requires: thunderbird >= 91
Requires: thunderbird < 121
Requires: thunderbird < 122
%else
Requires: MozillaThunderbird >= 91
Requires: MozillaThunderbird < 121
Requires: MozillaThunderbird < 122
%endif
%if 0%{?suse_version} > 1600 || 0%{?fedora_version} > 39
%if 0%{?fedora_version}

View File

@@ -56,7 +56,7 @@ Requires: thunderbird >= 91
Requires: thunderbird < 121
%else
Requires: MozillaThunderbird >= 91
Requires: MozillaThunderbird < 121
Requires: MozillaThunderbird < 122
%endif
%if 0%{?suse_version} > 1600 || 0%{?fedora_version} > 39
%if 0%{?fedora_version}

View File

@@ -43,10 +43,10 @@ BuildRequires: libqt5-qtx11extras-devel
BuildRequires: pkgconfig(x11)
%if 0%{?fedora_version} || 0%{?centos_version}
Requires: thunderbird >= 91
Requires: thunderbird < 121
Requires: thunderbird < 122
%else
Requires: MozillaThunderbird >= 91
Requires: MozillaThunderbird < 121
Requires: MozillaThunderbird < 122
%endif
%if 0%{?suse_version} > 1600 || 0%{?fedora_version} > 39
%if 0%{?fedora_version}

View File

@@ -8,7 +8,6 @@
</head>
<body>
<script src="js/defaults.js"></script>
<script src="js/folderTree.js"></script>
<h3>Background</h3>
<p>Background HTML</p>

View File

@@ -34,7 +34,6 @@ SysTrayX.Info = {
SysTrayX.Messaging = {
startupDelayFinished: false,
accounts: [],
folderTree: {},
countType: "0",
showNewIndicator: "false",
closeType: "1",
@@ -102,17 +101,8 @@ SysTrayX.Messaging = {
browser.accounts.onDeleted.addListener(SysTrayX.Messaging.accountDeleted);
}
// Get all accounts
SysTrayX.Messaging.accounts = await browser.accounts.list(false);
// Fill the sub folders using the folders API, they are not same...
for (let i = 0; i < SysTrayX.Messaging.accounts.length; ++i) {
const subFolders = await browser.folders.getSubFolders(
SysTrayX.Messaging.accounts[i],
true
);
SysTrayX.Messaging.accounts[i].folders = subFolders;
}
// Get the accounts and subfolders
SysTrayX.Messaging.accounts = await browser.accounts.list();
console.debug("Accounts: " + JSON.stringify(SysTrayX.Messaging.accounts));
@@ -318,26 +308,46 @@ SysTrayX.Messaging = {
// Count the initial unread messages
for (const filter of SysTrayX.Messaging.filters) {
for (const path of filter.folders) {
const folder = {
accountId: filter.accountId,
path: path,
};
const accountId = filter.accountId;
for (const storedFolder of filter.folders) {
let path;
let folderParam;
if (typeof(storedFolder) === "string") {
// Filters pre TB 121
path = storedFolder;
folderParam = {
accountId: accountId,
path: storedFolder,
};
} else {
// Filters TB 121
if (storedFolder.mailFolderId === undefined) {
// TB 121 filter setup but older TB
path = storedFolder.path;
folderParam = {
accountId: accountId,
path: path,
};
} else {
path = storedFolder.path;
folderParam = storedFolder.mailFolderId;
}
}
let mailFolderInfo = {};
try {
mailFolderInfo = await browser.folders.getFolderInfo(folder);
mailFolderInfo = await browser.folders.getFolderInfo(folderParam);
} catch (err) {
console.debug("Filter error: " + err);
console.debug("Filter error: " + JSON.stringify(folder));
}
if (mailFolderInfo.unreadMessageCount !== undefined) {
if (SysTrayX.Messaging.unread[folder.accountId] === undefined) {
SysTrayX.Messaging.unread[folder.accountId] = {};
if (SysTrayX.Messaging.unread[accountId] === undefined) {
SysTrayX.Messaging.unread[accountId] = {};
}
SysTrayX.Messaging.unread[folder.accountId][folder.path] =
SysTrayX.Messaging.unread[accountId][path] =
mailFolderInfo.unreadMessageCount;
}
}
@@ -472,110 +482,6 @@ SysTrayX.Messaging = {
}
},
//
// Callback for folder changes
//
updateFilters: function (rootFolder, parentFolder, folder, added) {
const oldFolders = SysTrayX.Messaging.folderTree[rootFolder];
const oldPaths = getFolderPaths(oldFolders);
browser.accounts.list().then(
(accounts) => {
this.updateFiltersCallback(
rootFolder,
parentFolder,
folder,
added,
oldFolders,
oldPaths,
accounts
);
},
() => console.log("Failed to get the accounts")
);
},
updateFiltersCallback: async function (
rootFolder,
parentFolder,
folder,
added,
oldFolders,
oldPaths,
accounts
) {
// Get new folder tree
const folderTree = getFolderTree(accounts, SysTrayX.Info.browserInfo);
const newFolders = folderTree[rootFolder];
const newPaths = getFolderPaths(newFolders);
const changes = findFolderPathsDiff(oldPaths, newPaths).filter((change) =>
change.endsWith(parentFolder + "/" + folder)
);
if (changes.length === 1 && added) {
// Folder has beeen added
const addedFolder = changes[0];
// Is parent selected?
const parentAddedFolder = addedFolder.substring(
0,
addedFolder.lastIndexOf("/")
);
const parentSelected = findFolderPath(
SysTrayX.Messaging.filters,
parentAddedFolder
);
if (parentSelected) {
// Add the new folder to the filters
const newFilter = {
...parentSelected,
folder: {
...parentSelected.folder,
path: changes[0],
name: changes[0].substring(changes[0].lastIndexOf("/") + 1),
},
};
if (
SysTrayX.Messaging.filters.filter(
(filter) => filter.folder.path === newFilter.folder.path
).length === 0
) {
SysTrayX.Messaging.filters.push(newFilter);
// Store the new filters
await storage().set({
filters: SysTrayX.Messaging.filters,
});
}
}
} else if (changes.length === 1 && !added) {
// Folder has been removed, remove also all children
const filters = SysTrayX.Messaging.filters.filter(
(filter) => !filter.folder.path.startsWith(changes[0])
);
if (filters.length !== SysTrayX.Messaging.filters.length) {
// Remove found filters (and children) from the filters
SysTrayX.Messaging.filters = filters;
// Store the new filters
await storage().set({
filters: SysTrayX.Messaging.filters,
});
}
}
// Store the new accounts and folder tree
SysTrayX.Messaging.accounts = accounts;
SysTrayX.Messaging.folderTree = folderTree;
},
requestOptions: function () {
SysTrayX.Link.postSysTrayXMessage({ optionsRequest: true });
},

View File

@@ -219,11 +219,44 @@ async function getIcon() {
}
}
//
// Find a path in the account folder tree
//
function findFolder(rootFolder, path) {
function traverse(folder) {
if (folder === undefined) {
return undefined;
}
if (folder.path === path) {
return folder;
}
if (folder.subFolders === undefined) {
return undefined;
}
for (let sub of folder.subFolders) {
const found = traverse(sub);
if( found !== undefined ) {
return found;
}
}
return undefined;
}
const found = traverse(rootFolder);
return found;
}
//
// Get filters
//
async function getFilters() {
function resolve(result) {
async function resolve(result) {
let filters = result.filters || undefined;
if (filters === undefined || filters.length === 0) {
@@ -234,19 +267,22 @@ async function getFilters() {
filters = [];
for (const account of SysTrayX.Messaging.accounts) {
const inbox = account.folders.filter(
(folder) => folder.type === "inbox"
);
let inbox;
if (account.rootFolder !== undefined) {
inbox = account.rootFolder.subFolders.filter(
(folder) => folder.type === "inbox"
);
} else {
inbox = account.folders.filter(
(folder) => folder.type === "inbox"
);
}
if (inbox.length > 0) {
let folder = {};
// console.debug("Folder 91+: " + JSON.stringify(inbox[0]));
filters.push({
accountId: inbox[0].accountId,
version: SysTrayX.Info.version,
folders: [inbox[0].path],
folders: [{mailFolderId: inbox[0].id, path: inbox[0].path}],
});
}
}
@@ -254,6 +290,101 @@ async function getFilters() {
console.debug("Force new filters: " + JSON.stringify(filters));
} else {
console.debug("Stored filters: " + JSON.stringify(filters));
if (filters[0].folders.length > 0) {
if (typeof(filters[0].folders[0]) === "string") {
console.debug("Conversion needed");
// Convert the filter folder path list to an object
// containing at least the path and if available the mail folder id (TB 121 and newer)
const newFilters = [];
for (const account of SysTrayX.Messaging.accounts) {
const filter = filters.filter(
(filter) => filter.accountId === account.id
);
console.debug("Found filters: " + filter.length);
console.debug("Found filter: " + JSON.stringify(filter));
if (filter.length === 1) {
let newFilter = {
accountId: filter[0].accountId,
version: SysTrayX.Info.version,
folders: []
};
for (const path of filter[0].folders) {
const accountFolder = findFolder(account.rootFolder, path)
if (accountFolder !== undefined)
{
newFilter.folders.push({mailFolderId: accountFolder.id, path: accountFolder.path});
}
}
newFilters.push(newFilter);
}
}
filters = newFilters;
console.debug("Force new filters: " + JSON.stringify(filters));
// Save the new filters
await storage().set({
filters: filters,
});
} else {
if (filters[0].folders[0].mailFolderId === undefined &&
SysTrayX.Info.browserInfo.majorVersion >= 121) {
console.debug("Update needed");
// Update filter folder object
// with the the mail folder id
const newFilters = [];
for (const account of SysTrayX.Messaging.accounts) {
const filter = filters.filter(
(filter) => filter.accountId === account.id
);
console.debug("Found filters: " + filter.length);
console.debug("Found filter: " + JSON.stringify(filter));
if (filter.length === 1) {
let newFilter = {
accountId: filter[0].accountId,
version: SysTrayX.Info.version,
folders: []
};
for (const folder of filter[0].folders) {
const accountFolder = findFolder(account.rootFolder, folder.path)
if (accountFolder !== undefined)
{
newFilter.folders.push({mailFolderId: accountFolder.id, path: accountFolder.path});
}
}
newFilters.push(newFilter);
}
}
filters = newFilters;
console.debug("Force new filters: " + JSON.stringify(filters));
// Save the new filters
await storage().set({
filters: filters,
});
}
}
}
}
return filters;
@@ -328,11 +459,23 @@ function isFolderInFilters(folder) {
);
if (accountIndex !== -1) {
return (
SysTrayX.Messaging.filters[accountIndex].folders.filter(
(path) => path === folder.path
).length > 0
);
const folders = SysTrayX.Messaging.filters[accountIndex].folders;
if (folders[0] === "string") {
// Filters pre TB 121
return (
folders.filter(
(path) => path === folder.path
).length > 0
);
} else {
// Filters TB 121
return (
folders.map(f => f.path).filter(
(path) => path === folder.path
).length > 0
);
}
} else {
return false;
}
@@ -347,11 +490,23 @@ function isParentFolderInFilters(folder) {
);
if (accountIndex !== -1) {
return (
SysTrayX.Messaging.filters[accountIndex].folders.filter(
(path) => path === parentPath
).length > 0
);
const folders = SysTrayX.Messaging.filters[accountIndex].folders;
if (folders[0] === "string") {
// Filters pre TB 121
return (
folders.filter(
(path) => path === parentPath
).length > 0
);
} else {
// Filters TB 121
return (
folders.map(f => f.path).filter(
(path) => path === parentPath
).length > 0
);
}
} else {
return false;
}
@@ -365,7 +520,14 @@ async function deleteFolderFromFilters(folder) {
if (accountIndex !== -1) {
const account = SysTrayX.Messaging.filters[accountIndex];
account.folders = account.folders.filter((path) => path !== folder.path);
if (account.folders[0] === "string" ) {
// Filters pre TB 121
account.folders = account.folders.filter((path) => path !== folder.path);
} else {
// Filters TB 121
account.folders = account.folders.filter((f) => f.path !== folder.path);
}
// Store the new filters
await storage().set({
@@ -391,7 +553,12 @@ async function addFolderToFilters(newFolder) {
if (accountIndex !== -1) {
const account = SysTrayX.Messaging.filters[accountIndex];
account.folders.push(newFolder.path);
if (account.folders[0] === "string" ) {
account.folders.push(newFolder.path);
} else {
account.folders.push({mailFolderId: newFolder.id, path: newFolder.path});
}
// Store the new filter
await storage().set({
@@ -403,42 +570,65 @@ async function addFolderToFilters(newFolder) {
// Collect unread mail
const collectUnreadMail = async () => {
for (const filter of SysTrayX.Messaging.filters) {
for (const path of filter.folders) {
const folder = {
accountId: filter.accountId,
path: path,
};
const accountId = filter.accountId;
for (const storedFolder of filter.folders) {
let mailFolderInfo = {};
try {
mailFolderInfo = await browser.folders.getFolderInfo(folder);
} catch (err) {
//console.debug("Filter error: " + err);
//console.debug("Filter error: " + JSON.stringify(folder));
// Get all accounts
SysTrayX.Messaging.accounts = await browser.accounts.list(false);
let path;
if (typeof(storedFolder) === "string") {
// Filters pre TB 121
path = storedFolder;
// Check the filters for the accounts
SysTrayX.Messaging.accountFilterCheck();
try {
mailFolderInfo = await browser.folders.getFolderInfo({
accountId: accountId,
path: storedFolder,
});
} catch (err) {
//console.debug("Filter error: " + err);
//console.debug("Filter error: " + JSON.stringify(folder));
// Get all accounts
SysTrayX.Messaging.accounts = await browser.accounts.list();
// Check the filters for the accounts
SysTrayX.Messaging.accountFilterCheck();
}
} else {
// Filters TB 121
path = storedFolder.path;
try {
mailFolderInfo = await browser.folders.getFolderInfo(storedFolder.mailFolderId);
} catch (err) {
//console.debug("Filter error: " + err);
//console.debug("Filter error: " + JSON.stringify(folder));
// Get all accounts
SysTrayX.Messaging.accounts = await browser.accounts.list();
// Check the filters for the accounts
SysTrayX.Messaging.accountFilterCheck();
}
}
if (mailFolderInfo.unreadMessageCount !== undefined) {
if (SysTrayX.Messaging.unread[folder.accountId] === undefined) {
SysTrayX.Messaging.unread[folder.accountId] = {};
if (SysTrayX.Messaging.unread[accountId] === undefined) {
SysTrayX.Messaging.unread[accountId] = {};
}
if (SysTrayX.Messaging.new[folder.accountId] === undefined) {
SysTrayX.Messaging.new[folder.accountId] = {};
if (SysTrayX.Messaging.new[accountId] === undefined) {
SysTrayX.Messaging.new[accountId] = {};
}
if (
SysTrayX.Messaging.new[folder.accountId][folder.path] === undefined
SysTrayX.Messaging.new[accountId][path] === undefined
) {
SysTrayX.Messaging.new[folder.accountId][folder.path] = [];
SysTrayX.Messaging.new[accountId][path] = [];
}
SysTrayX.Messaging.unread[folder.accountId][folder.path] =
SysTrayX.Messaging.unread[accountId][path] =
mailFolderInfo.unreadMessageCount;
}
}
@@ -457,7 +647,16 @@ const sendMailCountPre115 = () => {
let newCount = 0;
SysTrayX.Messaging.filters.forEach((filter) => {
const accountId = filter.accountId;
filter.folders.forEach((path) => {
filter.folders.forEach((storedFolder) => {
let path;
if (typeof(storedFolder) === "string") {
// Filters pre TB 121
path = storedFolder;
} else {
// Filters TB 121
path = storedFolder.path;
}
if (SysTrayX.Messaging.unread[accountId] !== undefined) {
if (SysTrayX.Messaging.unread[accountId][path] !== undefined) {
unreadCount = unreadCount + SysTrayX.Messaging.unread[accountId][path];
@@ -496,14 +695,21 @@ const sendMailCount = async () => {
// Get both unread and new message count
for (const filter of SysTrayX.Messaging.filters) {
for (const path of filter.folders) {
const folder = {
accountId: filter.accountId,
path: path,
};
for (const storedFolder of filter.folders) {
let listParam;
if (typeof(storedFolder) === "string") {
// Filters pre TB 121
listParam = {
accountId: filter.accountId,
path: storedFolder,
};
} else {
// Filters TB 121
listParam = storedFolder.mailFolderId;
}
async function* listMessages(folder) {
let page = await messenger.messages.list(folder);
async function* listMessages(listParam) {
let page = await messenger.messages.list(listParam);
for (let message of page.messages) {
yield message;
}
@@ -516,7 +722,7 @@ const sendMailCount = async () => {
}
}
let messages = listMessages(folder);
let messages = listMessages(listParam);
for await (let message of messages) {
if( message.new )
{
@@ -535,11 +741,18 @@ const sendMailCount = async () => {
// Only unread count
for (const filter of SysTrayX.Messaging.filters) {
for (const path of filter.folders) {
const folder = {
accountId: filter.accountId,
path: path,
};
for (const storedFolder of filter.folders) {
let folderParam;
if (typeof(storedFolder) === "string") {
// Filters pre TB 121
folderParam = {
accountId: filter.accountId,
path: storedFolder,
};
} else {
// Filters TB 121
folderParam = storedFolder.mailFolderId;
}
let mailFolderInfo = {};
try {
@@ -549,7 +762,7 @@ const sendMailCount = async () => {
//console.debug("Filter error: " + JSON.stringify(folder));
// Get all accounts
SysTrayX.Messaging.accounts = await browser.accounts.list(false);
SysTrayX.Messaging.accounts = await browser.accounts.list();
// Check the filters for the accounts
SysTrayX.Messaging.accountFilterCheck();

View File

@@ -1,124 +0,0 @@
//
// Create folder tree from accounts
//
function getFolderTree(mailAccounts, browserInfo) {
function traverse(accountName, path, folders) {
if (!folders) {
return;
}
for (let f of folders) {
f.accountName = accountName;
f.path = path + "/" + f.name;
traverse(accountName, path + "/" + f.name, f.subFolders);
}
}
function createFolderTree(accountName, folders) {
traverse(accountName, "", folders);
return folders;
}
let accounts = new Object();
for (let i = 0; i < mailAccounts.length; i++) {
if (false) {
console.debug("Accounts id: " + mailAccounts[i].id);
console.debug("Accounts name: " + mailAccounts[i].name);
console.debug("Accounts type: " + mailAccounts[i].type);
for (let j = 0; j < mailAccounts[i].folders.length; j++) {
console.debug(
"Accounts folder path: " + mailAccounts[i].folders[j].path
);
console.debug(
"Accounts folder name: " + mailAccounts[i].folders[j].name
);
console.debug(
"Accounts folder type: " + mailAccounts[i].folders[j].type
);
}
}
if (!accounts[mailAccounts[i].type]) {
accounts[mailAccounts[i].type] = [];
}
accounts[mailAccounts[i].type].push({
id: mailAccounts[i].id,
name: mailAccounts[i].name,
folders: mailAccounts[i].folders,
});
}
/*
* Build tree
*/
let folderTree = {};
for (let prop in accounts) {
if (accounts[prop]) {
for (let i = 0; i < accounts[prop].length; ++i) {
// Create a usable folder tree
const folders = createFolderTree(
accounts[prop][i].name,
accounts[prop][i].folders
);
// Store the tree
folderTree[accounts[prop][i].name] = folders;
}
}
}
return folderTree;
}
//
// Create a paths array from the folder tree
//
function getFolderPaths(folders) {
function traverse(folders) {
if (!folders) {
return;
}
for (let f of folders) {
paths.push(f.path);
traverse(f.subFolders);
}
}
let paths = [];
traverse(folders);
return paths;
}
//
// Find the difference between two path arrays
//
function findFolderPathsDiff(paths1, paths2) {
let diff = [];
paths1.forEach((path) => {
if (paths2.includes(path) === false) {
diff.push(path);
}
});
paths2.forEach((path) => {
if (paths1.includes(path) === false) {
diff.push(path);
}
});
return diff;
}
//
// Is the path in the filter folder list?
//
function findFolderPath(filters, path) {
for (const filter of filters) {
if (filter.folder.path === path) {
return filter;
}
}
return undefined;
}

View File

@@ -36,7 +36,7 @@ SysTrayX.Accounts = {
}
}
traverse("", folders);
traverse(folders);
return folders;
}
@@ -150,6 +150,7 @@ SysTrayX.Accounts = {
JSON.stringify({
accountName: element.accountName,
accountId: element.accountId,
mailFolderId: element.id,
type: element.type !== undefined ? element.type : "",
path: element.path,
name: element.originalName

View File

@@ -9,11 +9,12 @@
var { ExtensionCommon } = ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm");
// You probably already know what this does.
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
// var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
// A helpful class for listening to windows opening and closing.
var { ExtensionSupport } = ChromeUtils.import("resource:///modules/ExtensionSupport.jsm");
/**
* This object is just what we're using to listen for toolbar clicks. The implementation
* isn't what this example is about, but you might be interested as it's a common pattern.

View File

@@ -10,7 +10,7 @@
"gecko": {
"id": "systray-x@Ximi1970",
"strict_min_version": "91.0",
"strict_max_version": "120.*"
"strict_max_version": "121.*"
}
},

View File

@@ -38,7 +38,8 @@ SysTrayX.SaveOptions = {
folders.forEach((folder) => {
const mailFolderExt = JSON.parse(folder.value);
filters[filters.length - 1].folders.push(mailFolderExt.path);
filters[filters.length - 1].folders.push({
mailFolderId: mailFolderExt.mailFolderId, path: mailFolderExt.path});
});
}
}