mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
fix(themes): theme wallpapers dont apply on firefox
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
import HighlightedText from '../utils/HighlightedText.svelte';
|
||||
import { matchesHotkey } from '../utils/hotkeyUtils';
|
||||
import browser from 'webextension-polyfill';
|
||||
import { verboseDebug } from '@/utils/verboseLog';
|
||||
|
||||
const {
|
||||
transparencyEffects,
|
||||
@@ -160,7 +161,7 @@
|
||||
dynamicItems.forEach(item => dynamicIdToItemMap.set(item.id, item));
|
||||
commands.forEach(item => commandIdToItemMap.set(item.id, item));
|
||||
|
||||
console.debug(`[Global Search] Indexed ${commands.length} command items and ${dynamicItems.length} dynamic items.`);
|
||||
verboseDebug(`[Global Search] Indexed ${commands.length} command items and ${dynamicItems.length} dynamic items.`);
|
||||
}
|
||||
|
||||
const performSearch = async () => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
import { loadHomePage } from "@/seqta/utils/Loaders/LoadHomePage";
|
||||
import { waitForElm } from "@/seqta/utils/waitForElm";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
export interface BaseCommandItem {
|
||||
id: string;
|
||||
text: string;
|
||||
@@ -105,7 +106,7 @@ async function navigateToSpecificLesson(lesson: any) {
|
||||
if (lessonDate === todayDateString && lessonPeriod === normalizedLessonPeriod) {
|
||||
// Found the exact matching lesson, click it
|
||||
(lessonElement as HTMLElement).click();
|
||||
console.log(`Navigated to exact lesson: ${lessonDate} ${lessonPeriod}`);
|
||||
verboseLog(`Navigated to exact lesson: ${lessonDate} ${lessonPeriod}`);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
hotkeySetting,
|
||||
Setting,
|
||||
} from "@/plugins/core/settingsHelpers";
|
||||
import { verboseDebug, verboseInfo, verboseLog } from "@/utils/verboseLog";
|
||||
import styles from "./styles.css?inline";
|
||||
import { waitForElm } from "@/seqta/utils/waitForElm";
|
||||
import { runIndexing } from "../indexing/indexer";
|
||||
@@ -70,7 +71,7 @@ const settings = defineSettings({
|
||||
try {
|
||||
const workerManager = VectorWorkerManager.getInstance();
|
||||
await workerManager.resetWorker();
|
||||
console.log("Vector worker reset successfully");
|
||||
verboseLog("Vector worker reset successfully");
|
||||
} catch (e) {
|
||||
console.warn("Failed to reset vector worker:", e);
|
||||
}
|
||||
@@ -90,7 +91,7 @@ const settings = defineSettings({
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const req = indexedDB.deleteDatabase(dbName);
|
||||
req.onsuccess = () => {
|
||||
console.log(`Successfully deleted database: ${dbName}`);
|
||||
verboseLog(`Successfully deleted database: ${dbName}`);
|
||||
resolve();
|
||||
};
|
||||
req.onerror = () => {
|
||||
@@ -103,7 +104,7 @@ const settings = defineSettings({
|
||||
setTimeout(() => {
|
||||
const retryReq = indexedDB.deleteDatabase(dbName);
|
||||
retryReq.onsuccess = () => {
|
||||
console.log(`Successfully deleted database on retry: ${dbName}`);
|
||||
verboseLog(`Successfully deleted database on retry: ${dbName}`);
|
||||
resolve();
|
||||
};
|
||||
retryReq.onerror = () => reject(retryReq.error);
|
||||
@@ -176,7 +177,7 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
try {
|
||||
const wasUpdated = await checkAndHandleUpdate();
|
||||
if (wasUpdated) {
|
||||
console.log(
|
||||
verboseLog(
|
||||
"[Global Search] Extension updated — search index reset; the next indexing pass will repopulate.",
|
||||
);
|
||||
}
|
||||
@@ -188,7 +189,7 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
error?.message?.includes("MIME type") ||
|
||||
error?.message?.includes("NS_ERROR_CORRUPTED_CONTENT")
|
||||
) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[Global Search] Version check skipped due to asset loading restrictions:",
|
||||
error.message,
|
||||
);
|
||||
@@ -217,7 +218,7 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
if (isVectorSearchSupported()) {
|
||||
VectorWorkerManager.getInstance();
|
||||
} else {
|
||||
console.debug("[Global Search] Skipping vector worker warm-up (Firefox detected - using text search only)");
|
||||
verboseDebug("[Global Search] Skipping vector worker warm-up (Firefox detected - using text search only)");
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Global Search] Vector worker warm-up failed:", error);
|
||||
@@ -230,15 +231,15 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
resetWorker: async () => {
|
||||
const workerManager = VectorWorkerManager.getInstance();
|
||||
await workerManager.resetWorker();
|
||||
console.log("Vector worker reset via debug helper");
|
||||
verboseLog("Vector worker reset via debug helper");
|
||||
},
|
||||
checkWorkerStatus: () => {
|
||||
const workerManager = VectorWorkerManager.getInstance();
|
||||
console.log("Streaming active:", workerManager.isStreamingActive());
|
||||
verboseLog("Streaming active:", workerManager.isStreamingActive());
|
||||
},
|
||||
passiveItems: async () => {
|
||||
const items = await getStoredPassiveItems();
|
||||
console.log(`Captured ${items.length} passive items`);
|
||||
verboseLog(`Captured ${items.length} passive items`);
|
||||
return items;
|
||||
},
|
||||
runSelfTests: async () => {
|
||||
@@ -250,7 +251,7 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
checkIndexedDBSize: async () => {
|
||||
try {
|
||||
const estimate = await navigator.storage.estimate();
|
||||
console.log("Storage estimate:", estimate);
|
||||
verboseLog("Storage estimate:", estimate);
|
||||
|
||||
// Check embeddiaDB size
|
||||
const dbRequest = indexedDB.open("embeddiaDB");
|
||||
@@ -260,7 +261,7 @@ const globalSearchPlugin: Plugin<typeof settings> = {
|
||||
const store = transaction.objectStore("embeddiaObjectStore");
|
||||
const countRequest = store.count();
|
||||
countRequest.onsuccess = () => {
|
||||
console.log("embeddiaDB item count:", countRequest.result);
|
||||
verboseLog("embeddiaDB item count:", countRequest.result);
|
||||
};
|
||||
};
|
||||
} catch (e) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { IndexItem } from "./types";
|
||||
import ReactFiber from "@/seqta/utils/ReactFiber";
|
||||
import { delay } from "@/seqta/utils/delay";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
interface MessageMetadata {
|
||||
messageId: number;
|
||||
author: string;
|
||||
@@ -171,7 +172,7 @@ export const actionMap: Record<string, ActionHandler<any>> = {
|
||||
if ((assessmentId === undefined || assessmentId === null) && itemClone.id && itemClone.id.startsWith('assignment-')) {
|
||||
const extractedId = itemClone.id.replace('assignment-', '');
|
||||
assessmentId = Number(extractedId) || extractedId;
|
||||
console.log("[Assessment Action] Extracted assessmentId from item ID:", assessmentId);
|
||||
verboseLog("[Assessment Action] Extracted assessmentId from item ID:", assessmentId);
|
||||
}
|
||||
|
||||
// Convert to numbers, but preserve 0 as valid
|
||||
@@ -198,7 +199,7 @@ export const actionMap: Record<string, ActionHandler<any>> = {
|
||||
|
||||
if (hasProgrammeId && hasMetaclassId && hasAssessmentId) {
|
||||
const url = `#?page=/assessments/${programmeId}:${metaclassId}&item=${assessmentId}`;
|
||||
console.log("[Assessment Action] ✅ Navigating to:", url);
|
||||
verboseLog("[Assessment Action] ✅ Navigating to:", url);
|
||||
window.location.hash = url;
|
||||
} else {
|
||||
// Fallback: try to navigate to assessments page if metadata is incomplete
|
||||
|
||||
@@ -7,6 +7,7 @@ import { loadDynamicItems } from "../utils/dynamicItems";
|
||||
import { getVectorizedItemIds } from "./utils";
|
||||
import { INDEX_SCHEMA_VERSION, SCHEMA_VERSION_KEY } from "./schemaVersion";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const META_STORE = "meta";
|
||||
const LOCK_KEY = "bsq-indexer-lock";
|
||||
const HEARTBEAT_INTERVAL = 10000;
|
||||
@@ -101,7 +102,7 @@ async function updateLastRunMeta(jobId: string): Promise<void> {
|
||||
|
||||
async function acquireLock(): Promise<boolean> {
|
||||
if (isIndexingActive) {
|
||||
console.debug("[Indexer] Already indexing in this tab");
|
||||
verboseDebug("[Indexer] Already indexing in this tab");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -200,7 +201,7 @@ export async function loadAllStoredItems(): Promise<IndexItem[]> {
|
||||
console.error(`Error loading items for job store ${jobId}:`, error);
|
||||
}
|
||||
}
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`[Indexer] Loaded ${all.length} items from all primary stores.`,
|
||||
);
|
||||
return all;
|
||||
@@ -210,7 +211,7 @@ export async function runIndexing(): Promise<void> {
|
||||
await ensureSchemaCurrent();
|
||||
|
||||
if (!(await acquireLock())) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"%c[Indexer] Could not acquire lock - another tab is indexing or this tab is already indexing",
|
||||
"color: gray",
|
||||
);
|
||||
@@ -218,7 +219,7 @@ export async function runIndexing(): Promise<void> {
|
||||
}
|
||||
|
||||
startHeartbeat();
|
||||
console.debug("%c[Indexer] Starting indexing...", "color: green");
|
||||
verboseDebug("%c[Indexer] Starting indexing...", "color: green");
|
||||
|
||||
const jobIds = Object.keys(jobs);
|
||||
let completedJobs = 0;
|
||||
@@ -236,7 +237,7 @@ export async function runIndexing(): Promise<void> {
|
||||
const lastRun = await getLastRunMeta(jobId);
|
||||
|
||||
if (!shouldRun(job, lastRun)) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`%c[Indexer] Skipping job "${jobId}" (not due)`,
|
||||
"color: gray",
|
||||
);
|
||||
@@ -288,7 +289,7 @@ export async function runIndexing(): Promise<void> {
|
||||
setProgress: (p) => saveProgress(jobId, p),
|
||||
};
|
||||
|
||||
console.debug(`%c[Indexer] Running job "${jobId}"...`, "color: #4ea1ff");
|
||||
verboseDebug(`%c[Indexer] Running job "${jobId}"...`, "color: #4ea1ff");
|
||||
|
||||
try {
|
||||
const newItemsRaw = await job.run(ctx);
|
||||
@@ -300,12 +301,12 @@ export async function runIndexing(): Promise<void> {
|
||||
await setStoredItems(merged);
|
||||
await updateLastRunMeta(jobId);
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`%c[Indexer] ${job.label}: ${newItemsRaw.length} new items reported by run, ${merged.length} total items now in '${jobId}' store.`,
|
||||
"color: #00c46f",
|
||||
);
|
||||
} catch (err) {
|
||||
console.debug(`%c[Indexer] Job ${job.label} failed:`, "color: red");
|
||||
verboseDebug(`%c[Indexer] Job ${job.label} failed:`, "color: red");
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
@@ -321,7 +322,7 @@ export async function runIndexing(): Promise<void> {
|
||||
let allItemsInPrimaryStores = await loadAllStoredItems();
|
||||
|
||||
if (allItemsInPrimaryStores.length > 0) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`%c[Indexer] Checking ${allItemsInPrimaryStores.length} items for vectorization...`,
|
||||
"color: #4ea1ff",
|
||||
);
|
||||
@@ -331,7 +332,7 @@ export async function runIndexing(): Promise<void> {
|
||||
const newItemsToVectorize = allItemsInPrimaryStores.filter(item => !vectorizedItemIds.has(item.id));
|
||||
|
||||
if (newItemsToVectorize.length > 0) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`%c[Indexer] Sending ${newItemsToVectorize.length} new items to worker for vectorization (${allItemsInPrimaryStores.length - newItemsToVectorize.length} already vectorized)`,
|
||||
"color: #4ea1ff",
|
||||
);
|
||||
@@ -389,7 +390,7 @@ export async function runIndexing(): Promise<void> {
|
||||
);
|
||||
}
|
||||
});
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"%c[Indexer] Vectorization task for stored items sent to worker.",
|
||||
"color: green",
|
||||
);
|
||||
@@ -408,7 +409,7 @@ export async function runIndexing(): Promise<void> {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`%c[Indexer] All ${allItemsInPrimaryStores.length} items are already vectorized, skipping worker initialization.`,
|
||||
"color: gray",
|
||||
);
|
||||
@@ -421,7 +422,7 @@ export async function runIndexing(): Promise<void> {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"%c[Indexer] No items found in primary stores to send for vectorization.",
|
||||
"color: gray",
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { IndexItem, Job } from "../types";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const fetchJSON = async (url: string, body: any) => {
|
||||
const res = await fetch(`${location.origin}${url}`, {
|
||||
method: "POST",
|
||||
@@ -128,7 +129,7 @@ export const assignmentsJob: Job = {
|
||||
|
||||
const student = 69; // TODO: Get from context if available
|
||||
|
||||
console.debug("[Assignments job] Starting indexing - fetching all assessments (upcoming and past)...");
|
||||
verboseDebug("[Assignments job] Starting indexing - fetching all assessments (upcoming and past)...");
|
||||
|
||||
// Fetch data in parallel
|
||||
const [upcoming, subjects] = await Promise.all([
|
||||
@@ -136,12 +137,12 @@ export const assignmentsJob: Job = {
|
||||
fetchSubjects(),
|
||||
]);
|
||||
|
||||
console.debug(`[Assignments job] Fetched ${upcoming.length} upcoming assessments and ${subjects.length} subjects`);
|
||||
verboseDebug(`[Assignments job] Fetched ${upcoming.length} upcoming assessments and ${subjects.length} subjects`);
|
||||
|
||||
// Fetch past assessments for ALL subjects to ensure we get all historical assignments
|
||||
const past = await fetchPastAssessments(student, subjects);
|
||||
|
||||
console.debug(`[Assignments job] Fetched ${past.length} past assessments`);
|
||||
verboseDebug(`[Assignments job] Fetched ${past.length} past assessments`);
|
||||
|
||||
// Create a lookup map from subject code to programme/metaclass
|
||||
const subjectLookup = new Map<string, { programme: number; metaclass: number }>();
|
||||
@@ -220,7 +221,7 @@ export const assignmentsJob: Job = {
|
||||
const assessmentArray = Array.from(allAssessments.values());
|
||||
const pastCount = assessmentArray.filter(a => !a.isUpcoming).length;
|
||||
const upcomingCount = assessmentArray.filter(a => a.isUpcoming).length;
|
||||
console.debug(`[Assignments job] Processing ${assessmentArray.length} total assessments (${upcomingCount} upcoming, ${pastCount} past)`);
|
||||
verboseDebug(`[Assignments job] Processing ${assessmentArray.length} total assessments (${upcomingCount} upcoming, ${pastCount} past)`);
|
||||
const batchSize = 15; // Increased batch size for better performance
|
||||
|
||||
// Skip fetching assessment details - the API endpoint doesn't exist or returns 404
|
||||
@@ -321,7 +322,7 @@ export const assignmentsJob: Job = {
|
||||
renderComponentId: "assessment",
|
||||
};
|
||||
|
||||
console.debug(`[Assignments job] ✅ Created item for assignment ${assessment.id}:`, {
|
||||
verboseDebug(`[Assignments job] ✅ Created item for assignment ${assessment.id}:`, {
|
||||
id: item.id,
|
||||
programmeId: item.metadata.programmeId,
|
||||
programmeID: item.metadata.programmeID,
|
||||
@@ -350,7 +351,7 @@ export const assignmentsJob: Job = {
|
||||
|
||||
const newItemsCount = items.filter(item => !existingIds.has(item.id)).length;
|
||||
const updatedItemsCount = items.length - newItemsCount;
|
||||
console.debug(`[Assignments job] Indexed ${items.length} assignment items (${newItemsCount} new, ${updatedItemsCount} updated)`);
|
||||
verboseDebug(`[Assignments job] Indexed ${items.length} assignment items (${newItemsCount} new, ${updatedItemsCount} updated)`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { seqtaFetchPayload } from "../api";
|
||||
import { buildIndexItem } from "../extract";
|
||||
import { htmlToPlainText } from "../utils";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes per-subject course content from `/seqta/student/load/courses`.
|
||||
*
|
||||
@@ -106,7 +107,7 @@ export const coursesJob: Job = {
|
||||
run: async (_ctx) => {
|
||||
const subjects = await fetchActiveSubjects();
|
||||
if (subjects.length === 0) {
|
||||
console.debug("[Courses job] No active subjects discovered.");
|
||||
verboseDebug("[Courses job] No active subjects discovered.");
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ export const coursesJob: Job = {
|
||||
);
|
||||
}
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`[Courses job] Indexed ${items.length} courses across ${subjects.length} subjects.`,
|
||||
);
|
||||
return items;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { IndexItem, Job } from "../types";
|
||||
import { seqtaFetchPayload } from "../api";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes file metadata from `/seqta/student/load/documents`.
|
||||
*
|
||||
@@ -131,7 +132,7 @@ export const documentsJob: Job = {
|
||||
}
|
||||
}
|
||||
|
||||
console.debug(`[Documents job] Indexed ${items.length} document entries.`);
|
||||
verboseDebug(`[Documents job] Indexed ${items.length} document entries.`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { seqtaFetchPayload } from "../api";
|
||||
import { htmlToPlainText } from "../utils";
|
||||
import { delay } from "@/seqta/utils/delay";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes student folio entries from `/seqta/student/folio`.
|
||||
*
|
||||
@@ -126,7 +127,7 @@ export const folioJob: Job = {
|
||||
await delay(PER_ITEM_DELAY_MS);
|
||||
}
|
||||
|
||||
console.debug(`[Folio job] Indexed ${items.length} folio entries.`);
|
||||
verboseDebug(`[Folio job] Indexed ${items.length} folio entries.`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { seqtaFetchPayload } from "../api";
|
||||
import { extractTextFromValue } from "../extract";
|
||||
import { delay } from "@/seqta/utils/delay";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes student goals from `/seqta/student/load/goals`.
|
||||
*
|
||||
@@ -42,7 +43,7 @@ export const goalsJob: Job = {
|
||||
{ mode: "years" },
|
||||
);
|
||||
if (!Array.isArray(years) || years.length === 0) {
|
||||
console.debug("[Goals job] No goal years available; skipping.");
|
||||
verboseDebug("[Goals job] No goal years available; skipping.");
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -101,7 +102,7 @@ export const goalsJob: Job = {
|
||||
await delay(PER_YEAR_DELAY_MS);
|
||||
}
|
||||
|
||||
console.debug(`[Goals job] Indexed ${items.length} goal entries.`);
|
||||
verboseDebug(`[Goals job] Indexed ${items.length} goal entries.`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { loadAllStoredItems } from "../indexer";
|
||||
import { renderComponentMap } from "../renderComponents";
|
||||
import { jobs } from "../jobs";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const RATE_LIMIT_CONFIG = {
|
||||
minDelay: 30,
|
||||
maxDelay: 3000,
|
||||
@@ -208,7 +209,7 @@ function checkCircuitBreaker(progress: MessagesProgress): boolean {
|
||||
) {
|
||||
progress.circuitBreakerOpen = false;
|
||||
progress.consecutiveFailures = 0;
|
||||
console.info(
|
||||
verboseInfo(
|
||||
`[Messages job] Circuit breaker closed after ${RATE_LIMIT_CONFIG.circuitBreakerResetTime}ms`,
|
||||
);
|
||||
return false;
|
||||
@@ -352,7 +353,7 @@ async function processMessagesInParallel(
|
||||
batchResponseTime,
|
||||
);
|
||||
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Processed parallel batch: ${batchSuccesses} successes, ${batchFailures} failures, ${batchResponseTime}ms total time`,
|
||||
);
|
||||
}
|
||||
@@ -397,7 +398,7 @@ export const messagesJob: Job = {
|
||||
await vectorWorker.startStreamingSession(
|
||||
progress.totalEstimated,
|
||||
(progressData) => {
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Vector streaming progress: ${progressData.processed}/${progressData.total} (${progressData.status})`,
|
||||
);
|
||||
},
|
||||
@@ -405,7 +406,7 @@ export const messagesJob: Job = {
|
||||
"messages",
|
||||
);
|
||||
progress.streamingStarted = true;
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Started streaming vectorization session for ~${progress.totalEstimated} items`,
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -422,7 +423,7 @@ export const messagesJob: Job = {
|
||||
let itemsStreamedToVector = 0;
|
||||
|
||||
if (progress.retryQueue.length > 0) {
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Processing ${Math.min(progress.retryQueue.length, 10)} items from retry queue`,
|
||||
);
|
||||
|
||||
@@ -505,7 +506,7 @@ export const messagesJob: Job = {
|
||||
batchResponseTime,
|
||||
);
|
||||
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Processed retry batch: ${retrySuccesses} successes, ${retryFailures} failures`,
|
||||
);
|
||||
}
|
||||
@@ -590,7 +591,7 @@ export const messagesJob: Job = {
|
||||
try {
|
||||
await vectorWorker.streamItems(itemsToStream);
|
||||
itemsStreamedToVector += itemsToStream.length;
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Streamed ${itemsToStream.length} items to vector worker (total: ${itemsStreamedToVector})`,
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -659,7 +660,7 @@ export const messagesJob: Job = {
|
||||
await ctx.setProgress(progress);
|
||||
progressUpdateCounter = 0;
|
||||
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Progress: offset=${progress.offset}, batchSize=${progress.currentBatchSize}, delay=${progress.currentDelay}ms, failures=${progress.failedRequests}, retryQueue=${progress.retryQueue.length}, vectorStreamed=${itemsStreamedToVector}, parallelRequests=${RATE_LIMIT_CONFIG.parallelRequests}`,
|
||||
);
|
||||
}
|
||||
@@ -673,7 +674,7 @@ export const messagesJob: Job = {
|
||||
if (progress.streamingStarted) {
|
||||
try {
|
||||
await vectorWorker.endStreamingSession();
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Messages job] Ended streaming session. Total items streamed: ${itemsStreamedToVector}`,
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { seqtaFetchPayload } from "../api";
|
||||
import { htmlToPlainText } from "../utils";
|
||||
import { delay } from "@/seqta/utils/delay";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes daily notices from `/seqta/student/load/notices`.
|
||||
*
|
||||
@@ -205,7 +206,7 @@ export const noticesJob: Job = {
|
||||
await ctx.setProgress(progress);
|
||||
|
||||
const newCount = items.filter((i) => !existingIds.has(i.id)).length;
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`[Notices job] Indexed ${items.length} notices across ${dates.length} dates (${newCount} new).`,
|
||||
);
|
||||
return items;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { loadAllStoredItems } from "../indexer";
|
||||
import { renderComponentMap } from "../renderComponents";
|
||||
import { jobs } from "../jobs";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const NOTIFICATIONS_RATE_LIMIT = {
|
||||
baseDelay: 150,
|
||||
maxDelay: 3000,
|
||||
@@ -201,7 +202,7 @@ export const notificationsJob: Job = {
|
||||
await vectorWorker.startStreamingSession(
|
||||
estimatedTotal,
|
||||
(progressData) => {
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Vector streaming progress: ${progressData.processed}/${progressData.total} (${progressData.status})`,
|
||||
);
|
||||
},
|
||||
@@ -209,7 +210,7 @@ export const notificationsJob: Job = {
|
||||
"notifications",
|
||||
);
|
||||
progress.streamingStarted = true;
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Started streaming vectorization session for ~${estimatedTotal} items`,
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -247,7 +248,7 @@ export const notificationsJob: Job = {
|
||||
let itemsStreamedToVector = 0;
|
||||
|
||||
if (progress.retryQueue.length > 0) {
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Processing ${Math.min(progress.retryQueue.length, 3)} items from retry queue`,
|
||||
);
|
||||
|
||||
@@ -352,7 +353,7 @@ export const notificationsJob: Job = {
|
||||
try {
|
||||
await vectorWorker.streamItems([...itemsToStream]);
|
||||
itemsStreamedToVector += itemsToStream.length;
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Streamed ${itemsToStream.length} items to vector worker (total: ${itemsStreamedToVector})`,
|
||||
);
|
||||
itemsToStream.length = 0;
|
||||
@@ -424,7 +425,7 @@ export const notificationsJob: Job = {
|
||||
try {
|
||||
await vectorWorker.streamItems([...itemsToStream]);
|
||||
itemsStreamedToVector += itemsToStream.length;
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Streamed final ${itemsToStream.length} items to vector worker (total: ${itemsStreamedToVector})`,
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -438,7 +439,7 @@ export const notificationsJob: Job = {
|
||||
if (progress.streamingStarted) {
|
||||
try {
|
||||
await vectorWorker.endStreamingSession();
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Ended streaming session. Total items streamed: ${itemsStreamedToVector}`,
|
||||
);
|
||||
progress.streamingStarted = false;
|
||||
@@ -459,7 +460,7 @@ export const notificationsJob: Job = {
|
||||
}
|
||||
|
||||
await ctx.setProgress(progress);
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Notifications job] Processed ${processedCount} notifications, ${progress.retryQueue.length} in retry queue, ${progress.failedRequests} failures, ${itemsStreamedToVector} items streamed to vector worker`,
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { IndexItem, Job } from "../types";
|
||||
import { seqtaFetchPayload } from "../api";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes the user's external portal entries from `/seqta/student/load/portals`.
|
||||
*
|
||||
@@ -82,7 +83,7 @@ export const portalsJob: Job = {
|
||||
});
|
||||
}
|
||||
|
||||
console.debug(`[Portals job] Indexed ${items.length} portal entries.`);
|
||||
verboseDebug(`[Portals job] Indexed ${items.length} portal entries.`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { IndexItem, Job } from "../types";
|
||||
import { seqtaFetchPayload } from "../api";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Indexes report metadata from `/seqta/student/load/reports`.
|
||||
*
|
||||
@@ -89,7 +90,7 @@ export const reportsJob: Job = {
|
||||
});
|
||||
}
|
||||
|
||||
console.debug(`[Reports job] Indexed ${items.length} reports.`);
|
||||
verboseDebug(`[Reports job] Indexed ${items.length} reports.`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { IndexItem, Job } from "../types";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const fetchSubjects = async () => {
|
||||
const res = await fetch(`${location.origin}/seqta/student/load/subjects`, {
|
||||
method: "POST",
|
||||
@@ -129,7 +130,7 @@ export const subjectsJob: Job = {
|
||||
}
|
||||
}
|
||||
|
||||
console.debug(`[Subjects job] Indexed ${items.length} subject items`);
|
||||
verboseDebug(`[Subjects job] Indexed ${items.length} subject items`);
|
||||
return items;
|
||||
},
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
pickId,
|
||||
pickTitle,
|
||||
} from "./extract";
|
||||
import { verboseDebug, verboseInfo, verboseLog } from "@/utils/verboseLog";
|
||||
import { isSensitiveSeqtaPath, normalizeSeqtaPath } from "./api";
|
||||
import { loadAllStoredItems } from "./indexer";
|
||||
import { loadDynamicItems } from "../utils/dynamicItems";
|
||||
@@ -542,7 +543,7 @@ export function installPassiveObserver(): void {
|
||||
}
|
||||
} catch (e) {
|
||||
// Never let observer errors bubble up to the host page.
|
||||
console.debug("[Passive Observer] fetch hook error:", e);
|
||||
verboseDebug("[Passive Observer] fetch hook error:", e);
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -605,7 +606,7 @@ export function installPassiveObserver(): void {
|
||||
void persistItems(items);
|
||||
}
|
||||
} catch (e) {
|
||||
console.debug("[Passive Observer] xhr load error:", e);
|
||||
verboseDebug("[Passive Observer] xhr load error:", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -616,7 +617,7 @@ export function installPassiveObserver(): void {
|
||||
};
|
||||
}
|
||||
|
||||
console.debug("[Passive Observer] Installed.");
|
||||
verboseDebug("[Passive Observer] Installed.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
pickId,
|
||||
buildIndexItem,
|
||||
} from "./extract";
|
||||
import { verboseDebug, verboseInfo, verboseLog } from "@/utils/verboseLog";
|
||||
import { isSensitiveSeqtaPath, normalizeSeqtaPath } from "./api";
|
||||
import {
|
||||
coursesPayload,
|
||||
@@ -320,7 +321,7 @@ export async function runGlobalSearchSelfTests(): Promise<SelfTestReport> {
|
||||
report.failures,
|
||||
);
|
||||
} else {
|
||||
console.info(
|
||||
verboseInfo(
|
||||
`[Global Search Self-Tests] All ${report.passed} cases passed`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
/**
|
||||
* Check which items are already vectorized in embeddia's IndexedDB
|
||||
* Returns a Set of item IDs that are already indexed
|
||||
@@ -7,7 +8,7 @@ export async function getVectorizedItemIds(): Promise<Set<string>> {
|
||||
const request = indexedDB.open("embeddiaDB");
|
||||
|
||||
request.onerror = () => {
|
||||
console.debug("Could not open embeddiaDB, assuming no items are vectorized");
|
||||
verboseDebug("Could not open embeddiaDB, assuming no items are vectorized");
|
||||
resolve(new Set());
|
||||
};
|
||||
|
||||
@@ -15,7 +16,7 @@ export async function getVectorizedItemIds(): Promise<Set<string>> {
|
||||
const db = (event.target as IDBOpenDBRequest).result;
|
||||
|
||||
if (!db.objectStoreNames.contains("embeddiaObjectStore")) {
|
||||
console.debug("embeddiaObjectStore not found, assuming no items are vectorized");
|
||||
verboseDebug("embeddiaObjectStore not found, assuming no items are vectorized");
|
||||
db.close();
|
||||
resolve(new Set());
|
||||
return;
|
||||
@@ -34,7 +35,7 @@ export async function getVectorizedItemIds(): Promise<Set<string>> {
|
||||
}
|
||||
});
|
||||
|
||||
console.debug(`Found ${vectorizedIds.size} already vectorized items in embeddia DB`);
|
||||
verboseDebug(`Found ${vectorizedIds.size} already vectorized items in embeddia DB`);
|
||||
db.close();
|
||||
resolve(vectorizedIds);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EmbeddingIndex, getEmbedding, initializeModel } from "embeddia";
|
||||
import type { IndexItem } from "../types";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
let vectorIndex: EmbeddingIndex | null = null;
|
||||
let isInitialized = false;
|
||||
let initializationFailed = false;
|
||||
@@ -33,27 +34,27 @@ let streamingSession: {
|
||||
|
||||
async function initWorker() {
|
||||
if (isInitialized) {
|
||||
console.debug("Vector worker already initialized.");
|
||||
verboseDebug("Vector worker already initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip initialization in Firefox
|
||||
if (isFirefoxWorker()) {
|
||||
console.debug("[Vector Worker] Vector search not supported in Firefox - skipping initialization");
|
||||
verboseDebug("[Vector Worker] Vector search not supported in Firefox - skipping initialization");
|
||||
isInitialized = true;
|
||||
initializationFailed = true;
|
||||
vectorIndex = null;
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug("Initializing vector worker...");
|
||||
verboseDebug("Initializing vector worker...");
|
||||
try {
|
||||
await initializeModel();
|
||||
vectorIndex = new EmbeddingIndex([]);
|
||||
|
||||
const stored = await vectorIndex.getAllObjectsFromIndexedDB();
|
||||
if (stored.length > 0) {
|
||||
console.debug(`Found ${stored.length} existing items in IndexedDB`);
|
||||
verboseDebug(`Found ${stored.length} existing items in IndexedDB`);
|
||||
|
||||
loadedItemIds.clear();
|
||||
|
||||
@@ -64,14 +65,14 @@ async function initWorker() {
|
||||
}
|
||||
});
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Vector index loaded ${loadedItemIds.size} unique items from IndexedDB.`,
|
||||
);
|
||||
} else {
|
||||
console.debug("No existing vector index found in IndexedDB.");
|
||||
verboseDebug("No existing vector index found in IndexedDB.");
|
||||
}
|
||||
isInitialized = true;
|
||||
console.debug("Vector worker initialized successfully.");
|
||||
verboseDebug("Vector worker initialized successfully.");
|
||||
} catch (e) {
|
||||
console.warn("[Vector Worker] Failed to initialize vector worker (will use text search only):", e);
|
||||
isInitialized = true;
|
||||
@@ -149,7 +150,7 @@ async function startStreamingSession(
|
||||
processingPromise: null,
|
||||
};
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Started streaming session for ${totalExpected} items with batch size ${batchSize}`,
|
||||
);
|
||||
|
||||
@@ -175,7 +176,7 @@ async function processStreamingBatch(
|
||||
streamingSession.totalReceived += items.length;
|
||||
streamingSession.pendingItems.push(...items);
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Received streaming batch: ${items.length} items (${streamingSession.totalReceived}/${streamingSession.totalExpected})`,
|
||||
);
|
||||
|
||||
@@ -208,7 +209,7 @@ async function processStreamingItems() {
|
||||
|
||||
if (unprocessedItems.length === 0) {
|
||||
streamingSession.totalProcessed += batchToProcess.length;
|
||||
console.debug(`Skipped ${batchToProcess.length} already processed items`);
|
||||
verboseDebug(`Skipped ${batchToProcess.length} already processed items`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -231,7 +232,7 @@ async function processStreamingItems() {
|
||||
loadedItemIds.size % 200 === 0
|
||||
) {
|
||||
await vectorIndex!.saveIndex("indexedDB");
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Saved streaming index at ${streamingSession.totalProcessed} processed items (${loadedItemIds.size} total unique items)`,
|
||||
);
|
||||
}
|
||||
@@ -272,7 +273,7 @@ async function finalizeStreamingSession() {
|
||||
try {
|
||||
if (vectorIndex) {
|
||||
await vectorIndex.saveIndex("indexedDB");
|
||||
console.debug("Final save of streaming index completed");
|
||||
verboseDebug("Final save of streaming index completed");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error in final streaming save:", e);
|
||||
@@ -293,7 +294,7 @@ async function finalizeStreamingSession() {
|
||||
},
|
||||
});
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Streaming session completed: ${totalProcessed}/${totalExpected} items processed`,
|
||||
);
|
||||
}
|
||||
@@ -303,14 +304,14 @@ async function endStreamingSession() {
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug("Ending streaming session...");
|
||||
verboseDebug("Ending streaming session...");
|
||||
|
||||
if (streamingSession.processingPromise) {
|
||||
await streamingSession.processingPromise;
|
||||
}
|
||||
|
||||
if (streamingSession.pendingItems.length > 0) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Processing ${streamingSession.pendingItems.length} remaining items before ending session`,
|
||||
);
|
||||
streamingSession.processingPromise = processStreamingItems();
|
||||
@@ -320,7 +321,7 @@ async function endStreamingSession() {
|
||||
try {
|
||||
if (vectorIndex) {
|
||||
await vectorIndex.saveIndex("indexedDB");
|
||||
console.debug("Final save before ending streaming session");
|
||||
verboseDebug("Final save before ending streaming session");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error in final save before ending session:", e);
|
||||
@@ -341,7 +342,7 @@ async function endStreamingSession() {
|
||||
}
|
||||
|
||||
async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
console.debug("Worker received process request.");
|
||||
verboseDebug("Worker received process request.");
|
||||
|
||||
if (initializationFailed || isFirefoxWorker()) {
|
||||
self.postMessage({
|
||||
@@ -378,7 +379,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
});
|
||||
|
||||
if (signal.aborted) {
|
||||
console.debug("Processing cancelled before starting.");
|
||||
verboseDebug("Processing cancelled before starting.");
|
||||
self.postMessage({
|
||||
type: "progress",
|
||||
data: {
|
||||
@@ -390,7 +391,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
}
|
||||
|
||||
if (unprocessedItems.length === 0) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`No new items to process. ${loadedItemIds.size} items already in index.`,
|
||||
);
|
||||
self.postMessage({
|
||||
@@ -403,7 +404,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Starting processing of ${unprocessedItems.length} items (${items.length - unprocessedItems.length} already processed).`,
|
||||
);
|
||||
self.postMessage({
|
||||
@@ -419,7 +420,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
let processedCount = 0;
|
||||
for (let i = 0; i < unprocessedItems.length; i += BATCH_SIZE) {
|
||||
if (signal.aborted) {
|
||||
console.debug("Processing cancelled during batching.");
|
||||
verboseDebug("Processing cancelled during batching.");
|
||||
self.postMessage({
|
||||
type: "progress",
|
||||
data: {
|
||||
@@ -437,7 +438,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
) as (IndexItem & { embedding: number[] })[];
|
||||
|
||||
if (signal.aborted) {
|
||||
console.debug("Processing cancelled after vectorization batch.");
|
||||
verboseDebug("Processing cancelled after vectorization batch.");
|
||||
self.postMessage({
|
||||
type: "progress",
|
||||
data: {
|
||||
@@ -464,7 +465,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
}
|
||||
|
||||
if (signal.aborted) {
|
||||
console.debug("Processing cancelled before saving batch.");
|
||||
verboseDebug("Processing cancelled before saving batch.");
|
||||
self.postMessage({
|
||||
type: "progress",
|
||||
data: {
|
||||
@@ -481,7 +482,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
) {
|
||||
try {
|
||||
await vectorIndex!.saveIndex("indexedDB");
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Saved index after processing batch ${i / BATCH_SIZE + 1} (${loadedItemIds.size} total unique items)`,
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -505,7 +506,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
});
|
||||
}
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Processing complete. Total unique items in index: ${loadedItemIds.size}`,
|
||||
);
|
||||
self.postMessage({
|
||||
@@ -520,7 +521,7 @@ async function processItems(items: IndexItem[], signal: AbortSignal) {
|
||||
}
|
||||
|
||||
async function resetWorker() {
|
||||
console.debug("Resetting vector worker state...");
|
||||
verboseDebug("Resetting vector worker state...");
|
||||
|
||||
loadedItemIds.clear();
|
||||
|
||||
@@ -532,7 +533,7 @@ async function resetWorker() {
|
||||
if (vectorIndex) {
|
||||
try {
|
||||
await vectorIndex.saveIndex("indexedDB");
|
||||
console.debug("Saved index before reset");
|
||||
verboseDebug("Saved index before reset");
|
||||
} catch (e) {
|
||||
console.warn("Error saving index before reset:", e);
|
||||
}
|
||||
@@ -543,7 +544,7 @@ async function resetWorker() {
|
||||
|
||||
await initWorker();
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Vector worker reset complete. Loaded ${loadedItemIds.size} items.`,
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { IndexItem } from "../types";
|
||||
import { isVectorSearchSupported } from "../../utils/browserDetection";
|
||||
import vectorWorker from "./vectorWorker.ts?inlineWorker";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
export type ProgressCallback = (data: {
|
||||
status: "started" | "processing" | "complete" | "error" | "cancelled";
|
||||
total?: number;
|
||||
@@ -38,7 +39,7 @@ export class VectorWorkerManager {
|
||||
|
||||
static getInstance(): VectorWorkerManager {
|
||||
if (!VectorWorkerManager.instance) {
|
||||
console.debug("Creating new VectorWorkerManager instance");
|
||||
verboseDebug("Creating new VectorWorkerManager instance");
|
||||
VectorWorkerManager.instance = new VectorWorkerManager();
|
||||
}
|
||||
return VectorWorkerManager.instance;
|
||||
@@ -47,7 +48,7 @@ export class VectorWorkerManager {
|
||||
private async initWorker(): Promise<void> {
|
||||
// Skip initialization if vector search is not supported (e.g., Firefox)
|
||||
if (!isVectorSearchSupported()) {
|
||||
console.debug("[VectorWorkerManager] Vector search not supported - skipping worker initialization");
|
||||
verboseDebug("[VectorWorkerManager] Vector search not supported - skipping worker initialization");
|
||||
this.isInitialized = false;
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -55,19 +56,19 @@ export class VectorWorkerManager {
|
||||
if (this.isInitialized) return Promise.resolve();
|
||||
if (this.readyPromise) return this.readyPromise;
|
||||
|
||||
console.debug("Lazy-loading vector worker...");
|
||||
verboseDebug("Lazy-loading vector worker...");
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (this.worker) {
|
||||
console.debug("Terminating existing worker before creating new one");
|
||||
verboseDebug("Terminating existing worker before creating new one");
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
}
|
||||
|
||||
console.debug("Creating new vector worker instance");
|
||||
verboseDebug("Creating new vector worker instance");
|
||||
this.worker = vectorWorker();
|
||||
|
||||
console.log("Worker initialized", this.worker);
|
||||
verboseLog("Worker initialized", this.worker);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
console.error("Vector worker initialization timed out");
|
||||
@@ -82,14 +83,14 @@ export class VectorWorkerManager {
|
||||
|
||||
this.worker!.addEventListener("message", (e) => {
|
||||
const { type, data } = e.data;
|
||||
console.debug("Message from vector worker:", type, data);
|
||||
verboseDebug("Message from vector worker:", type, data);
|
||||
|
||||
switch (type) {
|
||||
case "ready":
|
||||
this.isInitialized = true;
|
||||
clearTimeout(timeout);
|
||||
this.updateActivity(); // Start idle timer after initialization
|
||||
console.debug("Vector worker initialized and ready.");
|
||||
verboseDebug("Vector worker initialized and ready.");
|
||||
resolve();
|
||||
break;
|
||||
|
||||
@@ -150,7 +151,7 @@ export class VectorWorkerManager {
|
||||
}
|
||||
|
||||
private resetWorkerState() {
|
||||
console.debug("Resetting vector worker state");
|
||||
verboseDebug("Resetting vector worker state");
|
||||
if (this.worker) {
|
||||
this.worker.terminate();
|
||||
this.worker = null;
|
||||
@@ -176,7 +177,7 @@ export class VectorWorkerManager {
|
||||
if (this.vectorizationLockCount > 0) return;
|
||||
if (this.streamingSession?.isActive) return;
|
||||
if (!this.isInitialized) return;
|
||||
console.debug("[VectorWorker] Auto-shutting down due to 2 minutes of inactivity");
|
||||
verboseDebug("[VectorWorker] Auto-shutting down due to 2 minutes of inactivity");
|
||||
this.resetWorkerState();
|
||||
}, 120000); // 2 minutes
|
||||
}
|
||||
@@ -208,7 +209,7 @@ export class VectorWorkerManager {
|
||||
this.unloadTimer = setTimeout(() => {
|
||||
if (this.vectorizationLockCount > 0) return;
|
||||
if (!this.streamingSession?.isActive && this.isInitialized) {
|
||||
console.debug("[VectorWorker] Auto-unloading after processing complete");
|
||||
verboseDebug("[VectorWorker] Auto-unloading after processing complete");
|
||||
this.resetWorkerState();
|
||||
}
|
||||
}, delay);
|
||||
@@ -295,7 +296,7 @@ export class VectorWorkerManager {
|
||||
});
|
||||
|
||||
if (uniqueItems.length !== items.length) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Filtered out ${items.length - uniqueItems.length} duplicate items before processing`,
|
||||
);
|
||||
}
|
||||
@@ -350,7 +351,7 @@ export class VectorWorkerManager {
|
||||
};
|
||||
this.progressCallback = wrap;
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Sending ${uniqueItems.length} unique items to worker for processing.`,
|
||||
);
|
||||
|
||||
@@ -378,7 +379,7 @@ export class VectorWorkerManager {
|
||||
): Promise<void> {
|
||||
// Skip if vector search is not supported
|
||||
if (!isVectorSearchSupported()) {
|
||||
console.debug("[VectorWorker] Vector search not supported - skipping streaming session");
|
||||
verboseDebug("[VectorWorker] Vector search not supported - skipping streaming session");
|
||||
if (onProgress) {
|
||||
onProgress({
|
||||
status: "complete",
|
||||
@@ -390,7 +391,7 @@ export class VectorWorkerManager {
|
||||
|
||||
// Only initialize if we expect items to process
|
||||
if (totalExpectedItems === 0) {
|
||||
console.debug("[VectorWorker] No items expected, not starting streaming session");
|
||||
verboseDebug("[VectorWorker] No items expected, not starting streaming session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -405,7 +406,7 @@ export class VectorWorkerManager {
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
} else {
|
||||
console.debug(`Streaming session for job ${jobId} already active`);
|
||||
verboseDebug(`Streaming session for job ${jobId} already active`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -425,7 +426,7 @@ export class VectorWorkerManager {
|
||||
lastActivityTime: Date.now(),
|
||||
};
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Starting streaming session for job ${jobId} with ${totalExpectedItems} items (batch size ${batchSize})`,
|
||||
);
|
||||
|
||||
@@ -456,7 +457,7 @@ export class VectorWorkerManager {
|
||||
});
|
||||
|
||||
if (uniqueItems.length !== items.length) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`[Streaming] Filtered out ${items.length - uniqueItems.length} duplicate items before streaming`,
|
||||
);
|
||||
}
|
||||
@@ -472,7 +473,7 @@ export class VectorWorkerManager {
|
||||
|
||||
this.streamingSession.inactivityTimer = setTimeout(() => {
|
||||
if (this.streamingSession?.isActive) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[VectorWorker] Auto-ending streaming session due to inactivity",
|
||||
);
|
||||
this.endStreamingSession();
|
||||
@@ -513,7 +514,7 @@ export class VectorWorkerManager {
|
||||
this.streamingSession.flushTimer = null;
|
||||
}
|
||||
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`Streaming batch of ${batch.length} items to worker (${this.streamingSession.totalSent}/${this.streamingSession.totalExpected})`,
|
||||
);
|
||||
|
||||
@@ -549,7 +550,7 @@ export class VectorWorkerManager {
|
||||
type: "endStreaming",
|
||||
});
|
||||
|
||||
console.debug("Streaming session ended");
|
||||
verboseDebug("Streaming session ended");
|
||||
|
||||
if (this.progressCallback) {
|
||||
this.progressCallback({
|
||||
@@ -590,12 +591,12 @@ export class VectorWorkerManager {
|
||||
}
|
||||
|
||||
terminate() {
|
||||
console.debug("Terminating Vector Worker Manager...");
|
||||
verboseDebug("Terminating Vector Worker Manager...");
|
||||
this.resetWorkerState();
|
||||
}
|
||||
|
||||
async resetWorker(): Promise<void> {
|
||||
console.debug("Resetting vector worker...");
|
||||
verboseDebug("Resetting vector worker...");
|
||||
|
||||
if (this.streamingSession?.isActive) {
|
||||
await this.endStreamingSession();
|
||||
@@ -605,6 +606,6 @@ export class VectorWorkerManager {
|
||||
|
||||
this.worker!.postMessage({ type: "reset" });
|
||||
|
||||
console.debug("Reset command sent to worker");
|
||||
verboseDebug("Reset command sent to worker");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
isStrongLexicalMatch,
|
||||
STRONG_LEXICAL_THRESHOLD,
|
||||
} from "./lexicalMatch";
|
||||
import { verboseDebug, verboseInfo, verboseLog } from "@/utils/verboseLog";
|
||||
|
||||
/** Same normalization as lexical matching (trim + lowercase). */
|
||||
function normSearchKey(s: string): string {
|
||||
@@ -91,7 +92,7 @@ function setCachedResults(query: string, results: CombinedResult[]) {
|
||||
*/
|
||||
export function clearSearchCache(): void {
|
||||
searchCache.clear();
|
||||
console.debug("[Search] Search result cache cleared");
|
||||
verboseDebug("[Search] Search result cache cleared");
|
||||
}
|
||||
|
||||
// Listen for cache clear events (e.g., on extension update)
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { IndexItem } from "../../indexing/types";
|
||||
import type { SearchResult } from "embeddia";
|
||||
import { isVectorSearchSupported } from "../../utils/browserDetection";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
let vectorIndex: EmbeddingIndex | null = null;
|
||||
let initializationAttempted = false;
|
||||
let initializationFailed = false;
|
||||
@@ -11,7 +12,7 @@ export async function initVectorSearch() {
|
||||
// Skip initialization if already attempted and failed, or if not supported
|
||||
if (initializationFailed || !isVectorSearchSupported()) {
|
||||
if (!isVectorSearchSupported()) {
|
||||
console.debug("[Vector Search] Vector search not supported in Firefox - using text search only");
|
||||
verboseDebug("[Vector Search] Vector search not supported in Firefox - using text search only");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -26,7 +27,7 @@ export async function initVectorSearch() {
|
||||
await initializeModel();
|
||||
vectorIndex = new EmbeddingIndex([]);
|
||||
vectorIndex.preloadIndexedDB();
|
||||
console.debug("[Vector Search] Initialized successfully");
|
||||
verboseDebug("[Vector Search] Initialized successfully");
|
||||
} catch (e) {
|
||||
console.warn("[Vector Search] Failed to initialize vector search (will use text search only):", e);
|
||||
initializationFailed = true;
|
||||
@@ -66,7 +67,7 @@ function setCachedEmbedding(query: string, embedding: number[]) {
|
||||
*/
|
||||
export function clearEmbeddingCache(): void {
|
||||
embeddingCache.clear();
|
||||
console.debug("[Vector Search] Embedding cache cleared");
|
||||
verboseDebug("[Vector Search] Embedding cache cleared");
|
||||
}
|
||||
|
||||
// Listen for cache clear events (e.g., on extension update)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import browser from "webextension-polyfill";
|
||||
import { resetSearchIndexes } from "../indexing/resetIndexes";
|
||||
|
||||
import { verboseDebug, verboseInfo, verboseLog } from '@/utils/verboseLog';
|
||||
const VERSION_STORAGE_KEY = "betterseqta-global-search-version";
|
||||
const VERSION_CACHE_KEY = "betterseqta-global-search-cache-version";
|
||||
|
||||
@@ -60,7 +61,7 @@ export async function checkAndHandleUpdate(): Promise<boolean> {
|
||||
// First run: just remember the version, don't reset (the user likely
|
||||
// just installed the extension; the index is already empty).
|
||||
if (!storedVersion) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
`[Version Check] First run detected, storing version ${currentVersion}`,
|
||||
);
|
||||
storeVersion(currentVersion);
|
||||
@@ -71,7 +72,7 @@ export async function checkAndHandleUpdate(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(
|
||||
verboseLog(
|
||||
`[Version Check] Extension updated from ${storedVersion} to ${currentVersion}, resetting search index...`,
|
||||
);
|
||||
|
||||
@@ -79,7 +80,7 @@ export async function checkAndHandleUpdate(): Promise<boolean> {
|
||||
|
||||
try {
|
||||
await resetSearchIndexes();
|
||||
console.log(
|
||||
verboseLog(
|
||||
"[Version Check] Search index reset; next indexing pass will repopulate from scratch.",
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -112,7 +113,7 @@ export async function clearAllCaches(): Promise<void> {
|
||||
} catch (e: any) {
|
||||
// Module might not be loaded yet, or CSS preload error - that's okay
|
||||
if (!e?.message?.includes("preload CSS") && !e?.message?.includes("MIME type")) {
|
||||
console.debug("[Version Check] Could not clear search cache:", e);
|
||||
verboseDebug("[Version Check] Could not clear search cache:", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,12 +123,12 @@ export async function clearAllCaches(): Promise<void> {
|
||||
} catch (e: any) {
|
||||
// Module might not be loaded yet, or CSS preload error - that's okay
|
||||
if (!e?.message?.includes("preload CSS") && !e?.message?.includes("MIME type")) {
|
||||
console.debug("[Version Check] Could not clear embedding cache:", e);
|
||||
verboseDebug("[Version Check] Could not clear embedding cache:", e);
|
||||
}
|
||||
}
|
||||
}, 50);
|
||||
|
||||
console.debug("[Version Check] All caches cleared");
|
||||
verboseDebug("[Version Check] All caches cleared");
|
||||
} catch (e) {
|
||||
console.error("[Version Check] Error clearing caches:", e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Plugin } from "../../core/types";
|
||||
import { isSeqtaEngageExperience } from "@/seqta/utils/isSeqtaEngage";
|
||||
import { verboseInfo } from "@/utils/verboseLog";
|
||||
|
||||
interface NotificationCollectorStorage {
|
||||
lastNotificationCount: number;
|
||||
@@ -75,7 +76,7 @@ const notificationCollectorPlugin: Plugin<{}, NotificationCollectorStorage> = {
|
||||
if (alertDiv) {
|
||||
alertDiv.textContent = notificationCount.toString();
|
||||
} else {
|
||||
console.info("[BetterSEQTA+] No notifications currently");
|
||||
verboseInfo("[BetterSEQTA+] No notifications currently");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[BetterSEQTA+] Error fetching notifications:", error);
|
||||
|
||||
@@ -17,6 +17,12 @@ import {
|
||||
clearCustomThemeAdaptiveCssVariables,
|
||||
setCustomThemeAdaptiveCssVariables,
|
||||
} from "@/seqta/ui/colors/customThemeAdaptiveBindings";
|
||||
import {
|
||||
clearThemeInPage,
|
||||
syncThemeToPage,
|
||||
type ThemePageSyncInput,
|
||||
} from "@/seqta/utils/patchThemeImagesPageContext";
|
||||
import { verboseDebug, verboseInfo } from "@/utils/verboseLog";
|
||||
import {
|
||||
clearThemeRuntime,
|
||||
injectThemeDom,
|
||||
@@ -56,18 +62,15 @@ export type InstallThemeMeta = {
|
||||
export class ThemeManager {
|
||||
private static instance: ThemeManager;
|
||||
private currentTheme: CustomTheme | null = null;
|
||||
private styleElement: HTMLStyleElement | null = null;
|
||||
private previewStyleElement: HTMLStyleElement | null = null;
|
||||
private previousImageVariableNames: string[] = [];
|
||||
private lastSyncedImageKey: string | null = null;
|
||||
private originalPreviewColor: string | null = null;
|
||||
private originalPreviewTheme: boolean | null = null;
|
||||
private imageUrlCache: Map<string, string> = new Map();
|
||||
private lastTransitionPoint: { x: number; y: number } = { x: 0, y: 0 };
|
||||
private storeUpdateCheckRunning = false;
|
||||
private headObserver: MutationObserver | null = null;
|
||||
|
||||
private constructor() {
|
||||
console.debug("[ThemeManager] Initializing...");
|
||||
verboseDebug("[ThemeManager] Initializing...");
|
||||
}
|
||||
|
||||
public static getInstance(): ThemeManager {
|
||||
@@ -88,7 +91,7 @@ export class ThemeManager {
|
||||
* Get a theme by ID from storage
|
||||
*/
|
||||
public async getTheme(themeId: string): Promise<CustomTheme | null> {
|
||||
console.debug("[ThemeManager] Getting theme:", themeId);
|
||||
verboseDebug("[ThemeManager] Getting theme:", themeId);
|
||||
try {
|
||||
const theme = (await localforage.getItem(themeId)) as CustomTheme;
|
||||
return theme;
|
||||
@@ -164,17 +167,17 @@ export class ThemeManager {
|
||||
* Disable the current theme without deleting it
|
||||
*/
|
||||
public async disableTheme(): Promise<void> {
|
||||
console.debug("[ThemeManager] Disabling current theme");
|
||||
verboseDebug("[ThemeManager] Disabling current theme");
|
||||
try {
|
||||
if (!this.currentTheme) {
|
||||
console.debug("[ThemeManager] No theme to disable");
|
||||
verboseDebug("[ThemeManager] No theme to disable");
|
||||
return;
|
||||
}
|
||||
|
||||
await this.removeTheme(this.currentTheme);
|
||||
this.currentTheme = null;
|
||||
settingsState.selectedTheme = "";
|
||||
console.debug("[ThemeManager] Theme disabled successfully");
|
||||
verboseDebug("[ThemeManager] Theme disabled successfully");
|
||||
} catch (error) {
|
||||
console.error("[ThemeManager] Error disabling theme:", error);
|
||||
}
|
||||
@@ -211,7 +214,7 @@ export class ThemeManager {
|
||||
* Initialize the theme system and restore previous state
|
||||
*/
|
||||
public async initialize(): Promise<void> {
|
||||
console.debug("[ThemeManager] Starting initialization");
|
||||
verboseDebug("[ThemeManager] Starting initialization");
|
||||
try {
|
||||
const neumorphicThemeId = "9a9786d1-b5fc-4a91-8c7a-f8bf7f7679ad";
|
||||
const migrationCSS = "#title {\nbackground: transparent !important;\n}";
|
||||
@@ -224,7 +227,7 @@ export class ThemeManager {
|
||||
|
||||
const themeCreatorOpen = localStorage.getItem("themeCreatorOpen");
|
||||
if (themeCreatorOpen === "true") {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Theme creator was open, clearing preview state",
|
||||
);
|
||||
this.clearPreview();
|
||||
@@ -232,7 +235,7 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
if (settingsState.selectedTheme) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Found selected theme, restoring:",
|
||||
settingsState.selectedTheme,
|
||||
);
|
||||
@@ -249,7 +252,7 @@ export class ThemeManager {
|
||||
* Clean up theme system resources
|
||||
*/
|
||||
public async cleanup(): Promise<void> {
|
||||
console.debug("[ThemeManager] Cleaning up resources");
|
||||
verboseDebug("[ThemeManager] Cleaning up resources");
|
||||
try {
|
||||
if (this.currentTheme) {
|
||||
await this.removeTheme(this.currentTheme, false);
|
||||
@@ -263,7 +266,7 @@ export class ThemeManager {
|
||||
* Set and apply a theme by ID
|
||||
*/
|
||||
public async setTheme(themeId: string, applyViewTransition: boolean = true): Promise<void> {
|
||||
console.debug("[ThemeManager] Setting theme:", themeId);
|
||||
verboseDebug("[ThemeManager] Setting theme:", themeId);
|
||||
try {
|
||||
const theme = (await localforage.getItem(themeId)) as CustomTheme;
|
||||
if (!theme) {
|
||||
@@ -273,7 +276,7 @@ export class ThemeManager {
|
||||
|
||||
// Store original settings before applying new theme
|
||||
if (!settingsState.selectedTheme) {
|
||||
console.debug("[ThemeManager] Storing original settings");
|
||||
verboseDebug("[ThemeManager] Storing original settings");
|
||||
settingsState.originalSelectedColor = settingsState.selectedColor;
|
||||
|
||||
if (shouldForceThemeAppearance(theme)) {
|
||||
@@ -286,7 +289,7 @@ export class ThemeManager {
|
||||
await this.applyViewTransition(async () => {
|
||||
// Remove current theme if exists
|
||||
if (this.currentTheme) {
|
||||
console.debug("[ThemeManager] Removing current theme");
|
||||
verboseDebug("[ThemeManager] Removing current theme");
|
||||
await this.removeThemeWithoutTransition(this.currentTheme);
|
||||
}
|
||||
|
||||
@@ -298,7 +301,7 @@ export class ThemeManager {
|
||||
} else {
|
||||
// Remove current theme if exists
|
||||
if (this.currentTheme) {
|
||||
console.debug("[ThemeManager] Removing current theme");
|
||||
verboseDebug("[ThemeManager] Removing current theme");
|
||||
await this.removeThemeWithoutTransition(this.currentTheme);
|
||||
}
|
||||
|
||||
@@ -317,7 +320,7 @@ export class ThemeManager {
|
||||
* Apply theme components (CSS, images, settings)
|
||||
*/
|
||||
private async applyTheme(theme: CustomTheme): Promise<void> {
|
||||
console.debug("[ThemeManager] Applying theme:", theme.name);
|
||||
verboseDebug("[ThemeManager] Applying theme:", theme.name);
|
||||
try {
|
||||
// Run the theme script BEFORE injecting CustomCSS so any state the
|
||||
// script publishes (e.g. `data-city-state` and `--city-sky-color` for
|
||||
@@ -326,40 +329,34 @@ export class ThemeManager {
|
||||
// its previous state before snapping to the right colour.
|
||||
runThemeScript(theme.themeScript);
|
||||
|
||||
// Apply custom CSS
|
||||
if (theme.CustomCSS) {
|
||||
console.debug("[ThemeManager] Applying custom CSS");
|
||||
this.applyCustomCSS(theme.CustomCSS);
|
||||
}
|
||||
|
||||
// Apply custom images
|
||||
if (theme.CustomImages) {
|
||||
console.debug("[ThemeManager] Applying custom images");
|
||||
theme.CustomImages.forEach((image) => {
|
||||
const imageUrl = URL.createObjectURL(image.blob);
|
||||
document.documentElement.style.setProperty(
|
||||
"--" + image.variableName,
|
||||
`url(${imageUrl})`,
|
||||
);
|
||||
});
|
||||
// Custom CSS + images must be applied in page context (Firefox).
|
||||
verboseDebug("[ThemeManager] Applying theme styles in page context");
|
||||
await syncThemeToPage({
|
||||
customCss: theme.CustomCSS || "",
|
||||
images: theme.CustomImages ?? [],
|
||||
});
|
||||
if (theme.CustomImages?.length) {
|
||||
this.lastSyncedImageKey = this.imageSyncKey(theme.CustomImages);
|
||||
} else {
|
||||
this.lastSyncedImageKey = null;
|
||||
}
|
||||
|
||||
// Apply theme settings
|
||||
if (shouldForceThemeAppearance(theme)) {
|
||||
const dark = getForcedDarkMode(theme);
|
||||
console.debug("[ThemeManager] Setting dark mode:", dark);
|
||||
verboseDebug("[ThemeManager] Setting dark mode:", dark);
|
||||
settingsState.DarkMode = dark;
|
||||
}
|
||||
|
||||
// Use the stored selected color if available, otherwise use the default
|
||||
if (theme.selectedColor) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Restoring saved color:",
|
||||
theme.selectedColor,
|
||||
);
|
||||
settingsState.selectedColor = theme.selectedColor;
|
||||
} else if (theme.defaultColour) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Using default color:",
|
||||
theme.defaultColour,
|
||||
);
|
||||
@@ -381,7 +378,7 @@ export class ThemeManager {
|
||||
theme: CustomTheme,
|
||||
clearSelectedTheme: boolean = true,
|
||||
): Promise<void> {
|
||||
console.debug("[ThemeManager] Removing theme with transition:", theme.name);
|
||||
verboseDebug("[ThemeManager] Removing theme with transition:", theme.name);
|
||||
try {
|
||||
await this.applyViewTransition(async () => {
|
||||
await this.removeThemeWithoutTransition(theme, clearSelectedTheme);
|
||||
@@ -398,37 +395,13 @@ export class ThemeManager {
|
||||
theme: CustomTheme,
|
||||
clearSelectedTheme: boolean = true,
|
||||
): Promise<void> {
|
||||
console.debug("[ThemeManager] Removing theme:", theme.name);
|
||||
verboseDebug("[ThemeManager] Removing theme:", theme.name);
|
||||
try {
|
||||
clearThemeRuntime();
|
||||
|
||||
// Disconnect the head observer BEFORE removing the style element,
|
||||
// otherwise the removal fires the observer and it would no-op only
|
||||
// because the style is already gone — wasted work, but harmless.
|
||||
this.disconnectStyleObserver();
|
||||
|
||||
// Remove custom CSS
|
||||
if (this.styleElement) {
|
||||
console.debug("[ThemeManager] Removing custom CSS");
|
||||
this.styleElement.remove();
|
||||
this.styleElement = null;
|
||||
}
|
||||
|
||||
// Remove custom images
|
||||
if (theme.CustomImages) {
|
||||
console.debug("[ThemeManager] Removing custom images");
|
||||
theme.CustomImages.forEach((image) => {
|
||||
const value = document.documentElement.style.getPropertyValue(
|
||||
"--" + image.variableName,
|
||||
);
|
||||
if (value) {
|
||||
URL.revokeObjectURL(value.slice(4, -1)); // Remove url() wrapper
|
||||
}
|
||||
document.documentElement.style.removeProperty(
|
||||
"--" + image.variableName,
|
||||
);
|
||||
});
|
||||
}
|
||||
verboseDebug("[ThemeManager] Removing theme page styles");
|
||||
clearThemeInPage();
|
||||
this.lastSyncedImageKey = null;
|
||||
|
||||
if (this.currentTheme) {
|
||||
// Store the current color with the theme before removing it
|
||||
@@ -449,7 +422,7 @@ export class ThemeManager {
|
||||
|
||||
// Restore original settings
|
||||
if (settingsState.originalSelectedColor) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Restoring original color:",
|
||||
settingsState.originalSelectedColor,
|
||||
);
|
||||
@@ -457,7 +430,7 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
if (settingsState.originalDarkMode !== undefined) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Restoring original dark mode:",
|
||||
settingsState.originalDarkMode,
|
||||
);
|
||||
@@ -476,58 +449,21 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply custom CSS to the document. The `<style>` element is always
|
||||
* re-appended to the end of `<head>` so it wins specificity ties
|
||||
* against any styles SEQTA's late-loading injected.scss adds in dev
|
||||
* mode (where `import("@/css/injected.scss")` is fire-and-forget and
|
||||
* can resolve after the theme has already been applied). The head
|
||||
* observer below keeps us at the end if anything else gets appended
|
||||
* later (Vite HMR, another script-injected stylesheet, etc.).
|
||||
* Stable key so preview updates can skip re-encoding image blobs when only CSS changed.
|
||||
*/
|
||||
private applyCustomCSS(css: string): void {
|
||||
console.debug("[ThemeManager] Applying custom CSS");
|
||||
try {
|
||||
if (!this.styleElement) {
|
||||
this.styleElement = document.createElement("style");
|
||||
this.styleElement.id = "custom-theme";
|
||||
}
|
||||
this.styleElement.textContent = css;
|
||||
document.head.appendChild(this.styleElement);
|
||||
this.ensureStyleStaysLast();
|
||||
} catch (error) {
|
||||
console.error("[ThemeManager] Error applying custom CSS:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch `<head>` for any child-list changes and re-append the theme
|
||||
* style element if anything has been added after it. Idempotent: the
|
||||
* observer's own re-append fires the callback again, but the early
|
||||
* `lastElementChild === style` check short-circuits the second pass.
|
||||
*/
|
||||
private ensureStyleStaysLast(): void {
|
||||
if (this.headObserver) return;
|
||||
this.headObserver = new MutationObserver(() => {
|
||||
const style = this.styleElement;
|
||||
if (!style || !document.head.contains(style)) return;
|
||||
if (document.head.lastElementChild === style) return;
|
||||
document.head.appendChild(style);
|
||||
});
|
||||
this.headObserver.observe(document.head, { childList: true });
|
||||
}
|
||||
|
||||
private disconnectStyleObserver(): void {
|
||||
if (this.headObserver) {
|
||||
this.headObserver.disconnect();
|
||||
this.headObserver = null;
|
||||
}
|
||||
private imageSyncKey(
|
||||
images: Array<{ id: string; variableName: string; blob: Blob }>,
|
||||
): string {
|
||||
return images
|
||||
.map((image) => `${image.id}:${image.variableName}:${image.blob.size}`)
|
||||
.join("|");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of available themes
|
||||
*/
|
||||
public async getAvailableThemes(): Promise<CustomTheme[]> {
|
||||
console.debug("[ThemeManager] Getting available themes");
|
||||
verboseDebug("[ThemeManager] Getting available themes");
|
||||
try {
|
||||
const themeIds = (await localforage.getItem("customThemes")) as
|
||||
| string[]
|
||||
@@ -553,7 +489,7 @@ export class ThemeManager {
|
||||
* Save or update a theme
|
||||
*/
|
||||
public async saveTheme(theme: LoadedCustomTheme): Promise<void> {
|
||||
console.debug("[ThemeManager] Saving theme:", theme.name);
|
||||
verboseDebug("[ThemeManager] Saving theme:", theme.name);
|
||||
try {
|
||||
const existing = (await localforage.getItem(theme.id)) as CustomTheme | null;
|
||||
let toSave = theme;
|
||||
@@ -583,7 +519,7 @@ export class ThemeManager {
|
||||
* Delete a theme
|
||||
*/
|
||||
public async deleteTheme(themeId: string): Promise<void> {
|
||||
console.debug("[ThemeManager] Deleting theme:", themeId);
|
||||
verboseDebug("[ThemeManager] Deleting theme:", themeId);
|
||||
try {
|
||||
const theme = (await localforage.getItem(themeId)) as CustomTheme;
|
||||
if (theme) {
|
||||
@@ -653,7 +589,7 @@ export class ThemeManager {
|
||||
theme_json_url?: string;
|
||||
updated_at?: number;
|
||||
}): Promise<void> {
|
||||
console.debug("[ThemeManager] Downloading theme:", themeContent.name);
|
||||
verboseDebug("[ThemeManager] Downloading theme:", themeContent.name);
|
||||
if (!themeContent.id) {
|
||||
throw new Error("Missing theme id");
|
||||
}
|
||||
@@ -689,7 +625,7 @@ export class ThemeManager {
|
||||
themeData: ThemeContent,
|
||||
meta?: InstallThemeMeta,
|
||||
): Promise<void> {
|
||||
console.debug("[ThemeManager] Installing theme:", themeData.name);
|
||||
verboseDebug("[ThemeManager] Installing theme:", themeData.name);
|
||||
try {
|
||||
// Validate required fields
|
||||
if (!themeData.id || !themeData.name) {
|
||||
@@ -860,7 +796,7 @@ export class ThemeManager {
|
||||
name: theme.name,
|
||||
updated_at: serverUpdated,
|
||||
});
|
||||
console.log(
|
||||
verboseInfo(
|
||||
"[ThemeManager] Theme auto-updated from store:",
|
||||
theme.name,
|
||||
);
|
||||
@@ -893,7 +829,7 @@ export class ThemeManager {
|
||||
* Share a theme by exporting it
|
||||
*/
|
||||
public async shareTheme(themeId: string): Promise<void> {
|
||||
console.debug("[ThemeManager] Sharing theme:", themeId);
|
||||
verboseDebug("[ThemeManager] Sharing theme:", themeId);
|
||||
try {
|
||||
const theme = (await localforage.getItem(themeId)) as LoadedCustomTheme;
|
||||
if (!theme) {
|
||||
@@ -947,7 +883,7 @@ export class ThemeManager {
|
||||
* Preview a theme without applying it
|
||||
*/
|
||||
public async previewTheme(theme: LoadedCustomTheme): Promise<void> {
|
||||
console.debug("[ThemeManager] Previewing theme:", theme.name);
|
||||
verboseDebug("[ThemeManager] Previewing theme:", theme.name);
|
||||
try {
|
||||
const { CustomCSS, CustomImages, defaultColour } = theme;
|
||||
|
||||
@@ -965,35 +901,16 @@ export class ThemeManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply custom CSS
|
||||
if (CustomCSS) {
|
||||
this.applyPreviewCSS(CustomCSS);
|
||||
}
|
||||
|
||||
// Apply custom images
|
||||
const newImageVariableNames = CustomImages.map(
|
||||
// Apply custom CSS + images in page context (preview stylesheet)
|
||||
await syncThemeToPage({
|
||||
previewCss: CustomCSS,
|
||||
images: CustomImages,
|
||||
});
|
||||
this.lastSyncedImageKey = this.imageSyncKey(CustomImages);
|
||||
this.previousImageVariableNames = CustomImages.map(
|
||||
(image) => image.variableName,
|
||||
);
|
||||
|
||||
// Remove old preview images
|
||||
this.previousImageVariableNames.forEach((variableName) => {
|
||||
if (!newImageVariableNames.includes(variableName)) {
|
||||
this.removeImageFromDocument(variableName);
|
||||
}
|
||||
});
|
||||
|
||||
// Apply new images
|
||||
CustomImages.forEach((image) => {
|
||||
const imageUrl = URL.createObjectURL(image.blob);
|
||||
document.documentElement.style.setProperty(
|
||||
`--${image.variableName}`,
|
||||
`url(${imageUrl})`,
|
||||
);
|
||||
});
|
||||
|
||||
// Update previousImageVariableNames
|
||||
this.previousImageVariableNames = newImageVariableNames;
|
||||
|
||||
// Apply theme settings
|
||||
if (shouldForceThemeAppearance(theme)) {
|
||||
settingsState.DarkMode = getForcedDarkMode(theme);
|
||||
@@ -1014,7 +931,7 @@ export class ThemeManager {
|
||||
* Update the preview of a theme in real-time (for theme creator)
|
||||
*/
|
||||
public async updatePreview(theme: Partial<LoadedCustomTheme>): Promise<void> {
|
||||
console.debug("[ThemeManager] Updating theme preview");
|
||||
verboseDebug("[ThemeManager] Updating theme preview");
|
||||
try {
|
||||
// Only store original settings if this is a new theme (not editing)
|
||||
// We can tell it's a new theme if it has no webURL (which is set when a theme is saved/loaded)
|
||||
@@ -1027,49 +944,28 @@ export class ThemeManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Apply CSS if changed
|
||||
const newImageVariableNames =
|
||||
theme.CustomImages?.map((image) => image.variableName) ?? [];
|
||||
|
||||
const syncInput: ThemePageSyncInput = {};
|
||||
|
||||
if (theme.CustomCSS !== undefined) {
|
||||
this.applyPreviewCSS(theme.CustomCSS);
|
||||
syncInput.previewCss = theme.CustomCSS;
|
||||
}
|
||||
|
||||
// Handle images if present
|
||||
if (theme.CustomImages) {
|
||||
const newImageVariableNames = theme.CustomImages.map(
|
||||
(image) => image.variableName,
|
||||
);
|
||||
|
||||
// Remove old preview images that are no longer present
|
||||
this.previousImageVariableNames.forEach((variableName) => {
|
||||
if (!newImageVariableNames.includes(variableName)) {
|
||||
this.removeImageFromDocument(variableName);
|
||||
// Clean up cached URL
|
||||
this.imageUrlCache.delete(variableName);
|
||||
}
|
||||
});
|
||||
|
||||
// Apply or update images
|
||||
theme.CustomImages.forEach((image) => {
|
||||
const existingUrl = this.imageUrlCache.get(image.variableName);
|
||||
if (!existingUrl) {
|
||||
// Only create new URL if one doesn't exist
|
||||
const imageUrl = URL.createObjectURL(image.blob);
|
||||
this.imageUrlCache.set(image.variableName, imageUrl);
|
||||
document.documentElement.style.setProperty(
|
||||
`--${image.variableName}`,
|
||||
`url(${imageUrl})`,
|
||||
);
|
||||
} else {
|
||||
// Reuse existing URL
|
||||
document.documentElement.style.setProperty(
|
||||
`--${image.variableName}`,
|
||||
`url(${existingUrl})`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const imageKey = this.imageSyncKey(theme.CustomImages);
|
||||
if (imageKey !== this.lastSyncedImageKey) {
|
||||
syncInput.images = theme.CustomImages;
|
||||
this.lastSyncedImageKey = imageKey;
|
||||
}
|
||||
this.previousImageVariableNames = newImageVariableNames;
|
||||
}
|
||||
|
||||
if (Object.keys(syncInput).length > 0) {
|
||||
await syncThemeToPage(syncInput);
|
||||
}
|
||||
|
||||
// Always apply dark mode setting when theme forces appearance
|
||||
if (shouldForceThemeAppearance(theme as CustomTheme)) {
|
||||
settingsState.DarkMode = getForcedDarkMode(theme as CustomTheme);
|
||||
@@ -1102,23 +998,12 @@ export class ThemeManager {
|
||||
* Clear theme preview
|
||||
*/
|
||||
public clearPreview(): void {
|
||||
console.debug("[ThemeManager] Clearing theme preview");
|
||||
verboseDebug("[ThemeManager] Clearing theme preview");
|
||||
try {
|
||||
// Remove preview images and revoke URLs
|
||||
this.previousImageVariableNames.forEach((variableName) => {
|
||||
this.removeImageFromDocument(variableName);
|
||||
});
|
||||
// Clear all cached URLs
|
||||
this.imageUrlCache.forEach((url) => URL.revokeObjectURL(url));
|
||||
this.imageUrlCache.clear();
|
||||
void syncThemeToPage({ clearPreview: true, images: [] });
|
||||
this.lastSyncedImageKey = null;
|
||||
this.previousImageVariableNames = [];
|
||||
|
||||
// Remove preview CSS
|
||||
if (this.previewStyleElement) {
|
||||
this.previewStyleElement.remove();
|
||||
this.previewStyleElement = null;
|
||||
}
|
||||
|
||||
clearCustomThemeAdaptiveCssVariables();
|
||||
|
||||
// Restore original settings
|
||||
@@ -1128,22 +1013,22 @@ export class ThemeManager {
|
||||
settingsState.selectedColor = storedColor;
|
||||
localStorage.removeItem("originalPreviewColor");
|
||||
} else if (this.originalPreviewColor !== null) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Restoring color from memory:",
|
||||
this.originalPreviewColor,
|
||||
);
|
||||
settingsState.selectedColor = this.originalPreviewColor;
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Color after restore:",
|
||||
settingsState.selectedColor,
|
||||
);
|
||||
} else {
|
||||
console.debug("[ThemeManager] No color to restore found");
|
||||
verboseDebug("[ThemeManager] No color to restore found");
|
||||
}
|
||||
this.originalPreviewColor = null;
|
||||
|
||||
if (this.originalPreviewTheme !== null) {
|
||||
console.debug(
|
||||
verboseDebug(
|
||||
"[ThemeManager] Restoring dark mode:",
|
||||
this.originalPreviewTheme,
|
||||
);
|
||||
@@ -1218,36 +1103,4 @@ export class ThemeManager {
|
||||
console.error("[ThemeManager] Error saving theme file:", err);
|
||||
}
|
||||
}
|
||||
|
||||
private removeImageFromDocument(variableName: string): void {
|
||||
try {
|
||||
const value = document.documentElement.style.getPropertyValue(
|
||||
"--" + variableName,
|
||||
);
|
||||
if (value) {
|
||||
const url = this.imageUrlCache.get(variableName);
|
||||
if (url) {
|
||||
URL.revokeObjectURL(url);
|
||||
this.imageUrlCache.delete(variableName);
|
||||
}
|
||||
}
|
||||
document.documentElement.style.removeProperty("--" + variableName);
|
||||
} catch (err) {
|
||||
console.error("[ThemeManager] Error removing image from document:", err);
|
||||
}
|
||||
}
|
||||
|
||||
private applyPreviewCSS(css: string): void {
|
||||
console.debug("[ThemeManager] Applying preview CSS");
|
||||
try {
|
||||
if (!this.previewStyleElement) {
|
||||
this.previewStyleElement = document.createElement("style");
|
||||
this.previewStyleElement.id = "custom-theme-preview";
|
||||
document.head.appendChild(this.previewStyleElement);
|
||||
}
|
||||
this.previewStyleElement.textContent = css;
|
||||
} catch (error) {
|
||||
console.error("[ThemeManager] Error applying preview CSS:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Theme decorative images must use data URLs instead of blob URLs on Firefox:
|
||||
* blob: URLs are tied to the origin where createObjectURL ran (page), while
|
||||
* settings UI runs in extension shadow DOM (moz-extension://).
|
||||
*/
|
||||
export function blobToDataUrl(blob: Blob): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
if (typeof reader.result === "string") {
|
||||
resolve(reader.result);
|
||||
} else {
|
||||
reject(new Error("FileReader did not return a string"));
|
||||
}
|
||||
};
|
||||
reader.onerror = () =>
|
||||
reject(reader.error ?? new Error("FileReader failed"));
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
/** Base64 payload only (no `data:…;base64,` prefix) for the page-context bridge. */
|
||||
export function blobToBase64Data(blob: Blob): Promise<string> {
|
||||
return blobToDataUrl(blob).then((dataUrl) => {
|
||||
const comma = dataUrl.indexOf(",");
|
||||
return comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl;
|
||||
});
|
||||
}
|
||||
|
||||
export function themeCssUrlValue(url: string): string {
|
||||
return `url("${url.replace(/"/g, "%22")}")`;
|
||||
}
|
||||
|
||||
export function releaseThemeImageUrl(url: string): void {
|
||||
if (url.startsWith("blob:")) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import type { Plugin } from "../../core/types";
|
||||
import { attachTimetableColorisRecovery } from "@/seqta/utils/timetableColoris";
|
||||
import { convertTo12HourFormat } from "@/seqta/utils/convertTo12HourFormat";
|
||||
import { waitForElm } from "@/seqta/utils/waitForElm";
|
||||
import { verboseLog } from "@/utils/verboseLog";
|
||||
|
||||
const timetablePlugin: Plugin<{}, {}> = {
|
||||
id: "timetable",
|
||||
@@ -87,7 +88,7 @@ async function handleTimetable(): Promise<void> {
|
||||
}
|
||||
|
||||
function handleTimetableZoom(): void {
|
||||
console.log("Initializing timetable zoom controls");
|
||||
verboseLog("Initializing timetable zoom controls");
|
||||
|
||||
// Create zoom controls
|
||||
const zoomControls = document.createElement("div");
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { Plugin, PluginSettings } from "./types";
|
||||
import { verboseInfo } from "@/utils/verboseLog";
|
||||
|
||||
/**
|
||||
* Interface for lazy-loaded plugin definitions
|
||||
@@ -37,13 +38,13 @@ export function createLazyPlugin<T extends PluginSettings = PluginSettings, S =
|
||||
beta: lazyPlugin.beta,
|
||||
|
||||
run: async (api) => {
|
||||
console.info(`[BetterSEQTA+] Dynamically loading plugin "${lazyPlugin.id}"...`);
|
||||
verboseInfo(`[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}"`);
|
||||
verboseInfo(`[BetterSEQTA+] Successfully loaded plugin "${lazyPlugin.id}"`);
|
||||
|
||||
// Execute the actual plugin's run function
|
||||
return await actualPlugin.run(api);
|
||||
|
||||
@@ -12,6 +12,7 @@ import type {
|
||||
import { createPluginAPI } from "./createAPI";
|
||||
import browser from "webextension-polyfill";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
import { verboseInfo } from "@/utils/verboseLog";
|
||||
|
||||
interface PluginSettingsStorage {
|
||||
enabled?: boolean;
|
||||
@@ -158,7 +159,7 @@ export class PluginManager {
|
||||
const enabled =
|
||||
pluginSettings?.enabled ?? plugin.defaultEnabled ?? true;
|
||||
if (!enabled) {
|
||||
console.info(
|
||||
verboseInfo(
|
||||
`Plugin "${pluginId}" is disabled, skipping initialization`,
|
||||
);
|
||||
return;
|
||||
@@ -181,7 +182,7 @@ export class PluginManager {
|
||||
this.cleanupFunctions.set(plugin.id, result);
|
||||
}
|
||||
this.runningPlugins.set(pluginId, true);
|
||||
console.info(`Plugin "${pluginId}" started successfully`);
|
||||
verboseInfo(`Plugin "${pluginId}" started successfully`);
|
||||
|
||||
// Process any backlogged events
|
||||
await this.processBackloggedEvents(pluginId);
|
||||
@@ -238,7 +239,7 @@ export class PluginManager {
|
||||
this.cleanupFunctions.delete(pluginId);
|
||||
}
|
||||
this.runningPlugins.set(pluginId, false);
|
||||
console.info(`Plugin "${pluginId}" stopped`);
|
||||
verboseInfo(`Plugin "${pluginId}" stopped`);
|
||||
this.emit("plugin.stopped", pluginId);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import RegisterClickListeners from "@/seqta/utils/listeners/ClickListeners";
|
||||
import { AddBetterSEQTAElements } from "@/seqta/ui/AddBetterSEQTAElements";
|
||||
import { updateAllColors } from "@/seqta/ui/colors/Manager";
|
||||
import { applySelectedFont } from "@/seqta/ui/fonts/Manager";
|
||||
import { verboseInfo, verboseLog } from "@/utils/verboseLog";
|
||||
import loading from "@/seqta/ui/Loading";
|
||||
import { SendNewsPage } from "@/seqta/utils/SendNewsPage";
|
||||
import { getEngageRoutePage } from "@/seqta/utils/engageRoute";
|
||||
@@ -300,7 +301,7 @@ async function handleSublink(sublink: string | undefined): Promise<void> {
|
||||
break;
|
||||
case "home":
|
||||
window.location.replace(`${location.origin}/#?page=/home`);
|
||||
console.info("[BetterSEQTA+] Started Init (SEQTA Engage home)");
|
||||
verboseInfo("[BetterSEQTA+] Started Init (SEQTA Engage home)");
|
||||
if (settingsState.onoff) void loadEngageHomePage();
|
||||
finishLoad();
|
||||
break;
|
||||
@@ -316,7 +317,7 @@ async function handleSublink(sublink: string | undefined): Promise<void> {
|
||||
await handleNewsPage();
|
||||
break;
|
||||
case "analytics":
|
||||
console.info("[BetterSEQTA+] Started Init (Analytics)");
|
||||
verboseInfo("[BetterSEQTA+] Started Init (Analytics)");
|
||||
if (settingsState.onoff) void loadAnalyticsPage();
|
||||
finishLoad();
|
||||
break;
|
||||
@@ -336,7 +337,7 @@ async function handleSublink(sublink: string | undefined): Promise<void> {
|
||||
break;
|
||||
case "home":
|
||||
window.location.replace(`${location.origin}/#?page=/home`);
|
||||
console.info("[BetterSEQTA+] Started Init");
|
||||
verboseInfo("[BetterSEQTA+] Started Init");
|
||||
if (settingsState.onoff) loadHomePage();
|
||||
finishLoad();
|
||||
break;
|
||||
@@ -353,7 +354,7 @@ async function handleNewsPage(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
console.info("[BetterSEQTA+] Started Init");
|
||||
verboseInfo("[BetterSEQTA+] Started Init");
|
||||
try {
|
||||
await SendNewsPage();
|
||||
} catch (error) {
|
||||
@@ -682,7 +683,7 @@ export function init() {
|
||||
};
|
||||
|
||||
if (settingsState.onoff) {
|
||||
console.info("[BetterSEQTA+] Enabled");
|
||||
verboseInfo("[BetterSEQTA+] Enabled");
|
||||
if (settingsState.DarkMode) document.documentElement.classList.add("dark");
|
||||
if (settingsState.iconOnlySidebar) {
|
||||
if (document.body) {
|
||||
@@ -783,7 +784,7 @@ export function init() {
|
||||
".outside-container .bottom-container",
|
||||
);
|
||||
if (legacyElement) {
|
||||
console.log("Legacy extension detected");
|
||||
verboseLog("Legacy extension detected");
|
||||
showConflictPopup();
|
||||
}
|
||||
}, 1000);
|
||||
@@ -795,7 +796,7 @@ export function init() {
|
||||
}
|
||||
|
||||
function InjectCustomIcons() {
|
||||
console.info("[BetterSEQTA+] Injecting Icons");
|
||||
verboseInfo("[BetterSEQTA+] Injecting Icons");
|
||||
|
||||
const style = document.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
@@ -812,7 +813,7 @@ function InjectCustomIcons() {
|
||||
export function AppendElementsToDisabledPage() {
|
||||
if (document.getElementById("AddedSettings")) return;
|
||||
|
||||
console.info("[BetterSEQTA+] Appending elements to disabled page");
|
||||
verboseInfo("[BetterSEQTA+] Appending elements to disabled page");
|
||||
AddBetterSEQTAElements();
|
||||
|
||||
let settingsStyle = document.createElement("style");
|
||||
|
||||
Reference in New Issue
Block a user