mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
perf: reduce startup work and fix grade analytics bar chart animation
Batch settings storage writes, tier plugin startup, lazy-load heavy UI chunks, and optimize global search indexing. Stop tweening bar height in grade analytics to prevent invalid negative SVG rect values. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -16,10 +16,12 @@ import { updateAllColors } from "./colors/Manager";
|
||||
import { delay } from "@/seqta/utils/delay";
|
||||
|
||||
let cachedUserInfo: any = null;
|
||||
let userInfoFetchPromise: Promise<any> | null = null;
|
||||
let userInfoCacheListenersAttached = false;
|
||||
|
||||
export function invalidateCachedUserInfo(): void {
|
||||
cachedUserInfo = null;
|
||||
userInfoFetchPromise = null;
|
||||
}
|
||||
|
||||
function attachUserInfoCacheInvalidation(): void {
|
||||
@@ -48,44 +50,61 @@ export async function getUserInfo(options?: { validateSession?: boolean }) {
|
||||
return cachedUserInfo;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${location.origin}/seqta/student/login`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mode: "normal",
|
||||
query: null,
|
||||
redirect_url: location.origin,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to get user info: HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
const payload = (await response.json()).payload;
|
||||
|
||||
if (
|
||||
cachedUserInfo &&
|
||||
options?.validateSession &&
|
||||
payload?.id != null &&
|
||||
cachedUserInfo.id != null &&
|
||||
payload.id !== cachedUserInfo.id
|
||||
) {
|
||||
console.warn(
|
||||
"[BetterSEQTA+] Session user changed; invalidating cached user info",
|
||||
);
|
||||
invalidateCachedUserInfo();
|
||||
}
|
||||
|
||||
cachedUserInfo = payload;
|
||||
return cachedUserInfo;
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Failed to get user info:", error);
|
||||
throw error;
|
||||
if (userInfoFetchPromise && !options?.validateSession) {
|
||||
return userInfoFetchPromise;
|
||||
}
|
||||
|
||||
const fetchUserInfo = async () => {
|
||||
try {
|
||||
const response = await fetch(`${location.origin}/seqta/student/login`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mode: "normal",
|
||||
query: null,
|
||||
redirect_url: location.origin,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to get user info: HTTP ${response.status}`);
|
||||
}
|
||||
|
||||
const payload = (await response.json()).payload;
|
||||
|
||||
if (
|
||||
cachedUserInfo &&
|
||||
options?.validateSession &&
|
||||
payload?.id != null &&
|
||||
cachedUserInfo.id != null &&
|
||||
payload.id !== cachedUserInfo.id
|
||||
) {
|
||||
console.warn(
|
||||
"[BetterSEQTA+] Session user changed; invalidating cached user info",
|
||||
);
|
||||
invalidateCachedUserInfo();
|
||||
}
|
||||
|
||||
cachedUserInfo = payload;
|
||||
return cachedUserInfo;
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Failed to get user info:", error);
|
||||
throw error;
|
||||
} finally {
|
||||
if (!options?.validateSession) {
|
||||
userInfoFetchPromise = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (options?.validateSession) {
|
||||
return fetchUserInfo();
|
||||
}
|
||||
|
||||
userInfoFetchPromise = fetchUserInfo();
|
||||
return userInfoFetchPromise;
|
||||
}
|
||||
|
||||
export async function AddBetterSEQTAElements() {
|
||||
@@ -115,11 +134,7 @@ export async function AddBetterSEQTAElements() {
|
||||
menuList.insertBefore(fragment, menuList.firstChild);
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
appendBackgroundToUI(),
|
||||
handleUserInfo(),
|
||||
handleStudentData(),
|
||||
]);
|
||||
await Promise.all([appendBackgroundToUI(), handleUserInfoAndStudentData()]);
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Failed to initialize UI elements:", error);
|
||||
}
|
||||
@@ -149,11 +164,26 @@ function createHomeButton(fragment: DocumentFragment, _: HTMLElement) {
|
||||
);
|
||||
}
|
||||
|
||||
async function handleUserInfo() {
|
||||
async function handleUserInfoAndStudentData() {
|
||||
try {
|
||||
updateUserInfo(await getUserInfo());
|
||||
const [userInfo, studentResponse] = await Promise.all([
|
||||
getUserInfo(),
|
||||
fetch(`${location.origin}/seqta/student/load/message/people`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({ mode: "student" }),
|
||||
}),
|
||||
]);
|
||||
|
||||
updateUserInfo(userInfo);
|
||||
await updateStudentInfo((await studentResponse.json()).payload, userInfo);
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Failed to handle user info:", error);
|
||||
console.error(
|
||||
"[BetterSEQTA+] Failed to handle user info and student data:",
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,27 +239,7 @@ function updateUserInfo(info: {
|
||||
.appendChild(document.getElementsByClassName("logout")[0]);
|
||||
}
|
||||
|
||||
async function handleStudentData() {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${location.origin}/seqta/student/load/message/people`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
},
|
||||
body: JSON.stringify({ mode: "student" }),
|
||||
},
|
||||
);
|
||||
|
||||
await updateStudentInfo((await response.json()).payload);
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Failed to handle student data:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function updateStudentInfo(students: any) {
|
||||
const info = await getUserInfo();
|
||||
async function updateStudentInfo(students: any, info: Awaited<ReturnType<typeof getUserInfo>>) {
|
||||
const index = students.findIndex(
|
||||
(person: any) =>
|
||||
person.firstname == info.userDesc.split(" ")[0] &&
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import renderSvelte from "@/interface/main";
|
||||
import Store from "@/interface/pages/store.svelte";
|
||||
|
||||
import { unmount } from "svelte";
|
||||
|
||||
let remove: () => void;
|
||||
|
||||
export function OpenStorePage() {
|
||||
remove = renderStore();
|
||||
export async function OpenStorePage(): Promise<void> {
|
||||
remove = await renderStore();
|
||||
}
|
||||
|
||||
export function renderStore() {
|
||||
export async function renderStore() {
|
||||
const [{ default: renderSvelte }, { default: Store }] = await Promise.all([
|
||||
import("@/interface/main"),
|
||||
import("@/interface/pages/store.svelte"),
|
||||
]);
|
||||
|
||||
const container = document.querySelector("#container");
|
||||
if (!container) {
|
||||
throw new Error("Container not found");
|
||||
}
|
||||
|
||||
// Avoid stacking multiple store roots if opened repeatedly without close.
|
||||
document.getElementById("store")?.remove();
|
||||
|
||||
const child = document.createElement("div");
|
||||
child.id = "store";
|
||||
container!.appendChild(child);
|
||||
container.appendChild(child);
|
||||
|
||||
const shadow = child.attachShadow({ mode: "open" });
|
||||
const app = renderSvelte(Store, shadow);
|
||||
|
||||
Reference in New Issue
Block a user