mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
perf: lazy loading improvements
This commit is contained in:
+16
-71
@@ -49,7 +49,7 @@ browser.runtime.onMessage.addListener(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "setDefaultStorage":
|
case "setDefaultStorage":
|
||||||
SetStorageValue(DefaultValues);
|
SetStorageValue(getDefaultValues());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sendNews":
|
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,
|
onoff: true,
|
||||||
animatedbk: true,
|
animatedbk: true,
|
||||||
bksliderinput: "50",
|
bksliderinput: "50",
|
||||||
@@ -96,7 +107,7 @@ const DefaultValues: SettingsState = {
|
|||||||
"linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
|
"linear-gradient(40deg, rgba(201,61,0,1) 0%, RGBA(170, 5, 58, 1) 100%)",
|
||||||
originalSelectedColor: "",
|
originalSelectedColor: "",
|
||||||
DarkMode: true,
|
DarkMode: true,
|
||||||
animations: true,
|
animations: !isLowEndDevice,
|
||||||
assessmentsAverage: true,
|
assessmentsAverage: true,
|
||||||
defaultPage: "home",
|
defaultPage: "home",
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
@@ -116,7 +127,8 @@ const DefaultValues: SettingsState = {
|
|||||||
customshortcuts: [],
|
customshortcuts: [],
|
||||||
lettergrade: false,
|
lettergrade: false,
|
||||||
newsSource: "australia",
|
newsSource: "australia",
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function SetStorageValue(object: any) {
|
function SetStorageValue(object: any) {
|
||||||
for (var i in object) {
|
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.runtime.onInstalled.addListener(function (event) {
|
||||||
browser.storage.local.remove(["justupdated"]);
|
browser.storage.local.remove(["justupdated"]);
|
||||||
browser.storage.local.remove(["data"]);
|
browser.storage.local.remove(["data"]);
|
||||||
|
|
||||||
if (event.reason == "install" || event.reason == "update") {
|
if (event.reason == "install" || event.reason == "update") {
|
||||||
browser.storage.local.set({ justupdated: true });
|
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";
|
import { PluginManager } from "./core/manager";
|
||||||
|
|
||||||
// plugins
|
// Lightweight plugins (load immediately)
|
||||||
import timetablePlugin from "./built-in/timetable";
|
import timetablePlugin from "./built-in/timetable";
|
||||||
import notificationCollectorPlugin from "./built-in/notificationCollector";
|
import notificationCollectorPlugin from "./built-in/notificationCollector";
|
||||||
import themesPlugin from "./built-in/themes";
|
import themesPlugin from "./built-in/themes";
|
||||||
import animatedBackgroundPlugin from "./built-in/animatedBackground";
|
import animatedBackgroundPlugin from "./built-in/animatedBackground";
|
||||||
import assessmentsAveragePlugin from "./built-in/assessmentsAverage";
|
import assessmentsAveragePlugin from "./built-in/assessmentsAverage";
|
||||||
import globalSearchPlugin from "./built-in/globalSearch/src/core";
|
|
||||||
import profilePicturePlugin from "./built-in/profilePicture";
|
import profilePicturePlugin from "./built-in/profilePicture";
|
||||||
import assessmentsOverviewPlugin from "./built-in/assessmentsOverview";
|
import assessmentsOverviewPlugin from "./built-in/assessmentsOverview";
|
||||||
//import testPlugin from './built-in/test';
|
//import testPlugin from './built-in/test';
|
||||||
|
|
||||||
|
// Heavy plugins (lazy-loaded only when enabled)
|
||||||
|
import globalSearchPluginLazy from "./built-in/globalSearch/lazy";
|
||||||
|
|
||||||
// Initialize plugin manager
|
// Initialize plugin manager
|
||||||
const pluginManager = PluginManager.getInstance();
|
const pluginManager = PluginManager.getInstance();
|
||||||
|
|
||||||
@@ -20,11 +22,13 @@ pluginManager.registerPlugin(animatedBackgroundPlugin);
|
|||||||
pluginManager.registerPlugin(assessmentsAveragePlugin);
|
pluginManager.registerPlugin(assessmentsAveragePlugin);
|
||||||
pluginManager.registerPlugin(notificationCollectorPlugin);
|
pluginManager.registerPlugin(notificationCollectorPlugin);
|
||||||
pluginManager.registerPlugin(timetablePlugin);
|
pluginManager.registerPlugin(timetablePlugin);
|
||||||
pluginManager.registerPlugin(globalSearchPlugin);
|
|
||||||
pluginManager.registerPlugin(profilePicturePlugin);
|
pluginManager.registerPlugin(profilePicturePlugin);
|
||||||
pluginManager.registerPlugin(assessmentsOverviewPlugin);
|
pluginManager.registerPlugin(assessmentsOverviewPlugin);
|
||||||
//pluginManager.registerPlugin(testPlugin);
|
//pluginManager.registerPlugin(testPlugin);
|
||||||
|
|
||||||
|
// Register heavy plugins with lazy loading
|
||||||
|
pluginManager.registerPlugin(globalSearchPluginLazy);
|
||||||
|
|
||||||
export { init as Monofile } from "./monofile";
|
export { init as Monofile } from "./monofile";
|
||||||
|
|
||||||
export async function initializePlugins(): Promise<void> {
|
export async function initializePlugins(): Promise<void> {
|
||||||
|
|||||||
Reference in New Issue
Block a user