mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-05 19:24:39 +00:00
perf: lazy loading improvements
This commit is contained in:
+16
-71
@@ -49,7 +49,7 @@ browser.runtime.onMessage.addListener(
|
||||
break;
|
||||
|
||||
case "setDefaultStorage":
|
||||
SetStorageValue(DefaultValues);
|
||||
SetStorageValue(getDefaultValues());
|
||||
break;
|
||||
|
||||
case "sendNews":
|
||||
@@ -64,7 +64,18 @@ browser.runtime.onMessage.addListener(
|
||||
},
|
||||
);
|
||||
|
||||
const DefaultValues: SettingsState = {
|
||||
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",
|
||||
@@ -96,7 +107,7 @@ const DefaultValues: SettingsState = {
|
||||
"linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
|
||||
originalSelectedColor: "",
|
||||
DarkMode: true,
|
||||
animations: true,
|
||||
animations: !isLowEndDevice,
|
||||
assessmentsAverage: true,
|
||||
defaultPage: "home",
|
||||
shortcuts: [
|
||||
@@ -116,7 +127,8 @@ const DefaultValues: SettingsState = {
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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")
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
|
||||
Reference in New Issue
Block a user