mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c613f4938 | |||
| 04843a90fe | |||
| 834d585ac7 | |||
| 343fa7ca9f | |||
| e049f34a5e |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "betterseqtaplus",
|
"name": "betterseqtaplus",
|
||||||
"version": "3.5.1",
|
"version": "3.5.3",
|
||||||
"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",
|
||||||
|
|||||||
+6
-1
@@ -50,7 +50,12 @@ if (document.childNodes[1]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
if (hasSEQTAText && document.title.includes("SEQTA Learn") && !IsSEQTAPage) {
|
if (
|
||||||
|
hasSEQTAText &&
|
||||||
|
(document.title.includes("SEQTA Learn") ||
|
||||||
|
document.title.includes("SEQTA Engage")) &&
|
||||||
|
!IsSEQTAPage
|
||||||
|
) {
|
||||||
IsSEQTAPage = true;
|
IsSEQTAPage = true;
|
||||||
console.info("[BetterSEQTA+] Verified SEQTA Page");
|
console.info("[BetterSEQTA+] Verified SEQTA Page");
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -6,7 +6,10 @@ function reloadSeqtaPages() {
|
|||||||
const result = browser.tabs.query({});
|
const result = browser.tabs.query({});
|
||||||
function open(tabs: any) {
|
function open(tabs: any) {
|
||||||
for (let tab of tabs) {
|
for (let tab of tabs) {
|
||||||
if (tab.title.includes("SEQTA Learn")) {
|
if (
|
||||||
|
tab.title?.includes("SEQTA Learn") ||
|
||||||
|
tab.title?.includes("SEQTA Engage")
|
||||||
|
) {
|
||||||
browser.tabs.reload(tab.id);
|
browser.tabs.reload(tab.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import * as pdfjs from "pdfjs-dist";
|
||||||
|
import browser from "webextension-polyfill";
|
||||||
|
import pdfWorkerHref from "pdfjs-dist/build/pdf.worker.min.mjs?url";
|
||||||
|
import pdfLegacyHref from "pdfjs-dist/legacy/build/pdf.min.mjs?url";
|
||||||
|
|
||||||
|
function extensionAssetUrl(viteAssetHref: string): string {
|
||||||
|
const path = viteAssetHref.replace(/^\/+/, "");
|
||||||
|
return browser.runtime.getURL(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
let workerConfigured = false;
|
||||||
|
|
||||||
|
/** Required before pdfjs spawns a worker (content-script / extension isolate). */
|
||||||
|
export function ensurePdfjsWorker(): void {
|
||||||
|
if (workerConfigured) return;
|
||||||
|
pdfjs.GlobalWorkerOptions.workerSrc = extensionAssetUrl(pdfWorkerHref);
|
||||||
|
workerConfigured = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Page-context script on Firefox must load these chrome-extension:// URLs (see web_accessible_resources). */
|
||||||
|
export function getPdfjsPageContextUrls(): { lib: string; worker: string } {
|
||||||
|
return {
|
||||||
|
lib: extensionAssetUrl(pdfLegacyHref),
|
||||||
|
worker: extensionAssetUrl(pdfWorkerHref),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -32,7 +32,12 @@
|
|||||||
],
|
],
|
||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
{
|
{
|
||||||
"resources": ["resources/icons/*", "resources/update-image.webp"],
|
"resources": [
|
||||||
|
"resources/icons/*",
|
||||||
|
"resources/update-image.webp",
|
||||||
|
"resources/pdfjs/pdf.worker.min.mjs",
|
||||||
|
"resources/pdfjs/pdf.legacy.min.mjs"
|
||||||
|
],
|
||||||
"matches": ["*://*/*"]
|
"matches": ["*://*/*"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { getUserInfo } from "@/seqta/ui/AddBetterSEQTAElements.ts";
|
import { getUserInfo } from "@/seqta/ui/AddBetterSEQTAElements.ts";
|
||||||
import ReactFiber from "@/seqta/utils/ReactFiber.ts";
|
import ReactFiber from "@/seqta/utils/ReactFiber.ts";
|
||||||
|
import {
|
||||||
|
ensurePdfjsWorker,
|
||||||
|
getPdfjsPageContextUrls,
|
||||||
|
} from "@/lib/pdfjsExtension.ts";
|
||||||
import * as pdfjs from "pdfjs-dist";
|
import * as pdfjs from "pdfjs-dist";
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc =
|
|
||||||
`https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
ensurePdfjsWorker();
|
||||||
|
|
||||||
export async function initStorage(api: any) {
|
export async function initStorage(api: any) {
|
||||||
await api.storage.loaded;
|
await api.storage.loaded;
|
||||||
@@ -219,6 +223,12 @@ async function fetchPDFAsArrayBuffer(url: string): Promise<ArrayBuffer> {
|
|||||||
export async function extractPDFText(url: string): Promise<string> {
|
export async function extractPDFText(url: string): Promise<string> {
|
||||||
try {
|
try {
|
||||||
if (isFirefox) {
|
if (isFirefox) {
|
||||||
|
const { lib: pdfLibUrl, worker: pdfWorkerUrl } = getPdfjsPageContextUrls();
|
||||||
|
const escJsSingleQuoted = (s: string) =>
|
||||||
|
s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
||||||
|
const pdfLibInj = escJsSingleQuoted(pdfLibUrl);
|
||||||
|
const pdfWorkerInj = escJsSingleQuoted(pdfWorkerUrl);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
const requestId = `pdf-extract-${Date.now()}-${Math.random()}`;
|
const requestId = `pdf-extract-${Date.now()}-${Math.random()}`;
|
||||||
@@ -232,13 +242,15 @@ export async function extractPDFText(url: string): Promise<string> {
|
|||||||
(function() {
|
(function() {
|
||||||
const requestId = '${requestId}';
|
const requestId = '${requestId}';
|
||||||
const url = '${escapedUrl}';
|
const url = '${escapedUrl}';
|
||||||
|
const pdfLibSrc = '${pdfLibInj}';
|
||||||
|
const pdfWorkerSrc = '${pdfWorkerInj}';
|
||||||
|
|
||||||
if (window.pdfjsLib) {
|
if (window.pdfjsLib) {
|
||||||
extractPDF();
|
extractPDF();
|
||||||
} else {
|
} else {
|
||||||
const pdfjsScript = document.createElement('script');
|
const pdfjsScript = document.createElement('script');
|
||||||
pdfjsScript.src = 'https://cdn.jsdelivr.net/npm/pdfjs-dist/build/pdf.min.js';
|
pdfjsScript.src = pdfLibSrc;
|
||||||
pdfjsScript.type = 'text/javascript';
|
pdfjsScript.type = 'module';
|
||||||
|
|
||||||
pdfjsScript.onload = function() {
|
pdfjsScript.onload = function() {
|
||||||
extractPDF();
|
extractPDF();
|
||||||
@@ -256,7 +268,7 @@ export async function extractPDFText(url: string): Promise<string> {
|
|||||||
|
|
||||||
function extractPDF() {
|
function extractPDF() {
|
||||||
try {
|
try {
|
||||||
window.pdfjsLib.GlobalWorkerOptions.workerSrc = '';
|
window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfWorkerSrc;
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
|
|||||||
+66
-16
@@ -17,6 +17,7 @@ import { StorageChangeHandler } from "@/seqta/utils/listeners/StorageChanges";
|
|||||||
import { eventManager } from "@/seqta/utils/listeners/EventManager";
|
import { eventManager } from "@/seqta/utils/listeners/EventManager";
|
||||||
|
|
||||||
// UI and theme management
|
// UI and theme management
|
||||||
|
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage";
|
||||||
import RegisterClickListeners from "@/seqta/utils/listeners/ClickListeners";
|
import RegisterClickListeners from "@/seqta/utils/listeners/ClickListeners";
|
||||||
import { AddBetterSEQTAElements } from "@/seqta/ui/AddBetterSEQTAElements";
|
import { AddBetterSEQTAElements } from "@/seqta/ui/AddBetterSEQTAElements";
|
||||||
import { updateAllColors } from "@/seqta/ui/colors/Manager";
|
import { updateAllColors } from "@/seqta/ui/colors/Manager";
|
||||||
@@ -82,7 +83,12 @@ export function hideSideBar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let betterSeqtaFinishLoadDone = false;
|
||||||
|
|
||||||
export async function finishLoad() {
|
export async function finishLoad() {
|
||||||
|
if (betterSeqtaFinishLoadDone) return;
|
||||||
|
betterSeqtaFinishLoadDone = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
document.querySelector(".legacy-root")?.classList.remove("hidden");
|
document.querySelector(".legacy-root")?.classList.remove("hidden");
|
||||||
|
|
||||||
@@ -115,19 +121,19 @@ export function GetCSSElement(file: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeThemeTagsFromNotices() {
|
function removeThemeTagsFromNotices() {
|
||||||
// Grabs an array of the notice iFrames
|
|
||||||
const userHTMLArray = document.getElementsByClassName("userHTML");
|
const userHTMLArray = document.getElementsByClassName("userHTML");
|
||||||
// Iterates through the array, applying the iFrame css
|
|
||||||
for (const item of userHTMLArray) {
|
for (const item of userHTMLArray) {
|
||||||
// Grabs the HTML of the body tag
|
const iframe = item as HTMLIFrameElement;
|
||||||
const item1 = item as HTMLIFrameElement;
|
try {
|
||||||
const body = item1.contentWindow!.document.querySelectorAll("body")[0];
|
const doc = iframe.contentDocument;
|
||||||
if (body) {
|
if (!doc?.body) continue;
|
||||||
// Replaces the theme tag with nothing
|
const body = doc.body;
|
||||||
const bodyText = body.innerHTML;
|
const bodyText = body.innerHTML;
|
||||||
body.innerHTML = bodyText
|
body.innerHTML = bodyText
|
||||||
.replace(/\[\[[\w]+[:][\w]+[\]\]]+/g, "")
|
.replace(/\[\[[\w]+[:][\w]+[\]\]]+/g, "")
|
||||||
.replace(/ +/, " ");
|
.replace(/ +/, " ");
|
||||||
|
} catch {
|
||||||
|
// Cross-origin or otherwise inaccessible iframe (common during Engage load / filter frames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,6 +302,11 @@ async function handleNotices(node: Element): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleSublink(sublink: string | undefined): Promise<void> {
|
async function handleSublink(sublink: string | undefined): Promise<void> {
|
||||||
|
if (isSeqtaEngageExperience()) {
|
||||||
|
finishLoad();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sublink) {
|
switch (sublink) {
|
||||||
case "news":
|
case "news":
|
||||||
await handleNewsPage();
|
await handleNewsPage();
|
||||||
@@ -382,8 +393,11 @@ async function handleDashboard(node: Element): Promise<void> {
|
|||||||
document.head.append(style);
|
document.head.append(style);
|
||||||
|
|
||||||
await waitForElm(".dashlet", true, 10);
|
await waitForElm(".dashlet", true, 10);
|
||||||
|
try {
|
||||||
|
const children = document.querySelectorAll(".dashboard > *");
|
||||||
|
if (children.length) {
|
||||||
animate(
|
animate(
|
||||||
".dashboard > *",
|
children,
|
||||||
{ opacity: [0, 1], y: [10, 0] },
|
{ opacity: [0, 1], y: [10, 0] },
|
||||||
{
|
{
|
||||||
delay: stagger(0.1),
|
delay: stagger(0.1),
|
||||||
@@ -391,6 +405,10 @@ async function handleDashboard(node: Element): Promise<void> {
|
|||||||
ease: [0.22, 0.03, 0.26, 1],
|
ease: [0.22, 0.03, 0.26, 1],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Avoid uncaught errors if motion hits an unexpected DOM state during load.
|
||||||
|
}
|
||||||
|
|
||||||
document.head.querySelector("style.dashboardHider")?.remove();
|
document.head.querySelector("style.dashboardHider")?.remove();
|
||||||
}
|
}
|
||||||
@@ -400,8 +418,11 @@ async function handleDocuments(node: Element): Promise<void> {
|
|||||||
if (!settingsState.animations) return;
|
if (!settingsState.animations) return;
|
||||||
|
|
||||||
await waitForElm(".document", true, 10);
|
await waitForElm(".document", true, 10);
|
||||||
|
try {
|
||||||
|
const rows = document.querySelectorAll(".documents tbody tr.document");
|
||||||
|
if (rows.length) {
|
||||||
animate(
|
animate(
|
||||||
".documents tbody tr.document",
|
rows,
|
||||||
{ opacity: [0, 1], y: [10, 0] },
|
{ opacity: [0, 1], y: [10, 0] },
|
||||||
{
|
{
|
||||||
delay: stagger(0.05),
|
delay: stagger(0.05),
|
||||||
@@ -409,6 +430,10 @@ async function handleDocuments(node: Element): Promise<void> {
|
|||||||
ease: [0.22, 0.03, 0.26, 1],
|
ease: [0.22, 0.03, 0.26, 1],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleReports(node: Element): Promise<void> {
|
async function handleReports(node: Element): Promise<void> {
|
||||||
@@ -416,8 +441,11 @@ async function handleReports(node: Element): Promise<void> {
|
|||||||
if (!settingsState.animations) return;
|
if (!settingsState.animations) return;
|
||||||
|
|
||||||
await waitForElm(".report", true, 10);
|
await waitForElm(".report", true, 10);
|
||||||
|
try {
|
||||||
|
const items = document.querySelectorAll(".reports .item");
|
||||||
|
if (items.length) {
|
||||||
animate(
|
animate(
|
||||||
".reports .item",
|
items,
|
||||||
{ opacity: [0, 1], y: [10, 0] },
|
{ opacity: [0, 1], y: [10, 0] },
|
||||||
{
|
{
|
||||||
delay: stagger(0.05, { startDelay: 0.2 }),
|
delay: stagger(0.05, { startDelay: 0.2 }),
|
||||||
@@ -425,6 +453,10 @@ async function handleReports(node: Element): Promise<void> {
|
|||||||
ease: [0.22, 0.03, 0.26, 1],
|
ease: [0.22, 0.03, 0.26, 1],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function CheckNoticeTextColour(notice: any) {
|
function CheckNoticeTextColour(notice: any) {
|
||||||
@@ -449,6 +481,26 @@ function CheckNoticeTextColour(notice: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function tryLoad() {
|
export function tryLoad() {
|
||||||
|
if (isSeqtaEngageExperience()) {
|
||||||
|
updateIframesWithDarkMode();
|
||||||
|
window.addEventListener(
|
||||||
|
"load",
|
||||||
|
() => removeThemeTagsFromNotices(),
|
||||||
|
{ once: true },
|
||||||
|
);
|
||||||
|
window.addEventListener(
|
||||||
|
"load",
|
||||||
|
() => void finishLoad(),
|
||||||
|
{ once: true },
|
||||||
|
);
|
||||||
|
waitForElm(".login").then(() => void finishLoad());
|
||||||
|
waitForElm(".day-container").then(() => void finishLoad());
|
||||||
|
waitForElm(".code", true, 50).then((elm: any) => {
|
||||||
|
if (!elm.innerText.includes("BetterSEQTA")) void LoadPageElements();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
waitForElm(".login").then(() => {
|
waitForElm(".login").then(() => {
|
||||||
finishLoad();
|
finishLoad();
|
||||||
});
|
});
|
||||||
@@ -466,13 +518,10 @@ export function tryLoad() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
updateIframesWithDarkMode();
|
updateIframesWithDarkMode();
|
||||||
// Waits for page to call on load, run scripts
|
window.addEventListener(
|
||||||
document.addEventListener(
|
|
||||||
"load",
|
"load",
|
||||||
function () {
|
() => removeThemeTagsFromNotices(),
|
||||||
removeThemeTagsFromNotices();
|
{ once: true },
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,6 +538,7 @@ function ReplaceMenuSVG(element: HTMLElement, svg: string) {
|
|||||||
const processedSymbol = Symbol("processed");
|
const processedSymbol = Symbol("processed");
|
||||||
|
|
||||||
export async function ObserveMenuItemPosition() {
|
export async function ObserveMenuItemPosition() {
|
||||||
|
if (isSeqtaEngageExperience()) return;
|
||||||
await waitForElm("#menu > ul > li");
|
await waitForElm("#menu > ul > li");
|
||||||
|
|
||||||
eventManager.register(
|
eventManager.register(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { addExtensionSettings } from "@/seqta/utils/Adders/AddExtensionSettings";
|
import { addExtensionSettings } from "@/seqta/utils/Adders/AddExtensionSettings";
|
||||||
|
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage";
|
||||||
import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage";
|
import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage";
|
||||||
import { SendNewsPage } from "@/seqta/utils/SendNewsPage";
|
import { SendNewsPage } from "@/seqta/utils/SendNewsPage";
|
||||||
import { setupSettingsButton } from "@/seqta/utils/setupSettingsButton";
|
import { setupSettingsButton } from "@/seqta/utils/setupSettingsButton";
|
||||||
@@ -42,6 +43,11 @@ export async function getUserInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function AddBetterSEQTAElements() {
|
export async function AddBetterSEQTAElements() {
|
||||||
|
if (isSeqtaEngageExperience()) {
|
||||||
|
addExtensionSettings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (settingsState.onoff) {
|
if (settingsState.onoff) {
|
||||||
if (settingsState.DarkMode) {
|
if (settingsState.DarkMode) {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
|
|||||||
@@ -9,21 +9,8 @@ import Settings from "@/interface/pages/settings.svelte";
|
|||||||
|
|
||||||
let isSettingsRendered = false;
|
let isSettingsRendered = false;
|
||||||
|
|
||||||
export function addExtensionSettings() {
|
function extensionOutsideClickHandler(extensionPopup: HTMLElement) {
|
||||||
const extensionPopup = document.createElement("div");
|
return (event: MouseEvent) => {
|
||||||
extensionPopup.classList.add("outside-container", "hide");
|
|
||||||
extensionPopup.id = "ExtensionPopup";
|
|
||||||
|
|
||||||
const extensionContainer = document.querySelector(
|
|
||||||
"#container",
|
|
||||||
) as HTMLDivElement;
|
|
||||||
if (extensionContainer) extensionContainer.appendChild(extensionPopup);
|
|
||||||
|
|
||||||
const container = document.getElementById("container");
|
|
||||||
|
|
||||||
new SettingsResizer();
|
|
||||||
|
|
||||||
container!.onclick = (event) => {
|
|
||||||
if (!SettingsClicked) return;
|
if (!SettingsClicked) return;
|
||||||
|
|
||||||
if (!(event.target as HTMLElement).closest("#AddedSettings")) {
|
if (!(event.target as HTMLElement).closest("#AddedSettings")) {
|
||||||
@@ -33,6 +20,24 @@ export function addExtensionSettings() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addExtensionSettings() {
|
||||||
|
if (document.getElementById("ExtensionPopup")) return;
|
||||||
|
|
||||||
|
const extensionPopup = document.createElement("div");
|
||||||
|
extensionPopup.classList.add("outside-container", "hide");
|
||||||
|
extensionPopup.id = "ExtensionPopup";
|
||||||
|
|
||||||
|
const extensionContainer =
|
||||||
|
document.querySelector("#container") ?? document.getElementById("container");
|
||||||
|
const mountParent = extensionContainer ?? document.body;
|
||||||
|
mountParent.appendChild(extensionPopup);
|
||||||
|
|
||||||
|
new SettingsResizer();
|
||||||
|
|
||||||
|
const handler = extensionOutsideClickHandler(extensionPopup);
|
||||||
|
(extensionContainer ?? document.body).addEventListener("click", handler, false);
|
||||||
|
}
|
||||||
|
|
||||||
export function renderSettingsIfNeeded() {
|
export function renderSettingsIfNeeded() {
|
||||||
if (isSettingsRendered) return;
|
if (isSettingsRendered) return;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ 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.5.3 - Adaptive theme updates</h1>
|
||||||
|
<li>Fixed adaptive theming on current-year course and assessment pages.</li>
|
||||||
|
|
||||||
|
<h1>3.5.2 - PDF & store compliance</h1>
|
||||||
|
<li>Put PDF.js with the extension so assessment weighting stays compatible with Chrome Web Store rules</li>
|
||||||
|
|
||||||
<h1>3.5.1 - QR & session link fix</h1>
|
<h1>3.5.1 - QR & session link fix</h1>
|
||||||
<li>Fixed DesQTA Connect Mobile App QR generation on Chrome</li>
|
<li>Fixed DesQTA Connect Mobile App QR generation on Chrome</li>
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ import { getUserInfo } from "@/seqta/ui/AddBetterSEQTAElements";
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the current page from window.location.hash.
|
* Parses the current page from window.location.hash.
|
||||||
* Returns { programme, metaclass } for /courses/SEMESTER/X:Y or /assessments/SEMESTER/X:Y, or null.
|
* Supports both old and current URL formats, e.g.
|
||||||
* e.g. #?page=/courses/2023S/4804:11066 or #?page=/assessments/2023S/4621:10772
|
* /courses/SEMESTER/X:Y and /courses/X:Y
|
||||||
|
* /assessments/SEMESTER/X:Y and /assessments/X:Y
|
||||||
|
* e.g. #?page=/courses/2023S/4804:11066,
|
||||||
|
* #?page=/courses/4804:11066,
|
||||||
|
* #?page=/assessments/2023S/4621:10772,
|
||||||
|
* #?page=/assessments/4621:10772
|
||||||
*/
|
*/
|
||||||
function parsePageContext(): { programme: number; metaclass: number } | null {
|
function parsePageContext(): { programme: number; metaclass: number } | null {
|
||||||
const hash = window.location.hash || "";
|
const hash = window.location.hash || "";
|
||||||
const match = hash.match(/[?&]page=\/(courses|assessments)\/[^/]+\/(\d+):(\d+)/);
|
const match = hash.match(/[?&]page=\/(courses|assessments)\/(?:[^/]+\/)?(\d+):(\d+)/);
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
const programme = parseInt(match[2], 10);
|
const programme = parseInt(match[2], 10);
|
||||||
const metaclass = parseInt(match[3], 10);
|
const metaclass = parseInt(match[3], 10);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/** SEQTA Engage (React) uses a different shell from classic SEQTA Learn. */
|
||||||
|
export function isSeqtaEngageExperience(): boolean {
|
||||||
|
return document.title.includes("SEQTA Engage");
|
||||||
|
}
|
||||||
@@ -9,10 +9,11 @@ import { renderSettingsIfNeeded } from "./Adders/AddExtensionSettings";
|
|||||||
import { delay } from "./delay";
|
import { delay } from "./delay";
|
||||||
|
|
||||||
export function setupSettingsButton() {
|
export function setupSettingsButton() {
|
||||||
var AddedSettings = document.getElementById("AddedSettings");
|
const AddedSettings = document.getElementById("AddedSettings");
|
||||||
var extensionPopup = document.getElementById("ExtensionPopup");
|
const extensionPopup = document.getElementById("ExtensionPopup");
|
||||||
|
if (!AddedSettings || !extensionPopup) return;
|
||||||
|
|
||||||
AddedSettings!.addEventListener("click", async () => {
|
AddedSettings.addEventListener("click", async () => {
|
||||||
if (SettingsClicked) {
|
if (SettingsClicked) {
|
||||||
closeExtensionPopup(extensionPopup as HTMLElement);
|
closeExtensionPopup(extensionPopup as HTMLElement);
|
||||||
} else {
|
} else {
|
||||||
@@ -23,20 +24,20 @@ export function setupSettingsButton() {
|
|||||||
if (settingsState.animations) {
|
if (settingsState.animations) {
|
||||||
animate(0, 1, {
|
animate(0, 1, {
|
||||||
onUpdate: (progress) => {
|
onUpdate: (progress) => {
|
||||||
extensionPopup!.style.opacity = progress.toString();
|
extensionPopup.style.opacity = progress.toString();
|
||||||
extensionPopup!.style.transform = `scale(${progress})`;
|
extensionPopup.style.transform = `scale(${progress})`;
|
||||||
},
|
},
|
||||||
type: "spring",
|
type: "spring",
|
||||||
stiffness: 280,
|
stiffness: 280,
|
||||||
damping: 20,
|
damping: 20,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
extensionPopup!.style.opacity = "1";
|
extensionPopup.style.opacity = "1";
|
||||||
extensionPopup!.style.transform = "scale(1)";
|
extensionPopup.style.transform = "scale(1)";
|
||||||
extensionPopup!.style.transition =
|
extensionPopup.style.transition =
|
||||||
"opacity 0s linear, transform 0s linear";
|
"opacity 0s linear, transform 0s linear";
|
||||||
}
|
}
|
||||||
extensionPopup!.classList.remove("hide");
|
extensionPopup.classList.remove("hide");
|
||||||
changeSettingsClicked(true);
|
changeSettingsClicked(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -84,6 +84,24 @@ export default defineConfig(({ command }) => ({
|
|||||||
settings: join(__dirname, "src", "interface", "index.html"),
|
settings: join(__dirname, "src", "interface", "index.html"),
|
||||||
pageState: join(__dirname, "src", "pageState.js"),
|
pageState: join(__dirname, "src", "pageState.js"),
|
||||||
},
|
},
|
||||||
|
output: {
|
||||||
|
assetFileNames(info) {
|
||||||
|
const labels = [
|
||||||
|
...(info.names ?? []),
|
||||||
|
...(info.originalFileNames ?? []),
|
||||||
|
].join(" ");
|
||||||
|
if (
|
||||||
|
labels.includes("pdf.worker.min") ||
|
||||||
|
labels.includes("pdf.worker.mjs")
|
||||||
|
) {
|
||||||
|
return "resources/pdfjs/pdf.worker.min.mjs";
|
||||||
|
}
|
||||||
|
if (labels.includes("legacy") && labels.includes("pdf.min")) {
|
||||||
|
return "resources/pdfjs/pdf.legacy.min.mjs";
|
||||||
|
}
|
||||||
|
return "assets/[name]-[hash][extname]";
|
||||||
|
},
|
||||||
|
},
|
||||||
onwarn(warning, warn) {
|
onwarn(warning, warn) {
|
||||||
if (warning.code === "FILE_NAME_CONFLICT") return;
|
if (warning.code === "FILE_NAME_CONFLICT") return;
|
||||||
warn(warning);
|
warn(warning);
|
||||||
|
|||||||
Reference in New Issue
Block a user