perf: lazy loading improvements

This commit is contained in:
SethBurkart123
2025-08-15 16:12:27 +10:00
parent b03e99faa2
commit a42d781955
4 changed files with 226 additions and 123 deletions
+65 -120
View File
@@ -49,7 +49,7 @@ browser.runtime.onMessage.addListener(
break;
case "setDefaultStorage":
SetStorageValue(DefaultValues);
SetStorageValue(getDefaultValues());
break;
case "sendNews":
@@ -64,59 +64,71 @@ browser.runtime.onMessage.addListener(
},
);
const DefaultValues: SettingsState = {
onoff: true,
animatedbk: true,
bksliderinput: "50",
transparencyEffects: false,
lessonalert: true,
defaultmenuorder: [],
menuitems: {
assessments: { toggle: true },
courses: { toggle: true },
dashboard: { toggle: true },
documents: { toggle: true },
forums: { toggle: true },
goals: { toggle: true },
home: { toggle: true },
messages: { toggle: true },
myed: { toggle: true },
news: { toggle: true },
notices: { toggle: true },
portals: { toggle: true },
reports: { toggle: true },
settings: { toggle: true },
timetable: { toggle: true },
welcome: { toggle: true },
},
menuorder: [],
subjectfilters: {},
selectedTheme: "",
selectedColor:
"linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
originalSelectedColor: "",
DarkMode: true,
animations: true,
assessmentsAverage: true,
defaultPage: "home",
shortcuts: [
{
name: "Outlook",
enabled: true,
function detectLowEndDevice(): boolean {
// Check for low-end hardware indicators
const lowCoreCount = navigator.hardwareConcurrency && navigator.hardwareConcurrency < 4;
const lowMemory = (navigator as any).deviceMemory && (navigator as any).deviceMemory <= 2;
return lowCoreCount || lowMemory;
}
function getDefaultValues(): SettingsState {
const isLowEndDevice = detectLowEndDevice();
return {
onoff: true,
animatedbk: true,
bksliderinput: "50",
transparencyEffects: false,
lessonalert: true,
defaultmenuorder: [],
menuitems: {
assessments: { toggle: true },
courses: { toggle: true },
dashboard: { toggle: true },
documents: { toggle: true },
forums: { toggle: true },
goals: { toggle: true },
home: { toggle: true },
messages: { toggle: true },
myed: { toggle: true },
news: { toggle: true },
notices: { toggle: true },
portals: { toggle: true },
reports: { toggle: true },
settings: { toggle: true },
timetable: { toggle: true },
welcome: { toggle: true },
},
{
name: "Office",
enabled: true,
},
{
name: "Google",
enabled: true,
},
],
customshortcuts: [],
lettergrade: false,
newsSource: "australia",
};
menuorder: [],
subjectfilters: {},
selectedTheme: "",
selectedColor:
"linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
originalSelectedColor: "",
DarkMode: true,
animations: !isLowEndDevice,
assessmentsAverage: true,
defaultPage: "home",
shortcuts: [
{
name: "Outlook",
enabled: true,
},
{
name: "Office",
enabled: true,
},
{
name: "Google",
enabled: true,
},
],
customshortcuts: [],
lettergrade: false,
newsSource: "australia",
};
}
function SetStorageValue(object: any) {
for (var i in object) {
@@ -124,78 +136,11 @@ function SetStorageValue(object: any) {
}
}
function convertBksliderToSpeed(bksliderinput: number): number {
const minBase = 50;
const maxBase = 150;
const scaledValue =
2 + ((maxBase - bksliderinput) / (maxBase - minBase)) ** 4;
const baseSpeed = 3;
const speed = baseSpeed / scaledValue;
return speed;
}
async function migrateLegacySettings() {
const storage = (await browser.storage.local.get(
null,
)) as unknown as SettingsState;
// Animated Background Migration
if ("animatedbk" in storage || "bksliderinput" in storage) {
const animatedSettings = {
enabled: storage.animatedbk ?? true,
speed: storage.bksliderinput
? convertBksliderToSpeed(parseFloat(storage.bksliderinput))
: 1,
};
await browser.storage.local.set({
"plugin.animated-background.settings": animatedSettings,
});
}
// Assessments Average Migration
if ("assessmentsAverage" in storage || "lettergrade" in storage) {
const assessmentsSettings = {
enabled: storage.assessmentsAverage ?? true,
lettergrade: storage.lettergrade ?? false,
};
await browser.storage.local.set({
"plugin.assessments-average.settings": assessmentsSettings,
});
}
if ("selectedTheme" in storage) {
const themesSettings = { enabled: true };
await browser.storage.local.set({
"plugin.themes.settings": themesSettings,
});
}
if (storage.notificationCollector !== false) {
await browser.storage.local.set({
"plugin.notificationCollector.settings": { enabled: true },
});
} else {
await browser.storage.local.set({
"plugin.notificationCollector.settings": { enabled: false },
});
}
const keysToRemove = [
"animatedbk",
"bksliderinput",
"assessmentsAverage",
"lettergrade",
];
await browser.storage.local.remove(keysToRemove);
}
browser.runtime.onInstalled.addListener(function (event) {
browser.storage.local.remove(["justupdated"]);
browser.storage.local.remove(["data"]);
if (event.reason == "install" || event.reason == "update") {
browser.storage.local.set({ justupdated: true });
migrateLegacySettings();
}
});
+88
View File
@@ -0,0 +1,88 @@
import { defineLazyPlugin } from "../../core/dynamicLoader";
import {
booleanSetting,
buttonSetting,
defineSettings,
hotkeySetting,
} from "../../core/settingsHelpers";
// Platform-aware default hotkey
const getDefaultHotkey = () => {
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
return isMac ? "cmd+k" : "ctrl+k";
};
const settings = defineSettings({
searchHotkey: hotkeySetting({
default: getDefaultHotkey(),
title: "Search Hotkey",
description: "Keyboard shortcut to open the search",
}),
showRecentFirst: booleanSetting({
default: true,
title: "Show Recent First",
description: "Sort dynamic content by most recent first",
}),
transparencyEffects: booleanSetting({
default: true,
title: "Transparency Effects",
description: "Enable transparency effects for the search bar",
}),
runIndexingOnLoad: booleanSetting({
default: true,
title: "Index on Page Load",
description: "Run content indexing when SEQTA loads",
}),
resetIndex: buttonSetting({
title: "Reset Index",
description: "Reset the search index and storage",
trigger: async () => {
const confirmed = confirm("Are you sure you want to reset the search index and storage?");
if (confirmed) {
try {
// Dynamically import the worker manager to avoid loading heavy dependencies
const { VectorWorkerManager } = await import("./src/indexing/worker/vectorWorkerManager");
const workerManager = VectorWorkerManager.getInstance();
await workerManager.resetWorker();
console.log("Vector worker reset successfully");
} catch (e) {
console.warn("Failed to reset vector worker:", e);
}
// Delete both 'embeddiaDB' and 'betterseqta-index' using native IndexedDB APIs
const deleteDb = (dbName: string) => {
return new Promise<void>((resolve, reject) => {
const req = indexedDB.deleteDatabase(dbName);
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
req.onblocked = () => {
reject(new Error(`One database is open, failed to remove: ${dbName}`));
};
});
};
try {
await deleteDb("embeddiaDB");
await deleteDb("betterseqta-index");
alert("Search index and storage have been reset.");
} catch (e) {
alert("Failed to reset one or more databases: " + String(e));
}
}
},
}),
});
// Create the lazy plugin definition - this loads immediately but doesn't import heavy dependencies
export default defineLazyPlugin({
id: "global-search",
name: "Global Search",
description: "Quick search for everything in SEQTA",
version: "1.0.0",
settings,
disableToggle: true,
defaultEnabled: false,
beta: true,
// Lazy loader - only imports the heavy plugin when actually needed
loader: () => import("./src/core/index")
});
+66
View File
@@ -0,0 +1,66 @@
import type { Plugin, PluginSettings } from "./types";
/**
* Interface for lazy-loaded plugin definitions
*/
export interface LazyPlugin<T extends PluginSettings = PluginSettings, S = any> {
id: string;
name: string;
description: string;
version: string;
settings: T;
styles?: string;
disableToggle?: boolean;
defaultEnabled?: boolean;
beta?: boolean;
// Instead of a run function, we have a loader that imports the actual plugin
loader: () => Promise<{ default: Plugin<T, S> }>;
}
/**
* Converts a lazy plugin into a regular plugin by wrapping the run function
* with dynamic import logic
*/
export function createLazyPlugin<T extends PluginSettings = PluginSettings, S = any>(
lazyPlugin: LazyPlugin<T, S>
): Plugin<T, S> {
return {
id: lazyPlugin.id,
name: lazyPlugin.name,
description: lazyPlugin.description,
version: lazyPlugin.version,
settings: lazyPlugin.settings,
styles: lazyPlugin.styles,
disableToggle: lazyPlugin.disableToggle,
defaultEnabled: lazyPlugin.defaultEnabled,
beta: lazyPlugin.beta,
run: async (api) => {
console.info(`[BetterSEQTA+] Dynamically loading plugin "${lazyPlugin.id}"...`);
try {
// Dynamically import the actual plugin implementation
const { default: actualPlugin } = await lazyPlugin.loader();
console.info(`[BetterSEQTA+] Successfully loaded plugin "${lazyPlugin.id}"`);
// Execute the actual plugin's run function
return await actualPlugin.run(api);
} catch (error) {
console.error(`[BetterSEQTA+] Failed to dynamically load plugin "${lazyPlugin.id}":`, error);
throw error;
}
}
};
}
/**
* Helper function to create a lazy plugin definition
*/
export function defineLazyPlugin<T extends PluginSettings = PluginSettings, S = any>(
config: LazyPlugin<T, S>
): Plugin<T, S> {
return createLazyPlugin(config);
}
+7 -3
View File
@@ -1,16 +1,18 @@
import { PluginManager } from "./core/manager";
// plugins
// Lightweight plugins (load immediately)
import timetablePlugin from "./built-in/timetable";
import notificationCollectorPlugin from "./built-in/notificationCollector";
import themesPlugin from "./built-in/themes";
import animatedBackgroundPlugin from "./built-in/animatedBackground";
import assessmentsAveragePlugin from "./built-in/assessmentsAverage";
import globalSearchPlugin from "./built-in/globalSearch/src/core";
import profilePicturePlugin from "./built-in/profilePicture";
import assessmentsOverviewPlugin from "./built-in/assessmentsOverview";
//import testPlugin from './built-in/test';
// Heavy plugins (lazy-loaded only when enabled)
import globalSearchPluginLazy from "./built-in/globalSearch/lazy";
// Initialize plugin manager
const pluginManager = PluginManager.getInstance();
@@ -20,11 +22,13 @@ pluginManager.registerPlugin(animatedBackgroundPlugin);
pluginManager.registerPlugin(assessmentsAveragePlugin);
pluginManager.registerPlugin(notificationCollectorPlugin);
pluginManager.registerPlugin(timetablePlugin);
pluginManager.registerPlugin(globalSearchPlugin);
pluginManager.registerPlugin(profilePicturePlugin);
pluginManager.registerPlugin(assessmentsOverviewPlugin);
//pluginManager.registerPlugin(testPlugin);
// Register heavy plugins with lazy loading
pluginManager.registerPlugin(globalSearchPluginLazy);
export { init as Monofile } from "./monofile";
export async function initializePlugins(): Promise<void> {