Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping colors to categories (proof-of-concept) #591

Open
wants to merge 4 commits into
base: legacy
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
},

"settings.warning": {
"message": "These settings are will allow you to make use of email scheduling via Google Calendar, but there have also been reports about extraneous notification emails being sent. Please test with a small meeting first."
"message": "The settings below allow you to make use of email scheduling via Google Calendar, but there have also been reports about extraneous notification emails being sent. Please test with a small meeting first."
},

"settings.enableEmailInvitations": {
Expand All @@ -180,6 +180,9 @@
"settings.forcePlainText": {
"message": "Force use of plain text in event descriptions"
},
"settings.enableColors": {
"message": "Enable support for event colors (experimental; enabling/disabling reloads all calendars)"
},

"eventdialog.conferenceLabel": {
"message": "Conference:"
Expand Down
33 changes: 33 additions & 0 deletions src/legacy/modules/gdataUI.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ var EXPORTED_SYMBOLS = ["register", "unregister", "recordModule", "recordWindow"

var { ExtensionSupport } = ChromeUtils.import("resource:///modules/ExtensionSupport.jsm");

const Services =
globalThis.Services || ChromeUtils.import("resource://gre/modules/Services.jsm").Services; // Thunderbird 103 compat

var unregisterIds = [];
var unregisterModules = new Set();
var closeWindows = new Set();
Expand Down Expand Up @@ -67,9 +70,39 @@ function register() {
checkMigrateCalendars(window);
},
});

let { doEnableColors, doDisableColors, flushCache, getMessenger } = ChromeUtils.import(
"resource://gdata-provider/legacy/modules/gdataUtils.jsm"
);

let messenger = getMessenger();
messenger.storage.onChanged.addListener((settings, _target) => {
if ("settings.enableColors" in settings) {
// check for true and false explicitly, since `undefined` can also happen
if (settings["settings.enableColors"].newValue === true) {
doEnableColors();
} else if (settings["settings.enableColors"].newValue === false) {
doDisableColors();
}
// We must delete the cache and reload all calendars from the source in order
// to add/remove the color categories. Restarting Thunderbird is insufficient
// because the locally cached calendar entries lack the color information.
flushCache();
}
});

let enableColors = messenger.gdataSyncPrefs.get("settings.enableColors", false);
if (enableColors) {
doEnableColors();
}
}

function unregister() {
let { doDisableColors } = ChromeUtils.import(
"resource://gdata-provider/legacy/modules/gdataUtils.jsm"
);
doDisableColors();

for (let id of unregisterIds) {
ExtensionSupport.unregisterWindowListener(id);
Cu.unload(`resource://gdata-provider/legacy/modules/ui/${id}.jsm`);
Expand Down
63 changes: 61 additions & 2 deletions src/legacy/modules/gdataUtils.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ var EXPORTED_SYMBOLS = [
"JSONToDate",
"monkeyPatch",
"spinEventLoop",
"doEnableColors",
"doDisableColors",
"flushCache",
"getMessenger",
];

Expand Down Expand Up @@ -380,9 +383,21 @@ function EventToJSON(aItem, aOfflineStorage, aIsImport) {
}
setIf(itemData, "status", status);

let categoryList = aItem.getCategories({});
let enableColors = getMessenger().gdataSyncPrefs.get("settings.enableColors", false);
if (enableColors) {
// Take the first category of the form "Google Color dd" for 1 <= dd <= 11 and turn it into a colorId.
// Right now, the rest are treated like all other categories.
// TODO would it make sense / be possible to issue some sort of warning / error here or elsewhere?
let colorCat = categoryList.findIndex((category) => /^Google Color (0[1-9]|1[01])$/.test(category));
if (colorCat > -1) {
itemData.colorId = parseInt(categoryList[colorCat].match(/^Google Color (0[1-9]|1[01])$/)[1]);
categoryList.splice(colorCat, 1);
}
}
// Google does not support categories natively, but allows us to store data
// as an "extendedProperty", so we do here
let categories = cal.category.arrayToString(aItem.getCategories({}));
let categories = cal.category.arrayToString(categoryList);
addExtendedProperty("X-MOZ-CATEGORIES", categories);

// Only parse attendees if they are enabled, due to bug 407961
Expand Down Expand Up @@ -893,10 +908,17 @@ function JSONToEvent(aEntry, aCalendar, aDefaultReminders, aReferenceItem, aMeta
}
}

let categories = cal.category.stringToArray(sharedProps["X-MOZ-CATEGORIES"]);
let enableColors = getMessenger().gdataSyncPrefs.get("settings.enableColors", false);
if (enableColors) {
if (aEntry.colorId) {
// Add color category at the beginning
categories.unshift("Google Color " + aEntry.colorId.toString().padStart(2,'0'));
}
}
// Google does not support categories natively, but allows us to store
// data as an "extendedProperty", and here it's going to be retrieved
// again
let categories = cal.category.stringToArray(sharedProps["X-MOZ-CATEGORIES"]);
item.setCategories(categories);

// Conference data
Expand Down Expand Up @@ -1479,6 +1501,43 @@ function getWXAPI(extension, name, sync = false) {
}
}

function doEnableColors() {
const GOOGLE_COLORS = ["#000", "#7986CB", "#33B679", "#8E24AA", "#E67C73", "#F6BF26",
"#F4511E", "#039BE5", "#616161", "#3F51B5", "#0B8043", "#D50000"];
let calendarCategories = Services.prefs.getStringPref("calendar.categories.names");
for (let i=1; i<=11; i++) {
let paddedIndex = i.toString().padStart(2,'0');
let catName = "Google Color " + paddedIndex;
if (!calendarCategories.includes(catName)) {
calendarCategories += "," + catName;
Services.prefs.setStringPref("calendar.category.color.google_color_" + paddedIndex, GOOGLE_COLORS[i]);
}
}
Services.prefs.setStringPref("calendar.categories.names", calendarCategories);
}

function doDisableColors() {
for (let i=1; i<=11; i++) {
let padded_index = i.toString().padStart(2,'0');
Services.prefs.clearUserPref("calendar.category.color.google_color_" + padded_index);
}
let calendarCategories = Services.prefs.getStringPref("calendar.categories.names");
calendarCategories = calendarCategories.replaceAll(/,Google\sColor\s\d\d/g, "")
Services.prefs.setStringPref("calendar.categories.names", calendarCategories);
}

/**
* Deletes the local Google calendar cache and reloads all Google calendars from the source.
*/
function flushCache() {
let cals = cal.manager.wrappedJSObject.getCalendars();
for (let calendar of cals) {
if (calendar.type == "gdata") {
calendar.mUncachedCalendar.resetLog();
}
}
}

class SyncPrefs {
prefs = {};

Expand Down
20 changes: 12 additions & 8 deletions src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
<meta charset="utf-8">
</head>
<body>
<div class="browser-style">
<input type="checkbox" id="enableAttendees"/>
<label for="enableAttendees" data-l10n-id="settings.enableAttendees"/>
</div>
<div class="browser-style">
<input type="checkbox" id="forcePlainText"/>
<label for="forcePlainText" data-l10n-id="settings.forcePlainText"/>
</div>
<div class="browser-style">
<input type="checkbox" id="enableColors"/>
<label for="enableColors" data-l10n-id="settings.enableColors"/>
</div>
<p data-l10n-id="settings.warning"></p>
<div class="browser-style">
<input type="checkbox" id="enableEmailInvitations"/>
Expand All @@ -13,14 +25,6 @@
<input type="checkbox" id="sendEventNotifications"/>
<label for="sendEventNotifications" data-l10n-id="settings.sendEventNotifications"/>
</div>
<div class="browser-style">
<input type="checkbox" id="enableAttendees"/>
<label for="enableAttendees" data-l10n-id="settings.enableAttendees"/>
</div>
<div class="browser-style">
<input type="checkbox" id="forcePlainText"/>
<label for="forcePlainText" data-l10n-id="settings.forcePlainText"/>
</div>
<script src="options.js"></script>
</body>
</html>
1 change: 1 addition & 0 deletions src/options/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ for (let node of document.querySelectorAll("[data-l10n-id]")) {
"settings.sendEventNotifications": false,
"settings.enableAttendees": false,
"settings.forcePlainText": false,
"settings.enableColors": false,
});

for (let [id, value] of Object.entries(prefs)) {
Expand Down