Compare commits

...

15 Commits

Author SHA1 Message Date
Alphons Joseph 5b3c3e5006 feat: initial changes (not fixed yet) 2026-01-24 17:59:10 +08:00
Seth Burkart c205a52f03 Merge pull request #370 from Jaxx7594/icon
fix: Favicon not showing
2026-01-23 15:33:17 +11:00
SethBurkart123 a6d95f27ed chore: update publish-browser extension 2026-01-23 14:13:11 +11:00
Jaxon Lewis-Wilson f05cd66e88 fix: Favicon not showing 2026-01-23 09:27:14 +08:00
SethBurkart123 a151e7a07e feat: 3.4.13 2026-01-23 08:10:38 +11:00
Seth Burkart 5b590512ee Merge pull request #365 from Jaxx7594/line
fix: House/year box hard failing when house_colour does not exist
2026-01-21 21:52:43 +11:00
Seth Burkart 3ff8ef144a Merge pull request #366 from Jones8683/main
Fix the message of the day being unreadable in light mode
2026-01-21 21:52:20 +11:00
Seth Burkart d9abed1c5d Merge pull request #367 from Jaxx7594/bar
fix: Incorrect styling due to SEQTA update
2026-01-21 21:51:40 +11:00
Jaxon Lewis-Wilson 82a789bbec fix: Global fonts
Prior commit was not actually functional upon review
2026-01-21 12:22:45 +08:00
Jaxon Lewis-Wilson ce6538f850 fix: Global font
Overrides SEQTA's new important tag for font under *{}
2026-01-21 11:40:16 +08:00
Jaxon Lewis-Wilson 979ae7149f fix: Incorrect styling due to SEQTA update 2026-01-21 11:17:49 +08:00
codefactor-io 6e71437fe8 [CodeFactor] Apply fixes to commit 940ecf8 2026-01-19 01:41:43 +00:00
Jones8683 940ecf8714 fix: message of the day unreadable in light mode 2026-01-19 12:09:57 +10:30
Jaxon Lewis-Wilson e0cc2e0fdf fix: House/year box hard failing when house_colour does not exist 2026-01-18 00:11:09 +08:00
SethBurkart123 5a19ef92e8 feat: v3.4.12 2025-12-19 17:04:08 +11:00
12 changed files with 2131 additions and 44 deletions
+1924
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "betterseqtaplus", "name": "betterseqtaplus",
"version": "3.4.11", "version": "3.4.13",
"type": "module", "type": "module",
"description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development add add heaps more features!", "description": "Enhance SEQTA Learn's usability and aesthetics! A fork of BetterSEQTA to continue development add add heaps more features!",
"browserslist": "> 0.5%, last 2 versions, not dead", "browserslist": "> 0.5%, last 2 versions, not dead",
@@ -47,7 +47,7 @@
"mime-types": "^3.0.1", "mime-types": "^3.0.1",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"process": "^0.11.10", "process": "^0.11.10",
"publish-browser-extension": "^3.0.1", "publish-browser-extension": "^4.0.0",
"sass": "^1.85.1", "sass": "^1.85.1",
"sass-loader": "^16.0.5", "sass-loader": "^16.0.5",
"semver": "^7.7.1", "semver": "^7.7.1",
+6 -4
View File
@@ -50,10 +50,12 @@ async function init() {
documentLoadStyle.textContent = documentLoadCSS; documentLoadStyle.textContent = documentLoadCSS;
document.head.appendChild(documentLoadStyle); document.head.appendChild(documentLoadStyle);
const icon = document.querySelector( const icons =
'link[rel*="icon"]', document.querySelectorAll<HTMLLinkElement>('link[rel*="icon"]');
)! as HTMLLinkElement;
icon.href = icon48; // Change the icon icons.forEach((link) => {
link.href = icon48;
});
try { try {
await initializeSettingsState(); await initializeSettingsState();
+1 -1
View File
@@ -108,7 +108,7 @@ function getDefaultValues(): SettingsState {
originalSelectedColor: "", originalSelectedColor: "",
DarkMode: true, DarkMode: true,
animations: !isLowEndDevice, animations: !isLowEndDevice,
assessmentsAverage: true, assessmentsAverage: false,
defaultPage: "home", defaultPage: "home",
shortcuts: [ shortcuts: [
{ {
+12 -14
View File
@@ -57,7 +57,8 @@ select {
transition: 200ms; transition: 200ms;
background: var(--auto-background) !important; background: var(--auto-background) !important;
} }
* { :root * {
font-family: Rubik, sans-serif !important;
--theme-fg-parts: white; --theme-fg-parts: white;
} }
.extension-editor { .extension-editor {
@@ -823,8 +824,8 @@ div > ol:has(.uiFileHandlerWrapper) {
[aria-labelledby="lixycoxs-tab-1"] [minlength="0"] { [aria-labelledby="lixycoxs-tab-1"] [minlength="0"] {
min-height: 128px !important; min-height: 128px !important;
} }
.student #menu > ul::before { body.student #menu > ul::before {
background-image: var(--betterseqta-logo); background-image: var(--betterseqta-logo) !important;
position: -webkit-sticky; position: -webkit-sticky;
position: sticky; position: sticky;
top: 0; top: 0;
@@ -1043,8 +1044,8 @@ html.transparencyEffects
display: none; display: none;
} }
#title { #title {
background: var(--background-primary); background: var(--background-primary) !important;
color: var(--text-primary); color: var(--text-primary) !important;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding-right: 56px !important; padding-right: 56px !important;
@@ -2206,7 +2207,6 @@ div.bar.flat {
border-radius: 12px !important; border-radius: 12px !important;
border: none !important; border: none !important;
box-shadow: none !important; box-shadow: none !important;
color: #fff !important;
padding: 16px !important; padding: 16px !important;
margin: 0 !important; margin: 0 !important;
height: 100% !important; height: 100% !important;
@@ -2214,6 +2214,7 @@ div.bar.flat {
display: flex !important; display: flex !important;
align-items: flex-start !important; align-items: flex-start !important;
overflow: hidden !important; overflow: hidden !important;
color: var(--text-primary) !important;
} }
} }
@@ -3357,7 +3358,6 @@ div.day-empty {
flex-direction: column; flex-direction: column;
color: var(--text-primary); color: var(--text-primary);
transform-origin: center center; transform-origin: center center;
} }
.whatsnewTextContainer.privacyStatement p { .whatsnewTextContainer.privacyStatement p {
margin-bottom: 1.5ex; margin-bottom: 1.5ex;
@@ -3436,7 +3436,6 @@ div.day-empty {
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 500; font-weight: 500;
color: #9a3412; color: #9a3412;
background-color: #ffedd569;
border-radius: 9999px; border-radius: 9999px;
border: 1px solid rgba(253, 186, 140, 0.3); border: 1px solid rgba(253, 186, 140, 0.3);
background-color: #ffedd5; background-color: #ffedd5;
@@ -3813,7 +3812,7 @@ div.day-empty {
font-size: 20px !important; // Nice middle ground - not too big, not too small font-size: 20px !important; // Nice middle ground - not too big, not too small
font-weight: 600 !important; font-weight: 600 !important;
color: var(--text-primary) !important; color: var(--text-primary) !important;
margin: 0 0 12px 0 !important; margin: 0 0 12px !important;
line-height: 1.3 !important; line-height: 1.3 !important;
flex-shrink: 0; flex-shrink: 0;
} }
@@ -3925,7 +3924,6 @@ button.notice-close-btn {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
font-size: 18px;
color: var(--text-primary); color: var(--text-primary);
transition: all 0.2s ease !important; transition: all 0.2s ease !important;
flex-shrink: 0; flex-shrink: 0;
@@ -3983,13 +3981,13 @@ button.notice-close-btn {
font-size: 24px; font-size: 24px;
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
margin: 16px 20px 20px 20px; margin: 16px 20px 20px;
line-height: 1.3; line-height: 1.3;
flex-shrink: 0; flex-shrink: 0;
} }
.notice-modal-body { .notice-modal-body {
padding: 0 20px 20px 20px; padding: 0 20px 20px;
font-size: 15px; font-size: 15px;
line-height: 1.6; line-height: 1.6;
color: var(--text-secondary); color: var(--text-secondary);
@@ -4070,11 +4068,11 @@ button.notice-close-btn {
.notice-modal-title { .notice-modal-title {
font-size: 20px; font-size: 20px;
margin: 12px 16px 16px 16px; margin: 12px 16px 16px;
} }
.notice-modal-body { .notice-modal-body {
padding: 0 16px 16px 16px; padding: 0 16px 16px;
} }
.notice-card { .notice-card {
+1 -1
View File
@@ -14,7 +14,7 @@ const updatedFirefoxManifest = {
}, },
browser_specific_settings: { browser_specific_settings: {
gecko: { gecko: {
id: pkg.author.email, id: "betterseqta@betterseqta.com",
}, },
}, },
}; };
@@ -8,12 +8,16 @@
object-fit: cover; object-fit: cover;
z-index: 4; z-index: 4;
box-shadow: 0 0 0 3px #000000; box-shadow: 0 0 0 3px #000000;
transition: box-shadow 0.05s ease-in-out;
} }
.dark .userInfoImg { .dark .userInfoImg {
box-shadow: 0 0 0 3px #ffffff; box-shadow: 0 0 0 3px #ffffff;
transition: box-shadow 0.05s ease-in-out;
} }
.userInfosvgdiv { @media (prefers-reduced-motion: reduce) {
filter: invert(0) !important; .userInfoImg {
transition: none !important;
}
} }
+9 -2
View File
@@ -147,14 +147,21 @@ export class ThemeManager {
public async initialize(): Promise<void> { public async initialize(): Promise<void> {
console.debug("[ThemeManager] Starting initialization"); console.debug("[ThemeManager] Starting initialization");
try { try {
// Check if theme creator was open during reload const neumorphicThemeId = "9a9786d1-b5fc-4a91-8c7a-f8bf7f7679ad";
const migrationCSS = "#title {\nbackground: transparent !important;\n}";
const theme = (await localforage.getItem(neumorphicThemeId)) as CustomTheme | null;
if (theme && theme.CustomCSS && !theme.CustomCSS.includes("#title {\nbackground: transparent !important;\n}")) {
theme.CustomCSS = theme.CustomCSS + "\n" + migrationCSS;
await localforage.setItem(neumorphicThemeId, theme);
}
const themeCreatorOpen = localStorage.getItem("themeCreatorOpen"); const themeCreatorOpen = localStorage.getItem("themeCreatorOpen");
if (themeCreatorOpen === "true") { if (themeCreatorOpen === "true") {
console.debug( console.debug(
"[ThemeManager] Theme creator was open, clearing preview state", "[ThemeManager] Theme creator was open, clearing preview state",
); );
this.clearPreview(); this.clearPreview();
// Clean up the flag
localStorage.removeItem("themeCreatorOpen"); localStorage.removeItem("themeCreatorOpen");
} }
+7 -1
View File
@@ -27,6 +27,7 @@ import { OpenWhatsNewPopup } from "@/seqta/utils/Openers/OpenWhatsNewPopup";
import { showPrivacyNotification } from "@/seqta/utils/Openers/OpenPrivacyNotification"; import { showPrivacyNotification } from "@/seqta/utils/Openers/OpenPrivacyNotification";
import { updateTimetableTimes } from "@/seqta/utils/updateTimetableTimes"; import { updateTimetableTimes } from "@/seqta/utils/updateTimetableTimes";
import { fixTimetableColours } from "@/seqta/utils/fixTimetableColours";
// JSON content // JSON content
import MenuitemSVGKey from "@/seqta/content/MenuItemSVGKey.json"; import MenuitemSVGKey from "@/seqta/content/MenuItemSVGKey.json";
@@ -99,7 +100,11 @@ export async function finishLoad() {
await showPrivacyNotification(); await showPrivacyNotification();
} }
if (settingsState.justupdated && !document.getElementById("whatsnewbk") && !document.getElementById("privacy-notification")) { if (
settingsState.justupdated &&
!document.getElementById("whatsnewbk") &&
!document.getElementById("privacy-notification")
) {
OpenWhatsNewPopup(); OpenWhatsNewPopup();
} }
} }
@@ -257,6 +262,7 @@ async function LoadPageElements(): Promise<void> {
}, },
async () => { async () => {
await updateTimetableTimes(); await updateTimetableTimes();
await fixTimetableColours();
}, },
); );
+22 -15
View File
@@ -173,28 +173,35 @@ async function updateStudentInfo(students: any) {
); );
}); });
let houseelement1 = document.getElementsByClassName("userInfohouse")[0]; const houseelement = document.getElementsByClassName("userInfohouse")[0] as HTMLElement;
const houseelement = houseelement1 as HTMLElement;
// Fallback to N/A
let text = 'N/A';
const student = students[index] ?? {};
// If student has a house, prefer to show year + house. If no year, only show house.
if (student.house) {
text = `${student.year ?? ""}${student.house}`;
// If house_colour exists, compute colour
if (student.house_colour) {
houseelement.style.background = student.house_colour;
if (students[index]?.house) {
if (students[index]?.house_colour) {
houseelement.style.background = students[index].house_colour;
try { try {
let colorresult = GetThresholdOfColor(students[index]?.house_colour); const colorresult = GetThresholdOfColor(student.house_colour);
houseelement.style.color = houseelement.style.color =
colorresult && colorresult > 300 ? "black" : "white"; colorresult && colorresult > 300 ? "black" : "white";
houseelement.innerText = students[index].year + students[index].house;
} catch (error) {
houseelement.innerText = students[index].house;
}
}
} else {
try {
houseelement.innerText = students[index].year;
} catch (err) { } catch (err) {
houseelement.innerText = "N/A"; // Colour calculation failed, no text colour set
} }
} }
} else if (student.year) {
// No house, only year will be shown
text = student.year;
}
houseelement.innerText = text;
} }
function createNewsButton(fragment: DocumentFragment, menu: HTMLElement) { function createNewsButton(fragment: DocumentFragment, menu: HTMLElement) {
@@ -32,6 +32,19 @@ export function OpenWhatsNewPopup() {
const text = stringToHTML(/* html */ ` const text = stringToHTML(/* html */ `
<div class="whatsnewTextContainer" style="height: 50%;overflow-y: auto;"> <div class="whatsnewTextContainer" style="height: 50%;overflow-y: auto;">
<h1>3.4.13 - Bug Fixes & Styling Improvements</h1>
<li>Fixed house/year box hard failing when house_colour does not exist</li>
<li>Fixed message of the day being unreadable in light mode</li>
<li>Fixed global font styling issues due to SEQTA updates</li>
<li>Fixed styling issues with title bar and other elements</li>
<li>Other minor bug fixes and improvements</li>
<h1>3.4.12 - Privacy Updates & Bug Fixes</h1>
<li>Added privacy statement</li>
<li>Added disclaimer modal to assessment averages switch</li>
<li>Improved popup management system</li>
<li>Other minor bug fixes and improvements</li>
<h1>3.4.11 - New Features & Bug Fixes</h1> <h1>3.4.11 - New Features & Bug Fixes</h1>
<li>Added Background Music plugin</li> <li>Added Background Music plugin</li>
<li>Added empty state for assessments on homepage</li> <li>Added empty state for assessments on homepage</li>
+126
View File
@@ -0,0 +1,126 @@
import { waitForElm } from "./waitForElm";
let timetableObserver: MutationObserver | null = null;
let isOnTimetablePage = false;
let isInitialized = false;
let abortController: AbortController | null = null;
let lastSnapshot: String = "";
function checkIfOnTimetablePage(): boolean {
return window.location.hash.includes("page=/timetable");
}
function startTimetableMonitoring(): void {
if (timetableObserver) return;
const timetablePage = document.querySelector(".timetablepage");
if (!timetablePage) return;
lastSnapshot = Array.from(
timetablePage.querySelectorAll("*"),
(el) => getComputedStyle(el).color,
).join("|");
// Create observer for timetable content changes
timetableObserver = new MutationObserver((mutations) => {
const snapshot = Array.from(
timetablePage.querySelectorAll("*"),
(el) => getComputedStyle(el).color,
).join("|");
if (snapshot !== lastSnapshot) {
// implement colour fix code here
lastSnapshot = snapshot;
}
});
timetableObserver.observe(timetablePage, {
childList: true,
subtree: true,
});
}
function handleUrlChange(): void {
const currentlyOnTimetable = checkIfOnTimetablePage();
if (currentlyOnTimetable !== isOnTimetablePage) {
isOnTimetablePage = currentlyOnTimetable;
if (isOnTimetablePage) {
// Wait a bit for the page to load, then start monitoring
setTimeout(() => {
startTimetableMonitoring();
}, 100);
} else {
stopTimetableMonitoring();
}
} else if (isOnTimetablePage) {
}
}
function startUrlMonitoring(): void {
if (isInitialized) return;
isInitialized = true;
// Create abort controller for cleanup
abortController = new AbortController();
const signal = abortController.signal;
// Listen for hash changes (more efficient than polling)
window.addEventListener("hashchange", handleUrlChange, { signal });
window.addEventListener("popstate", handleUrlChange, { signal });
// Initial check
handleUrlChange();
}
function stopTimetableMonitoring(): void {
if (timetableObserver) {
timetableObserver.disconnect();
timetableObserver = null;
}
}
function stopUrlMonitoring(): void {
if (!isInitialized) return;
isInitialized = false;
// Abort all event listeners at once
if (abortController) {
abortController.abort();
abortController = null;
}
stopTimetableMonitoring();
}
// Initialize monitoring on page load
if (typeof window !== "undefined") {
// Start URL monitoring immediately
startUrlMonitoring();
}
export async function fixTimetableColours(): Promise<void> {
const timetablePage = document.querySelector(".timetablepage");
if (!timetablePage) return;
// Wait for time elements to exist if page is still loading
try {
await waitForElm(".timetablepage .time", true, 10);
} catch {
return;
}
// Start continuous monitoring when this function is called
isOnTimetablePage = checkIfOnTimetablePage();
if (isOnTimetablePage) {
startTimetableMonitoring();
startUrlMonitoring();
}
}
// Cleanup function for when the module is unloaded
export function cleanup(): void {
stopUrlMonitoring();
}