mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
fix today's lessons tweaking out
This commit is contained in:
@@ -3,6 +3,8 @@ interface ElementConfig {
|
||||
action: (element: Element) => void;
|
||||
/** When true, element is not added to processedElements so the action runs every time (e.g. overwriting container content) */
|
||||
alwaysRun?: boolean;
|
||||
/** When true, never add to processedElements so the action can run again after DOM resets (e.g. home day column) */
|
||||
neverMarkProcessed?: boolean;
|
||||
}
|
||||
|
||||
interface ContentConfig {
|
||||
@@ -12,6 +14,12 @@ interface ContentConfig {
|
||||
// Track processed elements to avoid re-randomizing
|
||||
const processedElements = new WeakSet<Element>();
|
||||
|
||||
/** Marks mock-generated `.day` rows so granular rules do not re-randomize them */
|
||||
const MOCK_DAY_ATTR = "data-bsp-mock-day";
|
||||
|
||||
/** Skip MutationObserver-driven reprocessing while we inject the home mock (avoids feedback loops) */
|
||||
let suppressMockMutations = false;
|
||||
|
||||
function debounce(func: Function, wait: number): Function {
|
||||
let timeout: NodeJS.Timeout;
|
||||
return function executedFunction(...args: any[]) {
|
||||
@@ -44,19 +52,19 @@ function getRandomDate(): Date {
|
||||
|
||||
const contentConfig: ContentConfig = {
|
||||
lessonTitle: {
|
||||
selector: ".day h2",
|
||||
selector: `.day:not([${MOCK_DAY_ATTR}]) h2`,
|
||||
action: (element) => {
|
||||
element.textContent = getRandomElement(mockData.subjects);
|
||||
},
|
||||
},
|
||||
teacher: {
|
||||
selector: ".day h3:first-of-type",
|
||||
selector: `.day:not([${MOCK_DAY_ATTR}]) h3:first-of-type`,
|
||||
action: (element) => {
|
||||
element.textContent = getRandomElement(mockData.teachers);
|
||||
},
|
||||
},
|
||||
classroom: {
|
||||
selector: ".day h3:last-of-type",
|
||||
selector: `.day:not([${MOCK_DAY_ATTR}]) h3:last-of-type`,
|
||||
action: (element) => {
|
||||
element.textContent = getRandomElement(mockData.classrooms);
|
||||
},
|
||||
@@ -283,13 +291,28 @@ const contentConfig: ContentConfig = {
|
||||
// Home page: replace entire day with mock schedule (care + 7 lessons 8:55–3:15)
|
||||
homeDayContainer: {
|
||||
selector: "#day-container",
|
||||
alwaysRun: true,
|
||||
neverMarkProcessed: true,
|
||||
action: (element) => {
|
||||
const container = element as HTMLElement;
|
||||
if (!container.closest(".timetable-container")) return; // only on home
|
||||
if (container.classList.contains("loading") || container.innerHTML.trim() === "") {
|
||||
delete container.dataset.bspMockSchedule;
|
||||
return;
|
||||
}
|
||||
if (
|
||||
container.dataset.bspMockSchedule === "1" &&
|
||||
container.querySelector(`[${MOCK_DAY_ATTR}]`)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
suppressMockMutations = true;
|
||||
const schedule = getMockDaySchedule();
|
||||
container.innerHTML = schedule;
|
||||
container.classList.remove("loading");
|
||||
container.dataset.bspMockSchedule = "1";
|
||||
requestAnimationFrame(() => {
|
||||
suppressMockMutations = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -665,7 +688,7 @@ function getMockDaySchedule(): string {
|
||||
return blocks
|
||||
.map(
|
||||
(b, i) =>
|
||||
`<div class="day" style="--item-colour: ${colours[i % colours.length]};">
|
||||
`<div class="day" ${MOCK_DAY_ATTR} style="--item-colour: ${colours[i % colours.length]};">
|
||||
<h2>${b.title}</h2>
|
||||
<h3>${b.teacher}</h3>
|
||||
<h3>${b.room}</h3>
|
||||
@@ -758,12 +781,12 @@ const debouncedProcessElements = debounce(processNewElements, 1);
|
||||
|
||||
function processNewElements() {
|
||||
Object.entries(contentConfig).forEach(([_, config]) => {
|
||||
const { selector, action, alwaysRun } = config;
|
||||
const { selector, action, alwaysRun, neverMarkProcessed } = config;
|
||||
const elements = document.querySelectorAll(selector);
|
||||
elements.forEach((element: Element) => {
|
||||
if (alwaysRun || !processedElements.has(element)) {
|
||||
if (alwaysRun || neverMarkProcessed || !processedElements.has(element)) {
|
||||
action(element);
|
||||
if (!alwaysRun) {
|
||||
if (!alwaysRun && !neverMarkProcessed) {
|
||||
processedElements.add(element);
|
||||
}
|
||||
}
|
||||
@@ -772,7 +795,6 @@ function processNewElements() {
|
||||
}
|
||||
|
||||
let observer: MutationObserver | null = null;
|
||||
let intervalId: NodeJS.Timeout | null = null;
|
||||
|
||||
export default function hideSensitiveContent() {
|
||||
// Initial processing of existing elements
|
||||
@@ -781,6 +803,8 @@ export default function hideSensitiveContent() {
|
||||
// Set up MutationObserver if not already created
|
||||
if (!observer) {
|
||||
observer = new MutationObserver((mutations) => {
|
||||
if (suppressMockMutations) return;
|
||||
|
||||
let shouldProcess = false;
|
||||
|
||||
mutations.forEach((mutation) => {
|
||||
@@ -802,9 +826,25 @@ export default function hideSensitiveContent() {
|
||||
});
|
||||
}
|
||||
|
||||
// Also trigger on large DOM replacements (like page navigation)
|
||||
// Large DOM replacements (e.g. page navigation). Skip only when #day-container gains many *mock* rows (our inject).
|
||||
if (mutation.addedNodes.length > 5 || mutation.removedNodes.length > 5) {
|
||||
shouldProcess = true;
|
||||
const target = mutation.target as Element;
|
||||
if (target.id === "day-container") {
|
||||
for (const node of mutation.addedNodes) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const el = node as Element;
|
||||
if (
|
||||
el.classList?.contains("day") &&
|
||||
!el.hasAttribute(MOCK_DAY_ATTR)
|
||||
) {
|
||||
shouldProcess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldProcess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,13 +873,6 @@ export default function hideSensitiveContent() {
|
||||
attributeFilter: ['class', 'id'] // Watch for class/id changes that might affect our selectors
|
||||
});
|
||||
}
|
||||
|
||||
// Fallback: periodic check for new elements (especially useful for SPA navigation)
|
||||
if (!intervalId) {
|
||||
intervalId = setInterval(() => {
|
||||
debouncedProcessElements();
|
||||
}, 500); // Check every 500ms as a fallback
|
||||
}
|
||||
}
|
||||
|
||||
// Function to stop observing (useful for cleanup)
|
||||
@@ -848,8 +881,4 @@ export function stopHidingSensitiveContent() {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
}
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user