mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 09:11:06 +00:00
3bac45032d
Co-authored-by: Cursor <[email protected]>
222 lines
6.3 KiB
JavaScript
222 lines
6.3 KiB
JavaScript
/**
|
|
* PAGE context — patches broken menu.update.colours and removes stuck colour-dialog layers.
|
|
*/
|
|
(function () {
|
|
if (window.__bsplusMenuColoursPatched) return;
|
|
|
|
var MENU_UPDATE_COLOURS = "menu.update.colours";
|
|
var SUBJECT_PREFIX = "timetable.subject.colour.";
|
|
var TUTOR_PREFIX = "timetable.tutor.";
|
|
var CLEANUP_FOLLOWUP_MS = 300;
|
|
var cleanupFollowup = null;
|
|
|
|
function isTesStyling() {
|
|
var el = document.getElementById("logo-style");
|
|
return el && el.textContent.indexOf("tesSeqta") !== -1;
|
|
}
|
|
|
|
function dismissStaleDialogs(forceColour) {
|
|
var slide = 0;
|
|
var panes = document.querySelectorAll(".uiSlidePane");
|
|
for (var i = 0; i < panes.length; i++) {
|
|
var p = panes[i];
|
|
if (p.querySelector(".pane.colourChooser")) {
|
|
p.remove();
|
|
slide++;
|
|
continue;
|
|
}
|
|
if (!forceColour && p.classList.contains("shown")) continue;
|
|
if (!p.classList.contains("shown")) {
|
|
p.remove();
|
|
slide++;
|
|
}
|
|
}
|
|
|
|
var modal = 0;
|
|
var containers = document.querySelectorAll(".modaliser-container");
|
|
for (var j = 0; j < containers.length; j++) {
|
|
var c = containers[j];
|
|
var m = c.querySelector(".modaliser");
|
|
if (!m || !m.childElementCount || !c.classList.contains("visible")) {
|
|
c.remove();
|
|
modal++;
|
|
}
|
|
}
|
|
|
|
document.body.classList.remove("clr-open");
|
|
document.documentElement.classList.remove("clr-open");
|
|
return { slideRemoved: slide, modalRemoved: modal };
|
|
}
|
|
|
|
function scheduleCleanup() {
|
|
dismissStaleDialogs(true);
|
|
if (cleanupFollowup) clearTimeout(cleanupFollowup);
|
|
cleanupFollowup = setTimeout(function () {
|
|
cleanupFollowup = null;
|
|
dismissStaleDialogs(true);
|
|
}, CLEANUP_FOLLOWUP_MS);
|
|
}
|
|
|
|
function applyMenuColours() {
|
|
if (!window.user) return;
|
|
var def = isTesStyling() ? "#2b3547" : "#dddddd";
|
|
var items = document.querySelectorAll("#menu li[data-colour]");
|
|
for (var i = 0; i < items.length; i++) {
|
|
var item = items[i];
|
|
var prefName = item.getAttribute("data-colour");
|
|
if (!prefName) continue;
|
|
var pref = window.user.getPreference(prefName);
|
|
item.style.setProperty("--item-colour", (pref && pref.value) || def);
|
|
}
|
|
}
|
|
|
|
function reconcileQuickbars() {
|
|
var fixed = 0;
|
|
var quickbars = document.querySelectorAll(".timetablepage .quickbar.visible");
|
|
for (var i = 0; i < quickbars.length; i++) {
|
|
var qb = quickbars[i];
|
|
var w = qb.querySelector(".wrapper");
|
|
if (!w || !w.childElementCount) {
|
|
qb.classList.remove("visible");
|
|
fixed++;
|
|
}
|
|
}
|
|
if (fixed) {
|
|
try {
|
|
window.msg.send("calendar.quickbar.hide");
|
|
} catch (err) {
|
|
/* ignore */
|
|
}
|
|
}
|
|
return fixed;
|
|
}
|
|
|
|
function findEntry(calendarId, code) {
|
|
if (calendarId) {
|
|
var byId = document.querySelector(
|
|
".timetablepage .entry[data-calendarid=\"" + calendarId + "\"]",
|
|
);
|
|
if (byId) return byId;
|
|
}
|
|
if (!code) return null;
|
|
var entries = document.querySelectorAll(".timetablepage .entry.class");
|
|
for (var i = 0; i < entries.length; i++) {
|
|
var entry = entries[i];
|
|
var titleEl = entry.querySelector(".title");
|
|
var title =
|
|
titleEl && titleEl.textContent ? titleEl.textContent.trim() : "";
|
|
if (title && title.indexOf(code) !== -1) return entry;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function normalizeQuickbarContext(contents) {
|
|
if (!contents) return contents;
|
|
|
|
reconcileQuickbars();
|
|
|
|
var element = contents.element;
|
|
var calendarId =
|
|
(element && element.getAttribute && element.getAttribute("data-calendarid")) ||
|
|
(contents.data && contents.data.calendarid);
|
|
var code = contents.data && contents.data.code;
|
|
var connected =
|
|
element &&
|
|
element.isConnected &&
|
|
typeof document.contains === "function" &&
|
|
document.contains(element);
|
|
|
|
if (!connected) {
|
|
var replacement = findEntry(calendarId, code);
|
|
if (replacement) contents.element = replacement;
|
|
}
|
|
|
|
return contents;
|
|
}
|
|
|
|
function isColourPref(handle) {
|
|
return (
|
|
typeof handle === "string" &&
|
|
(handle.indexOf(SUBJECT_PREFIX) === 0 || handle.indexOf(TUTOR_PREFIX) === 0)
|
|
);
|
|
}
|
|
|
|
function onMenuColourUpdate() {
|
|
try {
|
|
applyMenuColours();
|
|
} catch (err) {
|
|
console.error("[BetterSEQTA+] menu.update.colours failed:", err);
|
|
}
|
|
scheduleCleanup();
|
|
reconcileQuickbars();
|
|
}
|
|
|
|
function neutralizeBrokenListeners(msg) {
|
|
var listeners = msg.listeners && msg.listeners[MENU_UPDATE_COLOURS];
|
|
if (!listeners) return;
|
|
for (var i = 0; i < listeners.length; i++) {
|
|
if (listeners[i]) listeners[i].fn = onMenuColourUpdate;
|
|
}
|
|
}
|
|
|
|
function patchMsg(msg) {
|
|
if (!msg || msg.__bsplusPatched) return;
|
|
|
|
var send = msg.send.bind(msg);
|
|
var register = msg.register.bind(msg);
|
|
|
|
msg.send = function (handle, contents, suppressLogs, noRecord) {
|
|
if (handle === MENU_UPDATE_COLOURS) {
|
|
onMenuColourUpdate();
|
|
return;
|
|
}
|
|
if (isColourPref(handle)) {
|
|
var result = send(handle, contents, suppressLogs, noRecord);
|
|
scheduleCleanup();
|
|
reconcileQuickbars();
|
|
return result;
|
|
}
|
|
if (handle === "calendar.quickbar.class") {
|
|
return send(
|
|
handle,
|
|
normalizeQuickbarContext(contents),
|
|
suppressLogs,
|
|
noRecord,
|
|
);
|
|
}
|
|
return send(handle, contents, suppressLogs, noRecord);
|
|
};
|
|
|
|
msg.register = function (handle, callback, clear, ignoreHistory) {
|
|
if (handle === MENU_UPDATE_COLOURS) {
|
|
return register(handle, onMenuColourUpdate, clear, ignoreHistory);
|
|
}
|
|
return register(handle, callback, clear, ignoreHistory);
|
|
};
|
|
|
|
neutralizeBrokenListeners(msg);
|
|
msg.__bsplusPatched = true;
|
|
}
|
|
|
|
function tryPatch() {
|
|
if (window.__bsplusMenuColoursPatched) return true;
|
|
if (!window.msg || !window.msg.send) return false;
|
|
patchMsg(window.msg);
|
|
window.__bsplusMenuColoursPatched = true;
|
|
return true;
|
|
}
|
|
|
|
if (!tryPatch()) {
|
|
var interval = setInterval(function () {
|
|
if (tryPatch()) {
|
|
clearInterval(interval);
|
|
} else if (window.msg) {
|
|
neutralizeBrokenListeners(window.msg);
|
|
}
|
|
}, 25);
|
|
setTimeout(function () {
|
|
clearInterval(interval);
|
|
}, 120000);
|
|
}
|
|
})();
|