diff options
Diffstat (limited to 'comm/mail/modules/TagUtils.jsm')
-rw-r--r-- | comm/mail/modules/TagUtils.jsm | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/comm/mail/modules/TagUtils.jsm b/comm/mail/modules/TagUtils.jsm new file mode 100644 index 0000000000..05747e7b8c --- /dev/null +++ b/comm/mail/modules/TagUtils.jsm @@ -0,0 +1,152 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + Color: "resource://gre/modules/Color.sys.mjs", +}); + +var EXPORTED_SYMBOLS = ["TagUtils"]; + +var TagUtils = { + loadTagsIntoCSS, + addTagToAllDocumentSheets, + isColorContrastEnough, +}; + +function loadTagsIntoCSS(aDocument) { + let tagSheet = findTagColorSheet(aDocument); + let tagArray = MailServices.tags.getAllTags(); + for (let tag of tagArray) { + // tag.key is the internal key, like "$label1" for "Important". + // For user defined keys with non-ASCII characters, key is + // the MUTF-7 encoded name. + addTagToSheet(tag.key, tag.color, tagSheet); + } +} + +function addTagToAllDocumentSheets(aKey, aColor) { + for (let nextWin of Services.wm.getEnumerator("mail:3pane", true)) { + addTagToSheet(aKey, aColor, findTagColorSheet(nextWin.document)); + } + + for (let nextWin of Services.wm.getEnumerator("mailnews:search", true)) { + addTagToSheet(aKey, aColor, findTagColorSheet(nextWin.document)); + } +} + +function addTagToSheet(aKey, aColor, aSheet) { + if (!aSheet) { + return; + } + + // Add rules to sheet. + let ruleString1; + let ruleString2; + let ruleString3; + let ruleString4; + let selector = MailServices.tags.getSelectorForKey(aKey); + if (!aColor) { + ruleString1 = + ":root[lwt-tree] treechildren::-moz-tree-row(" + + selector + + ", selected, focus) { background-color: " + + "var(--sidebar-highlight-background-color) !important; }"; + ruleString2 = + "treechildren::-moz-tree-cell-text(" + + selector + + ", selected, focus) { color: SelectedItemText !important; }"; + ruleString3 = + "tree:-moz-lwtheme treechildren::-moz-tree-cell-text(" + + selector + + ", selected) { color: currentColor !important; }"; + ruleString4 = + ":root[lwt-tree] treechildren::-moz-tree-cell-text(" + + selector + + ", selected, focus) { color: var(--sidebar-highlight-text-color, " + + "var(--sidebar-text-color)) !important; }"; + } else { + ruleString1 = + "treechildren::-moz-tree-row(" + + selector + + ", selected, focus) { background-color: " + + aColor + + " !important; outline-color: color-mix(in srgb, " + + aColor + + ", black 25%); }"; + ruleString2 = + "treechildren::-moz-tree-cell-text(" + + selector + + ") { color: " + + aColor + + "; }"; + let textColor = "black"; + if (!isColorContrastEnough(aColor)) { + textColor = "white"; + } + ruleString3 = + "treechildren::-moz-tree-cell-text(" + + selector + + ", selected, focus) { color: " + + textColor + + " }"; + ruleString4 = + "treechildren::-moz-tree-image(" + + selector + + ", selected, focus)," + + "treechildren::-moz-tree-twisty(" + + selector + + ", selected, focus) { --select-focus-text-color: " + + textColor + + "; }"; + } + try { + aSheet.insertRule(ruleString1, aSheet.cssRules.length); + aSheet.insertRule(ruleString2, aSheet.cssRules.length); + aSheet.insertRule(ruleString3, aSheet.cssRules.length); + aSheet.insertRule(ruleString4, aSheet.cssRules.length); + } catch (ex) { + aSheet.ownerNode.addEventListener( + "load", + () => addTagToSheet(aKey, aColor, aSheet), + { once: true } + ); + } +} + +function findTagColorSheet(aDocument) { + const cssUri = "chrome://messenger/skin/tagColors.css"; + let tagSheet = null; + for (let sheet of aDocument.styleSheets) { + if (sheet.href == cssUri) { + tagSheet = sheet; + break; + } + } + if (!tagSheet) { + console.error("TagUtils.findTagColorSheet: tagColors.css not found"); + } + return tagSheet; +} + +/* Checks if black writing on 'aColor' background has enough contrast */ +function isColorContrastEnough(aColor) { + // Is a color set? If not, return "true" to use the default color. + if (!aColor) { + return true; + } + // Zero-pad the number just to make sure that it is 8 digits. + let colorHex = ("00000000" + aColor).substr(-8); + let colorArray = colorHex.match(/../g); + let [, cR, cG, cB] = colorArray.map(val => parseInt(val, 16)); + return new lazy.Color(cR, cG, cB).isContrastRatioAcceptable( + new lazy.Color(0, 0, 0), + "AAA" + ); +} |