From 78c00fcb3d48f110d4b430fcf6e1d7afc46860e1 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Sat, 25 May 2024 21:50:22 +0200 Subject: [PATCH 01/40] Enhance Balloon spawn console log statements #200 --- src/background/background.ts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index c95c5130..db929649 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -84,37 +84,45 @@ const updateBadgeColors = () => { }; const spawnBalloon = async () => { + console.groupCollapsed(`Spawning Balloon...`); + const now = Date.now(); const minSpawnInterval = (await storage.get('config')).spawnInterval.min; - const skipSpawnMessage = (note: any, level: 'log' | 'warn' = 'warn') => + const skipSpawnMessage = (note: any, level: 'log' | 'warn' = 'warn') => { console[level](`Skipping spawnBalloon message: \r\n\t`, note); + console.groupEnd(); + }; // Check if there is a spawn timeout if (spawnTimeout !== null && Date.now() < spawnTimeout) return skipSpawnMessage('balloon spawn in timeout'); + console.log(' - No spawn timeout'); // Check if the last spawn was too recent if (lastSpawn && now - lastSpawn < minSpawnInterval) { spawnTimeout = now + rapidSpawnPenalty; return skipSpawnMessage('Spawned too recently, setting timeout'); } - - // Get all active tabs - const tabs = await browser.tabs.query({ active: true }); - // Select a random tab - const num = Math.round(random(0, tabs.length - 1)); - const tab = tabs[num]; - if (!tab.id) return skipSpawnMessage('No tab id'); + console.log(' - Last spawn was not too recent'); // Check if the browser is idle const state = await browser.idle.queryState(5 * 60); if (state !== 'active') return skipSpawnMessage('Browser is idle', 'log'); + console.log(' - Browser is not idle'); // Check if no spawn alarms are already set const alarms = await browser.alarms.getAll(); if (alarms.some((alarm) => alarm.name === 'spawnBalloon')) return skipSpawnMessage('Spawn alarm already set'); - console.log(`Spawning balloon on tab`, tab.id); + console.log(' - No spawn alarm already set'); + + // Get all active tabs + const tabs = await browser.tabs.query({ active: true }); + // Select a random tab + const num = Math.round(random(0, tabs.length - 1)); + const tab = tabs[num]; + if (!tab.id) return skipSpawnMessage('No tab id', 'warn'); + console.log(' - Selected tab', tab.id); try { // Execute content script on tab @@ -122,8 +130,10 @@ const updateBadgeColors = () => { files: ['spawn-balloon.js'], target: { tabId: tab.id }, }); + console.log(' - Successfully sent spawn balloon script to tab', tab.id); } catch (e) {} lastSpawn = now; + console.groupEnd(); }; const createSpawnAlarm = async (name: AlarmName) => { From 7249095c8170ed85e36a1af024ed150cb3b76b1f Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Sat, 25 May 2024 21:50:40 +0200 Subject: [PATCH 02/40] Update Balloon spawn console log statements with timestamp #200 --- src/background/background.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/background/background.ts b/src/background/background.ts index db929649..39b98591 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -84,7 +84,9 @@ const updateBadgeColors = () => { }; const spawnBalloon = async () => { - console.groupCollapsed(`Spawning Balloon...`); + console.groupCollapsed( + `(${new Date().toLocaleTimeString()}) Spawning Balloon...` + ); const now = Date.now(); const minSpawnInterval = (await storage.get('config')).spawnInterval.min; From d04f58e5c38cb66872620519766ed8f60cbea667 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Mon, 27 May 2024 22:41:01 +0200 Subject: [PATCH 03/40] Log balloon spawn time #200 --- src/background/background.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/background/background.ts b/src/background/background.ts index 39b98591..c9e68847 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -87,11 +87,13 @@ const updateBadgeColors = () => { console.groupCollapsed( `(${new Date().toLocaleTimeString()}) Spawning Balloon...` ); + console.time('Spawn Time'); const now = Date.now(); const minSpawnInterval = (await storage.get('config')).spawnInterval.min; const skipSpawnMessage = (note: any, level: 'log' | 'warn' = 'warn') => { console[level](`Skipping spawnBalloon message: \r\n\t`, note); + console.timeEnd('Spawn Time'); console.groupEnd(); }; @@ -135,6 +137,7 @@ const updateBadgeColors = () => { console.log(' - Successfully sent spawn balloon script to tab', tab.id); } catch (e) {} lastSpawn = now; + console.timeEnd('Spawn Time'); console.groupEnd(); }; From 76da8c6fe7d672c23d7beff6b5bdd06793b0362b Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Tue, 28 May 2024 22:49:05 +0200 Subject: [PATCH 04/40] Update webpack.config.js to include npm package version env variable --- webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 4d87e8b5..49299f54 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -73,7 +73,7 @@ module.exports = { ], }, plugins: [ - new EnvironmentPlugin(['REMOTE']), + new EnvironmentPlugin(['REMOTE', 'npm_package_version']), new HtmlWebpackPlugin({ template: './src/popup/index.html', // Specify the path to your HTML template filename: './popup.html', // Specify the output filename From 02b4bfd62acccd6fde5b9a2e3e51df1d0f62ef2a Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Tue, 28 May 2024 23:29:41 +0200 Subject: [PATCH 05/40] Add logging setup --- src/background/background.ts | 2 ++ src/utils.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/background/background.ts b/src/background/background.ts index c9e68847..a1d88bc0 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -9,6 +9,7 @@ import { getBrowser, isRunningInBackground, sendMessage, + setupLogging, } from '@utils'; const setBadgeNumber = (count: number) => { @@ -36,6 +37,7 @@ const updateBadgeColors = () => { let spawnTimeout: number | null = null; const setup = async () => { + setupLogging(); // Clear all alarms await browser.alarms.clearAll(); diff --git a/src/utils.ts b/src/utils.ts index a6773e95..12796fee 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,6 +3,7 @@ import { Message, BalloonContainerId } from '@const'; import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; import storage from '@/storage'; +import log from 'loglevel'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -129,3 +130,14 @@ export async function importStylesheet(id: string, href: string) { document.head.appendChild(style); } } + +export function setupLogging() { + if (process.env.NODE_ENV === 'development') log.setLevel(log.levels.DEBUG); + + log.info('Pop-a-loon version:', process.env.npm_package_version); + log.debug(`Mode: ${process.env.NODE_ENV}`); + log.debug('Browser:', getBrowser()); + log.debug('Running in background:', isRunningInBackground()); + log.debug('Logging level:', log.getLevel()); + log.debug(''); +} From d5fee32570ab9a4a57140e14a4708a86fe67f809 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Tue, 28 May 2024 23:31:24 +0200 Subject: [PATCH 06/40] Add loglevel dependency version 1.9.1 --- package-lock.json | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) diff --git a/package-lock.json b/package-lock.json index 99880509..67d6f483 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "js-abbreviation-number": "^1.4.0", + "loglevel": "^1.9.1", "lucide-react": "^0.356.0", "postcss-loader": "^8.1.0", "react": "^18.2.0", @@ -6711,6 +6712,18 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/loglevel": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", diff --git a/package.json b/package.json index a81afc72..5f393663 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "js-abbreviation-number": "^1.4.0", + "loglevel": "^1.9.1", "lucide-react": "^0.356.0", "postcss-loader": "^8.1.0", "react": "^18.2.0", From 9d0c366fcd24868814b44d62b756711461a67034 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Wed, 29 May 2024 11:49:09 +0200 Subject: [PATCH 07/40] Setup logging method factory --- src/utils.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/utils.ts b/src/utils.ts index 12796fee..9a8d82e6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -134,6 +134,29 @@ export async function importStylesheet(id: string, href: string) { export function setupLogging() { if (process.env.NODE_ENV === 'development') log.setLevel(log.levels.DEBUG); + // Save the original factory method + const originalFactory = log.methodFactory; + + // Modify the method factory + log.methodFactory = (methodName, logLevel, loggerName) => { + const rawMethod = originalFactory(methodName, logLevel, loggerName); + + // Return a new method that prepends the date and colored prefix to the message + return (...message) => { + let prefix = '%c' + methodName.toUpperCase(); + const styles: Record = { + trace: 'color: #888;', + debug: 'color: #888;', + info: 'color: #4d0;', + warn: 'color: #fa0;', + error: 'color: #d00;', + }; + rawMethod(`${prefix.padStart(7)}:`, styles[methodName], ...message); + }; + }; + + log.rebuild(); + log.info('Pop-a-loon version:', process.env.npm_package_version); log.debug(`Mode: ${process.env.NODE_ENV}`); log.debug('Browser:', getBrowser()); From bb99e935575e7721a6adc649c0089dee1318310c Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Wed, 29 May 2024 22:05:13 +0200 Subject: [PATCH 08/40] Add console.time and console.group methods to loglevel --- src/index.d.ts | 12 ++++++++++++ src/utils.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/index.d.ts diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 00000000..f841b181 --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,12 @@ +import log from 'loglevel'; + +declare module 'loglevel' { + // Extend the Logger interface to include new methods + export interface RootLogger { + time: (level: log.LogLevelNames, label: string) => void; + timeEnd: (level: log.LogLevelNames, label: string) => void; + group: (level: log.LogLevelNames, label: string) => void; + groupCollapsed: (level: log.LogLevelNames, label: string) => void; + groupEnd: (level: log.LogLevelNames) => void; + } +} diff --git a/src/utils.ts b/src/utils.ts index 9a8d82e6..b89d248c 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -155,6 +155,34 @@ export function setupLogging() { }; }; + const shouldLog = (level: log.LogLevelNames): boolean => { + return ( + log.levels[level.toUpperCase() as keyof log.LogLevel] >= log.getLevel() + ); + }; + + // Add methods for console.time and console.group + log.time = (level: log.LogLevelNames, label: string) => { + if (!shouldLog(level)) return; + console.time(label); + }; + log.timeEnd = (level: log.LogLevelNames, label: string) => { + if (!shouldLog(level)) return; + console.timeEnd(label); + }; + log.group = (level: log.LogLevelNames, label: string) => { + if (!shouldLog(level)) return; + console.group(label); + }; + log.groupCollapsed = (level: log.LogLevelNames, label: string) => { + if (!shouldLog(level)) return; + console.groupCollapsed(label); + }; + log.groupEnd = (level: log.LogLevelNames) => { + if (!shouldLog(level)) return; + console.groupEnd(); + }; + log.rebuild(); log.info('Pop-a-loon version:', process.env.npm_package_version); From e4f7e0c2062ccf323e47c5d32f891b04ace53887 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Wed, 29 May 2024 22:06:01 +0200 Subject: [PATCH 09/40] Use loglevel instead of console for logging #200 --- src/background/background.ts | 40 ++++++++++---------- src/popup/components/forms/LocalSettings.tsx | 15 +++----- src/remote.ts | 7 ++-- src/utils.ts | 2 +- 4 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index a1d88bc0..096264ab 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -11,6 +11,7 @@ import { sendMessage, setupLogging, } from '@utils'; +import log from 'loglevel'; const setBadgeNumber = (count: number) => { browser.action.setBadgeText({ @@ -43,13 +44,13 @@ const updateBadgeColors = () => { //! Fix for #145 try { - console.log('Checking for depricated balloonCount'); + log.debug('Checking for depricated balloonCount'); await storage.remove('balloonCount' as any); } catch (e) {} const remoteAvailable = await remote.isAvailable(); if (!remoteAvailable) { - console.log('Remote is not available, retrying in 1 minute'); + log.warn('Remote is not available, retrying in 1 minute'); await browser.alarms.create('restart', { when: Date.now() + 60000 }); return; } @@ -86,41 +87,42 @@ const updateBadgeColors = () => { }; const spawnBalloon = async () => { - console.groupCollapsed( + log.groupCollapsed( + 'info', `(${new Date().toLocaleTimeString()}) Spawning Balloon...` ); - console.time('Spawn Time'); + log.time('info', 'Spawn Time'); const now = Date.now(); const minSpawnInterval = (await storage.get('config')).spawnInterval.min; - const skipSpawnMessage = (note: any, level: 'log' | 'warn' = 'warn') => { - console[level](`Skipping spawnBalloon message: \r\n\t`, note); - console.timeEnd('Spawn Time'); - console.groupEnd(); + const skipSpawnMessage = (note: any, level: log.LogLevelNames = 'warn') => { + log[level](`Skipping spawnBalloon message: \r\n\t`, note); + log.timeEnd('info', 'Spawn Time'); + log.groupEnd('info'); }; // Check if there is a spawn timeout if (spawnTimeout !== null && Date.now() < spawnTimeout) return skipSpawnMessage('balloon spawn in timeout'); - console.log(' - No spawn timeout'); + log.debug(' - No spawn timeout'); // Check if the last spawn was too recent if (lastSpawn && now - lastSpawn < minSpawnInterval) { spawnTimeout = now + rapidSpawnPenalty; return skipSpawnMessage('Spawned too recently, setting timeout'); } - console.log(' - Last spawn was not too recent'); + log.debug(' - Last spawn was not too recent'); // Check if the browser is idle const state = await browser.idle.queryState(5 * 60); - if (state !== 'active') return skipSpawnMessage('Browser is idle', 'log'); - console.log(' - Browser is not idle'); + if (state !== 'active') return skipSpawnMessage('Browser is idle', 'info'); + log.debug(' - Browser is not idle'); // Check if no spawn alarms are already set const alarms = await browser.alarms.getAll(); if (alarms.some((alarm) => alarm.name === 'spawnBalloon')) return skipSpawnMessage('Spawn alarm already set'); - console.log(' - No spawn alarm already set'); + log.debug(' - No spawn alarm already set'); // Get all active tabs const tabs = await browser.tabs.query({ active: true }); @@ -128,7 +130,7 @@ const updateBadgeColors = () => { const num = Math.round(random(0, tabs.length - 1)); const tab = tabs[num]; if (!tab.id) return skipSpawnMessage('No tab id', 'warn'); - console.log(' - Selected tab', tab.id); + log.debug(' - Selected tab', tab.id); try { // Execute content script on tab @@ -136,11 +138,11 @@ const updateBadgeColors = () => { files: ['spawn-balloon.js'], target: { tabId: tab.id }, }); - console.log(' - Successfully sent spawn balloon script to tab', tab.id); + log.info(' - Successfully sent spawn balloon script to tab', tab.id); } catch (e) {} lastSpawn = now; - console.timeEnd('Spawn Time'); - console.groupEnd(); + log.timeEnd('info', 'Spawn Time'); + log.groupEnd('info'); }; const createSpawnAlarm = async (name: AlarmName) => { @@ -161,8 +163,8 @@ const updateBadgeColors = () => { await setup(); } catch (e) { - console.error(e); - console.log('Restarting in 1 minute'); + log.error(e); + log.info('Restarting in 1 minute'); browser.alarms.create('restart', { when: Date.now() + 60000 }); } }; diff --git a/src/popup/components/forms/LocalSettings.tsx b/src/popup/components/forms/LocalSettings.tsx index 362dd6e6..e66ff80c 100644 --- a/src/popup/components/forms/LocalSettings.tsx +++ b/src/popup/components/forms/LocalSettings.tsx @@ -15,6 +15,7 @@ import { Slider } from '@components/ui/slider'; import InfoIcon from '@components/InfoIcon'; import { Default as DefaultBalloon } from '@/balloons'; import storage from '@/storage'; +import log from 'loglevel'; const MIN_POP_VOLUME = 0; const VOLUME_STEP = 20; @@ -50,10 +51,7 @@ export default () => { }); setPopVolume(popVolume); - console.log( - 'Pop volume changed to', - (await storage.get('config')).popVolume - ); + log.debug('Pop volume changed to', (await storage.get('config')).popVolume); // Play the pop sound popSound.volume = popVolume / 100; @@ -69,20 +67,17 @@ export default () => { }); setSpawnRate(spawnRate); - console.log( - 'Spawn rate changed to', - (await storage.get('config')).spawnRate - ); + log.debug('Spawn rate changed to', (await storage.get('config')).spawnRate); }; const onGrantOriginPermissionClick = async () => { const host_permissions = await browser.runtime.getManifest().host_permissions; - if (!host_permissions) return console.error('No host_permissions found'); + if (!host_permissions) return log.error('No host_permissions found'); const permissions = await browser.permissions.request({ origins: host_permissions, }); - console.log('Permissions granted for', permissions); + log.debug('Permissions granted for', permissions); setPermissions(await browser.permissions.getAll()); }; diff --git a/src/remote.ts b/src/remote.ts index 3fc7df38..6e198621 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -1,5 +1,6 @@ import { RemoteResponse, devRemoteResponse, Prettify, Endpoint } from '@/const'; import storage from '@/storage'; +import log from 'loglevel'; interface RequestParams { [key: string]: string | number | undefined; @@ -52,7 +53,7 @@ class BackendAPI { }, }); if (!response.ok) { - console.error(response, await response.json()); + log.error(response, await response.json()); throw new Error(`Failed to fetch ${url.toString()}`); } return response.json() as Promise; @@ -75,8 +76,8 @@ class BackendAPI { return this.available; } catch (e) { this.available = false; - console.warn('Remote is not available'); - console.log(BackendAPI.BASE_URL, e); + log.warn('Remote is not available'); + log.debug(BackendAPI.BASE_URL, e); return false; } } diff --git a/src/utils.ts b/src/utils.ts index b89d248c..dffacf80 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -32,7 +32,7 @@ export async function sendMessage(message: Message) { try { const res = await browser.runtime.sendMessage(message); if (browser.runtime.lastError) { - console.log( + log.error( 'Error sending message:', message, '\nError message:', From 29a526da240096bfce80d0bc29736151b0c7180e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Wed, 29 May 2024 22:52:28 +0200 Subject: [PATCH 10/40] Add softwarn and softerror log methods --- src/index.d.ts | 3 ++- src/utils.ts | 35 +++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/index.d.ts b/src/index.d.ts index f841b181..21aa8c67 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,12 +1,13 @@ import log from 'loglevel'; declare module 'loglevel' { - // Extend the Logger interface to include new methods export interface RootLogger { time: (level: log.LogLevelNames, label: string) => void; timeEnd: (level: log.LogLevelNames, label: string) => void; group: (level: log.LogLevelNames, label: string) => void; groupCollapsed: (level: log.LogLevelNames, label: string) => void; groupEnd: (level: log.LogLevelNames) => void; + softwarn: (message?: any, ...optionalParams: any[]) => void; + softerror: (message?: any, ...optionalParams: any[]) => void; } } diff --git a/src/utils.ts b/src/utils.ts index dffacf80..9ff12359 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -138,20 +138,37 @@ export function setupLogging() { const originalFactory = log.methodFactory; // Modify the method factory - log.methodFactory = (methodName, logLevel, loggerName) => { - const rawMethod = originalFactory(methodName, logLevel, loggerName); + log.methodFactory = ( + methodName: log.LogLevelNames | 'softwarn' | 'softerror', + logLevel, + loggerName + ) => { + const rawMethod = originalFactory( + (() => { + if (methodName == 'softwarn') return 'info'; + if (methodName == 'softerror') return 'info'; + return methodName; + })(), + logLevel, + loggerName + ); - // Return a new method that prepends the date and colored prefix to the message return (...message) => { - let prefix = '%c' + methodName.toUpperCase(); - const styles: Record = { + let lvl = methodName; + if (message.length > 0 && message[0] == 'softwarn') lvl = 'warn'; + if (message.length > 0 && message[0] == 'softerror') lvl = 'error'; + + let prefix = '%c' + lvl.toUpperCase(); + const styles: Record = { trace: 'color: #888;', debug: 'color: #888;', info: 'color: #4d0;', warn: 'color: #fa0;', + softwarn: 'color: #fa0;', error: 'color: #d00;', + softerror: 'color: #d00;', }; - rawMethod(`${prefix.padStart(7)}:`, styles[methodName], ...message); + rawMethod(`${prefix.padStart(7)}:`, styles[lvl], ...message); }; }; @@ -182,6 +199,12 @@ export function setupLogging() { if (!shouldLog(level)) return; console.groupEnd(); }; + log.softwarn = (message?: any, ...optionalParams: any[]) => { + log.info('softwarn', message, ...optionalParams); + }; + log.softerror = (message?: any, ...optionalParams: any[]) => { + log.info('softerror', message, ...optionalParams); + }; log.rebuild(); From 6d824ca3d9a467de6d799e40ec7e8b9b6b91f5b6 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:12:55 +0200 Subject: [PATCH 11/40] Move types to types folder --- src/{ => types}/index.d.ts | 2 ++ 1 file changed, 2 insertions(+) rename src/{ => types}/index.d.ts (87%) diff --git a/src/index.d.ts b/src/types/index.d.ts similarity index 87% rename from src/index.d.ts rename to src/types/index.d.ts index 21aa8c67..8d9af455 100644 --- a/src/index.d.ts +++ b/src/types/index.d.ts @@ -11,3 +11,5 @@ declare module 'loglevel' { softerror: (message?: any, ...optionalParams: any[]) => void; } } + +export type LogLevelNames = log.LogLevelNames | 'softwarn' | 'softerror'; From 109814e238ae74fd515c8f2ad627dca516b4898e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:13:44 +0200 Subject: [PATCH 12/40] Update logging setup and dependencies --- src/background/background.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index 096264ab..ae29aa86 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -1,5 +1,7 @@ import browser from 'webextension-polyfill'; import { abbreviateNumber } from 'js-abbreviation-number'; +import log from 'loglevel'; +import { type LogLevelNames } from '@/types'; import { AlarmName, Message, initalConfig } from '@const'; import storage from '@/storage'; import remote from '@/remote'; @@ -11,7 +13,6 @@ import { sendMessage, setupLogging, } from '@utils'; -import log from 'loglevel'; const setBadgeNumber = (count: number) => { browser.action.setBadgeText({ @@ -84,6 +85,8 @@ const updateBadgeColors = () => { // Set badge number and colors setBadgeNumber(user.count || 0); updateBadgeColors(); + + log.debug('Setup complete'); }; const spawnBalloon = async () => { @@ -95,7 +98,7 @@ const updateBadgeColors = () => { const now = Date.now(); const minSpawnInterval = (await storage.get('config')).spawnInterval.min; - const skipSpawnMessage = (note: any, level: log.LogLevelNames = 'warn') => { + const skipSpawnMessage = (note: any, level: LogLevelNames = 'softwarn') => { log[level](`Skipping spawnBalloon message: \r\n\t`, note); log.timeEnd('info', 'Spawn Time'); log.groupEnd('info'); @@ -115,7 +118,7 @@ const updateBadgeColors = () => { // Check if the browser is idle const state = await browser.idle.queryState(5 * 60); - if (state !== 'active') return skipSpawnMessage('Browser is idle', 'info'); + if (state !== 'active') return skipSpawnMessage('Browser is idle'); log.debug(' - Browser is not idle'); // Check if no spawn alarms are already set From 1363241009c4a62bcccb8e2986a2ee8e17d4a48e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:25:38 +0200 Subject: [PATCH 13/40] Log failed execScript in spawnballoon --- src/background/background.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/background/background.ts b/src/background/background.ts index ae29aa86..1dfccaab 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -142,7 +142,9 @@ const updateBadgeColors = () => { target: { tabId: tab.id }, }); log.info(' - Successfully sent spawn balloon script to tab', tab.id); - } catch (e) {} + } catch (e) { + log.softerror(' - Error sending spawn balloon script to tab', tab.id, e); + } lastSpawn = now; log.timeEnd('info', 'Spawn Time'); log.groupEnd('info'); From 20e4fa7f0d59cbd05a8c407dbd5624cd3ced22d4 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:40:02 +0200 Subject: [PATCH 14/40] Add console warning message to tell users not to copy paste --- src/background/background.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/background/background.ts b/src/background/background.ts index 1dfccaab..7667f709 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -14,6 +14,11 @@ import { setupLogging, } from '@utils'; +console.log( + "%cIf someone told you to copy/paste something here you have an 11/10 chance you're being scammed.", + 'font-size:18px; color: red; font-weight: bold; padding: 25px 10px;' +); + const setBadgeNumber = (count: number) => { browser.action.setBadgeText({ text: abbreviateNumber(count), From 2094f78cd335d4ad98c80a62271955a4b4e9bf36 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:46:34 +0200 Subject: [PATCH 15/40] Add extra log statements in background --- src/background/background.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/background/background.ts b/src/background/background.ts index 7667f709..d7ee3be9 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -168,6 +168,7 @@ const updateBadgeColors = () => { try { // If extension is being run in firefox, set the browserAction popup if (getBrowser() === 'Firefox' && !('action' in browser)) { + log.debug('Setting browser action to browser.browserAction'); (browser as any).action = (browser as any).browserAction; } @@ -180,6 +181,7 @@ const updateBadgeColors = () => { }; browser.alarms.onAlarm.addListener(async (alarm) => { + log.debug('Alarm triggered', alarm.name); switch (alarm.name as AlarmName) { case 'spawnBalloon': // Spawn a balloon @@ -199,6 +201,7 @@ const updateBadgeColors = () => { sender, sendResponse ) { + log.debug('Message received:', message); switch (message.action) { case 'updateCounter': setBadgeNumber(message.balloonCount); From 8ad5c20f94ba0eb063e67078e5469144ad831fc1 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:47:01 +0200 Subject: [PATCH 16/40] Update logging setup --- src/background/background.ts | 8 ++++++++ src/utils.ts | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index d7ee3be9..281525eb 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -45,6 +45,14 @@ const updateBadgeColors = () => { const setup = async () => { setupLogging(); + + log.info('Pop-a-loon version:', process.env.npm_package_version); + log.debug(`Mode: ${process.env.NODE_ENV}`); + log.debug('Browser:', getBrowser()); + log.debug('Running in background:', isRunningInBackground()); + log.debug('Logging level:', log.getLevel()); + log.debug(''); + // Clear all alarms await browser.alarms.clearAll(); diff --git a/src/utils.ts b/src/utils.ts index 9ff12359..bc4e7235 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -207,11 +207,4 @@ export function setupLogging() { }; log.rebuild(); - - log.info('Pop-a-loon version:', process.env.npm_package_version); - log.debug(`Mode: ${process.env.NODE_ENV}`); - log.debug('Browser:', getBrowser()); - log.debug('Running in background:', isRunningInBackground()); - log.debug('Logging level:', log.getLevel()); - log.debug(''); } From 118ecfb6defefa1d73ffb68ae9e03c60c312c542 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 17:54:16 +0200 Subject: [PATCH 17/40] Add logging in spawn-balloon.ts --- src/content/spawn-balloon.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/content/spawn-balloon.ts b/src/content/spawn-balloon.ts index c44f79e5..cc563f23 100644 --- a/src/content/spawn-balloon.ts +++ b/src/content/spawn-balloon.ts @@ -1,10 +1,19 @@ import browser from 'webextension-polyfill'; import * as balloons from '@/balloons'; -import { getBalloonContainer, importStylesheet, weightedRandom } from '@/utils'; +import { + getBalloonContainer, + importStylesheet, + setupLogging, + weightedRandom, +} from '@/utils'; +import log from 'loglevel'; (() => { // Prevent running in popup if (document.body.id === 'pop-a-loon') return; + setupLogging(); + log.groupCollapsed('debug', 'Pop-a-loon: Spawning balloon'); + log.time('debug', 'Balloon spawn time'); importStylesheet( 'balloon-styles', @@ -27,4 +36,9 @@ import { getBalloonContainer, importStylesheet, weightedRandom } from '@/utils'; const balloon = new Balloon(); balloon.rise(); + + log.debug('Balloon spawned:', balloon.name); + + log.timeEnd('debug', 'Balloon spawn time'); + log.groupEnd('debug'); })(); From 7f86f09cdad0ccb5a162fc6a0af6b796e0088b65 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 20:44:15 +0200 Subject: [PATCH 18/40] Update storage manager --- src/storage.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/storage.ts b/src/storage.ts index b2a537d1..b5a44a9d 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -1,23 +1,28 @@ import browser from 'webextension-polyfill'; -import { storageKey, StorageStructure } from '@const'; +import { SyncStorageStructure } from '@const'; -class StorageManager { - private _storage: browser.Storage.StorageAreaSync; +class StorageManager> { + private _storage: browser.Storage.StorageArea; - constructor() { - this._storage = browser.storage.sync; + constructor(storage: browser.Storage.StorageArea) { + this._storage = storage; } - async get(key: K): Promise { + async get( + key: K + ): Promise { const result = await this._storage.get(key); return result[key]; } - async set(key: K, value: StorageStructure[K]) { + async set( + key: K, + value: StorageStructure[K] + ) { return await this._storage.set({ [key]: value }); } - async remove(key: K) { + async remove(key: K) { return await this._storage.remove(key); } @@ -26,4 +31,7 @@ class StorageManager { } } -export default new StorageManager(); +const storage = { + sync: new StorageManager(browser.storage.sync), +}; +export default storage; From 402f396baf5dd2ce6737299d1c45cbd08aecfb07 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 20:44:48 +0200 Subject: [PATCH 19/40] Update storagestructure type name --- src/const.ts | 4 ++-- tests/__mocks__/webextension-polyfill.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/const.ts b/src/const.ts index 189535ae..316a443a 100644 --- a/src/const.ts +++ b/src/const.ts @@ -81,13 +81,13 @@ export type Endpoint = type Config = Prettify; -export type StorageStructure = { +export type SyncStorageStructure = { config: Config; token: string; user: User; }; -export type storageKey = keyof StorageStructure; +export type SyncStorageKey = keyof SyncStorageStructure; // // * Chrome message types diff --git a/tests/__mocks__/webextension-polyfill.ts b/tests/__mocks__/webextension-polyfill.ts index 24dfbf9d..23623e39 100644 --- a/tests/__mocks__/webextension-polyfill.ts +++ b/tests/__mocks__/webextension-polyfill.ts @@ -1,6 +1,6 @@ -import { StorageStructure, initalConfig, storageKey } from '@const'; +import { initalConfig, SyncStorageKey, SyncStorageStructure } from '@const'; -const defaultStorage: StorageStructure = { +const defaultStorage: SyncStorageStructure = { config: initalConfig, token: '', user: { @@ -13,7 +13,7 @@ const defaultStorage: StorageStructure = { }, }; -let mockStorage: StorageStructure = defaultStorage; +let mockStorage: SyncStorageStructure = defaultStorage; export default { runtime: { @@ -24,13 +24,13 @@ export default { }, storage: { sync: { - get: jest.fn(async (key: storageKey) => { + get: jest.fn(async (key: SyncStorageKey) => { return mockStorage[key]; }), set: jest.fn(async (data) => { mockStorage = { ...mockStorage, ...data }; }), - remove: jest.fn(async (key: storageKey) => { + remove: jest.fn(async (key: SyncStorageKey) => { delete mockStorage[key]; }), clear: jest.fn(async () => { From 1930d15af801c9df0e01cb0fbee51f3b5241ef7c Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 20:45:18 +0200 Subject: [PATCH 20/40] Update all storage instances to use storage.sync --- src/background/background.ts | 21 ++++++++++---------- src/balloon.ts | 2 +- src/popup/App.tsx | 2 +- src/popup/components/forms/DeleteUser.tsx | 4 ++-- src/popup/components/forms/LocalSettings.tsx | 20 ++++++++++++------- src/popup/components/forms/UpdateUser.tsx | 4 ++-- src/remote.ts | 6 +++--- src/utils.ts | 2 +- 8 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index 281525eb..5ca3ce1a 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -27,7 +27,7 @@ const setBadgeNumber = (count: number) => { const updateBadgeColors = () => { (async () => { - const config = await storage.get('config'); + const config = await storage.sync.get('config'); browser.action.setBadgeBackgroundColor({ color: config.badge.backgroundColor, }); @@ -59,7 +59,7 @@ const updateBadgeColors = () => { //! Fix for #145 try { log.debug('Checking for depricated balloonCount'); - await storage.remove('balloonCount' as any); + await storage.sync.remove('balloonCount' as any); } catch (e) {} const remoteAvailable = await remote.isAvailable(); @@ -70,23 +70,23 @@ const updateBadgeColors = () => { } // Get the user from the local storage - let localUser = await storage.get('user'); + let localUser = await storage.sync.get('user'); // If the user is not in the local storage, get a new user from the remote if (!localUser) { const usr = await remote.NewUser('Anonymous'); - await storage.set('token', usr.token); + await storage.sync.set('token', usr.token); localUser = usr; } // Get the user from the remote and save it to the local storage const user = await remote.getUser(localUser.id); - await storage.set('user', user); + await storage.sync.set('user', user); // Get the config from the remote const remoteConfig = await remote.getConfiguration(); // Get the config from the local storage - const config = (await storage.get('config')) || initalConfig; + const config = (await storage.sync.get('config')) || initalConfig; // Merge the local config with the remote config - await storage.set('config', { + await storage.sync.set('config', { ...initalConfig, ...config, // config overrides the initial config ...remoteConfig, // remoteConfig overrides the config @@ -110,7 +110,8 @@ const updateBadgeColors = () => { log.time('info', 'Spawn Time'); const now = Date.now(); - const minSpawnInterval = (await storage.get('config')).spawnInterval.min; + const minSpawnInterval = (await storage.sync.get('config')).spawnInterval + .min; const skipSpawnMessage = (note: any, level: LogLevelNames = 'softwarn') => { log[level](`Skipping spawnBalloon message: \r\n\t`, note); log.timeEnd('info', 'Spawn Time'); @@ -218,8 +219,8 @@ const updateBadgeColors = () => { case 'incrementCount': // Increment the count and save it to the local storage const newCount = await remote.incrementCount(); - storage.set('user', { - ...(await storage.get('user')), + storage.sync.set('user', { + ...(await storage.sync.get('user')), count: newCount.count, }); diff --git a/src/balloon.ts b/src/balloon.ts index d14b61a0..b6ce2f40 100644 --- a/src/balloon.ts +++ b/src/balloon.ts @@ -142,7 +142,7 @@ export default abstract class Balloon { sendMessage({ action: 'incrementCount' }); // Set volume - this.popSound.volume = (await storage.get('config')).popVolume / 100; + this.popSound.volume = (await storage.sync.get('config')).popVolume / 100; // Play the pop sound this.popSound.play().catch((e) => { this.popSound.src = defaultBalloonResourceLocation + 'pop.mp3'; diff --git a/src/popup/App.tsx b/src/popup/App.tsx index 4cea4354..cd1f3654 100644 --- a/src/popup/App.tsx +++ b/src/popup/App.tsx @@ -8,7 +8,7 @@ const App: React.FC = () => { const [balloonCount, setBalloonCount] = useState(0); const fetchBalloonCount = async () => { - const count = (await storage.get('user'))?.count; + const count = (await storage.sync.get('user'))?.count; setBalloonCount(count || 0); }; diff --git a/src/popup/components/forms/DeleteUser.tsx b/src/popup/components/forms/DeleteUser.tsx index 9f719a27..15614c4e 100644 --- a/src/popup/components/forms/DeleteUser.tsx +++ b/src/popup/components/forms/DeleteUser.tsx @@ -33,14 +33,14 @@ export default () => { }); const deleteFormOnSubmit = async () => { - const token = await storage.get('token'); + const token = await storage.sync.get('token'); await remote.deleteUser(token); browser.runtime.reload(); }; useEffect(() => { const loadUser = async () => { - const storedUser = await storage.get('user'); + const storedUser = await storage.sync.get('user'); setUser(storedUser); }; diff --git a/src/popup/components/forms/LocalSettings.tsx b/src/popup/components/forms/LocalSettings.tsx index e66ff80c..9aea2216 100644 --- a/src/popup/components/forms/LocalSettings.tsx +++ b/src/popup/components/forms/LocalSettings.tsx @@ -44,14 +44,17 @@ export default () => { const onPopVolumeChange = async (popVolume: number) => { // Save volume to storage - const config = await storage.get('config'); - await storage.set('config', { + const config = await storage.sync.get('config'); + await storage.sync.set('config', { ...config, popVolume, }); setPopVolume(popVolume); - log.debug('Pop volume changed to', (await storage.get('config')).popVolume); + log.debug( + 'Pop volume changed to', + (await storage.sync.get('config')).popVolume + ); // Play the pop sound popSound.volume = popVolume / 100; @@ -60,14 +63,17 @@ export default () => { const onSpawnRateChange = async (spawnRate: number) => { // Save volume to storage - const config = await storage.get('config'); - await storage.set('config', { + const config = await storage.sync.get('config'); + await storage.sync.set('config', { ...config, spawnRate, }); setSpawnRate(spawnRate); - log.debug('Spawn rate changed to', (await storage.get('config')).spawnRate); + log.debug( + 'Spawn rate changed to', + (await storage.sync.get('config')).spawnRate + ); }; const onGrantOriginPermissionClick = async () => { @@ -84,7 +90,7 @@ export default () => { useEffect(() => { const loadVolume = async () => { - const config = await storage.get('config'); + const config = await storage.sync.get('config'); // Load volume from storage setPopVolume(config.popVolume); setSpawnRate(config.spawnRate); diff --git a/src/popup/components/forms/UpdateUser.tsx b/src/popup/components/forms/UpdateUser.tsx index 8f8a8884..06a6fd74 100644 --- a/src/popup/components/forms/UpdateUser.tsx +++ b/src/popup/components/forms/UpdateUser.tsx @@ -45,7 +45,7 @@ export default () => { useEffect(() => { const loadUser = async () => { - const storedUser = await storage.get('user'); + const storedUser = await storage.sync.get('user'); setUser(storedUser); form.setValue('username', storedUser.username); form.setValue('email', storedUser.email || ''); @@ -58,7 +58,7 @@ export default () => { if (username === user?.username && email === user?.email) return; const newUser = await remote.putUser({ username, email }); setUser(newUser); - await storage.set('user', newUser); + await storage.sync.set('user', newUser); }; return ( diff --git a/src/remote.ts b/src/remote.ts index 6e198621..0f024b8a 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -49,7 +49,7 @@ class BackendAPI { const response = await fetch(url.toString(), { method, headers: { - authorization: (await storage.get('token')) || '', + authorization: (await storage.sync.get('token')) || '', }, }); if (!response.ok) { @@ -114,13 +114,13 @@ class BackendAPI { } public async deleteUser(token: string) { - if ((await storage.get('token')) !== token) + if ((await storage.sync.get('token')) !== token) throw new Error('Cannot delete user without token'); const response = await this.request( 'DELETE', `/user` ); - await storage.clear(); + await storage.sync.clear(); return response; } diff --git a/src/utils.ts b/src/utils.ts index bc4e7235..86439ee2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -91,7 +91,7 @@ export function weightedRandom( } export async function calculateBalloonSpawnDelay() { - const config = await storage.get('config'); + const config = await storage.sync.get('config'); // Generate a random delay between the min and max spawn interval const randomDelay = random( config.spawnInterval.min, From 0cc357634091ae8b997197c0c8596317d9d0eafc Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 20:58:04 +0200 Subject: [PATCH 21/40] Add session storage --- src/storage.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/storage.ts b/src/storage.ts index b5a44a9d..ce8478ea 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -1,5 +1,8 @@ import browser from 'webextension-polyfill'; -import { SyncStorageStructure } from '@const'; +import { + type SessionStorageStructure, + type SyncStorageStructure, +} from '@const'; class StorageManager> { private _storage: browser.Storage.StorageArea; @@ -33,5 +36,6 @@ class StorageManager> { const storage = { sync: new StorageManager(browser.storage.sync), + session: new StorageManager(browser.storage.session), }; export default storage; From f3b1fad0d49365b00c90cdbef2804474fc2f4dff Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 21:01:32 +0200 Subject: [PATCH 22/40] Add session storage types --- src/const.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/const.ts b/src/const.ts index 316a443a..d803ce28 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1,3 +1,5 @@ +import log from 'loglevel'; + // // * Config types // @@ -86,9 +88,13 @@ export type SyncStorageStructure = { token: string; user: User; }; - export type SyncStorageKey = keyof SyncStorageStructure; +export type SessionStorageStructure = { + loglevel?: log.LogLevelNumbers; +}; +export type SessionStorageKey = keyof SessionStorageStructure; + // // * Chrome message types // From e9fd32532f53815afa83c8758161dacf717ed4a5 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 21:03:12 +0200 Subject: [PATCH 23/40] Store log level --- src/background/background.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/background/background.ts b/src/background/background.ts index 5ca3ce1a..f7301610 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -45,6 +45,7 @@ const updateBadgeColors = () => { const setup = async () => { setupLogging(); + await storage.session.set('loglevel', log.getLevel()); log.info('Pop-a-loon version:', process.env.npm_package_version); log.debug(`Mode: ${process.env.NODE_ENV}`); From 7e11570790da073b761989f9958d0300410cbc08 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 22:13:10 +0200 Subject: [PATCH 24/40] Add shadcn checkbox component --- package-lock.json | 31 ++++++++++++++++++++++++++++ package.json | 1 + src/popup/components/ui/checkbox.tsx | 28 +++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/popup/components/ui/checkbox.tsx diff --git a/package-lock.json b/package-lock.json index 67d6f483..2466daa3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@hookform/resolvers": "^3.3.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-hover-card": "^1.0.7", "@radix-ui/react-label": "^2.0.2", @@ -1369,6 +1370,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", + "integrity": "sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", diff --git a/package.json b/package.json index 5f393663..c97f8da0 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "@hookform/resolvers": "^3.3.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-hover-card": "^1.0.7", "@radix-ui/react-label": "^2.0.2", diff --git a/src/popup/components/ui/checkbox.tsx b/src/popup/components/ui/checkbox.tsx new file mode 100644 index 00000000..8fda91ba --- /dev/null +++ b/src/popup/components/ui/checkbox.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; +import { Check } from 'lucide-react'; + +import { cn } from '@utils'; + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; + +export { Checkbox }; From f446bf13edc17fe20a027861c8fba79ab4c751da Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 22:13:57 +0200 Subject: [PATCH 25/40] Listen for update loglevel messages in background --- src/background/background.ts | 3 +++ src/const.ts | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/background/background.ts b/src/background/background.ts index f7301610..cb309329 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -234,6 +234,9 @@ const updateBadgeColors = () => { // Call the listener again to update the badge number messageListener(msg, sender, sendResponse); break; + case 'setLogLevel': + log.setLevel(message.level); + break; } }); diff --git a/src/const.ts b/src/const.ts index d803ce28..5a924157 100644 --- a/src/const.ts +++ b/src/const.ts @@ -112,10 +112,16 @@ type SpawnBalloonMessage = { action: 'spawnBalloon'; }; +type SetLogLevelMessage = { + action: 'setLogLevel'; + level: log.LogLevelNumbers; +}; + export type Message = | UpdateCounterMessage | IncrementCount - | SpawnBalloonMessage; + | SpawnBalloonMessage + | SetLogLevelMessage; // // * Alarms From 73595d4b85607ed4dda5d3e51bb08f8fcf1dcf82 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Thu, 30 May 2024 22:14:13 +0200 Subject: [PATCH 26/40] Add toggle for debug logging in settings --- src/popup/Settings.tsx | 5 ++ src/popup/components/forms/Developer.tsx | 77 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/popup/components/forms/Developer.tsx diff --git a/src/popup/Settings.tsx b/src/popup/Settings.tsx index 714854f6..b41270bf 100644 --- a/src/popup/Settings.tsx +++ b/src/popup/Settings.tsx @@ -15,6 +15,7 @@ import Main from '@components/Main'; import LocalSettings from '@components/forms/LocalSettings'; import UpdateUser from '@components/forms/UpdateUser'; import DeleteUser from '@components/forms/DeleteUser'; +import Developer from './components/forms/Developer'; export default () => { return ( @@ -56,6 +57,10 @@ export default () => { + +
+ +
diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx new file mode 100644 index 00000000..816d915b --- /dev/null +++ b/src/popup/components/forms/Developer.tsx @@ -0,0 +1,77 @@ +import React, { useEffect, useState } from 'react'; +import log from 'loglevel'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@components/ui/form'; +import { Checkbox } from '@components/ui/checkbox'; +import { sendMessage } from '@/utils'; + +const formSchema = z.object({ + loglevel: z.number().int().min(log.levels.TRACE).max(log.levels.SILENT), +}); + +export default () => { + const [loglevel, setLoglevel] = useState(log.getLevel()); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + loglevel: log.getLevel(), + }, + }); + + const toggleDebugLogging = async () => { + const level = + loglevel === log.levels.DEBUG ? log.levels.INFO : log.levels.DEBUG; + setLoglevel(level); + log.setLevel(level); + console.log('Toggling debug logging', log.getLevel()); + await sendMessage({ action: 'setLogLevel', level }); + }; + + useEffect(() => { + const loadLoglevel = async () => { + const level = await log.getLevel(); + setLoglevel(level); + form.setValue('loglevel', level); + }; + loadLoglevel(); + }, []); + + return ( +
+ + ( + + + Debug logging + + + + + Enable debug logging (session). + + + )} + /> + + + ); +}; From 6b65c8e0a3c09a6258317d4e4c774520f22db35e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:06:08 +0200 Subject: [PATCH 27/40] Use local storage to store log level --- src/background/background.ts | 3 ++- src/const.ts | 4 ++-- src/content/spawn-balloon.ts | 4 +++- src/popup/components/forms/Developer.tsx | 11 ++++++----- src/storage.ts | 7 ++----- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index cb309329..998e93aa 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -45,7 +45,7 @@ const updateBadgeColors = () => { const setup = async () => { setupLogging(); - await storage.session.set('loglevel', log.getLevel()); + await storage.local.set('loglevel', log.getLevel()); log.info('Pop-a-loon version:', process.env.npm_package_version); log.debug(`Mode: ${process.env.NODE_ENV}`); @@ -236,6 +236,7 @@ const updateBadgeColors = () => { break; case 'setLogLevel': log.setLevel(message.level); + await storage.local.set('loglevel', message.level); break; } }); diff --git a/src/const.ts b/src/const.ts index 5a924157..0102a457 100644 --- a/src/const.ts +++ b/src/const.ts @@ -90,10 +90,10 @@ export type SyncStorageStructure = { }; export type SyncStorageKey = keyof SyncStorageStructure; -export type SessionStorageStructure = { +export type LocalStorageStructure = { loglevel?: log.LogLevelNumbers; }; -export type SessionStorageKey = keyof SessionStorageStructure; +export type LocalStorageKey = keyof LocalStorageStructure; // // * Chrome message types diff --git a/src/content/spawn-balloon.ts b/src/content/spawn-balloon.ts index cc563f23..ff231ffd 100644 --- a/src/content/spawn-balloon.ts +++ b/src/content/spawn-balloon.ts @@ -7,11 +7,13 @@ import { weightedRandom, } from '@/utils'; import log from 'loglevel'; +import storage from '@/storage'; -(() => { +(async () => { // Prevent running in popup if (document.body.id === 'pop-a-loon') return; setupLogging(); + log.setLevel((await storage.local.get('loglevel')) || 'info'); log.groupCollapsed('debug', 'Pop-a-loon: Spawning balloon'); log.time('debug', 'Balloon spawn time'); diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx index 816d915b..c06bfeb5 100644 --- a/src/popup/components/forms/Developer.tsx +++ b/src/popup/components/forms/Developer.tsx @@ -14,9 +14,10 @@ import { } from '@components/ui/form'; import { Checkbox } from '@components/ui/checkbox'; import { sendMessage } from '@/utils'; +import storage from '@/storage'; const formSchema = z.object({ - loglevel: z.number().int().min(log.levels.TRACE).max(log.levels.SILENT), + loglevel: z.boolean(), }); export default () => { @@ -25,7 +26,7 @@ export default () => { const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { - loglevel: log.getLevel(), + loglevel: log.getLevel() === log.levels.DEBUG, }, }); @@ -34,15 +35,14 @@ export default () => { loglevel === log.levels.DEBUG ? log.levels.INFO : log.levels.DEBUG; setLoglevel(level); log.setLevel(level); - console.log('Toggling debug logging', log.getLevel()); await sendMessage({ action: 'setLogLevel', level }); }; useEffect(() => { const loadLoglevel = async () => { - const level = await log.getLevel(); + const level = (await storage.local.get('loglevel')) || log.levels.INFO; setLoglevel(level); - form.setValue('loglevel', level); + form.setValue('loglevel', level === log.levels.DEBUG); }; loadLoglevel(); }, []); @@ -63,6 +63,7 @@ export default () => { defaultChecked={loglevel === log.levels.DEBUG} {...field} onCheckedChange={toggleDebugLogging} + value={loglevel} /> diff --git a/src/storage.ts b/src/storage.ts index ce8478ea..14583e5d 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -1,8 +1,5 @@ import browser from 'webextension-polyfill'; -import { - type SessionStorageStructure, - type SyncStorageStructure, -} from '@const'; +import { type LocalStorageStructure, type SyncStorageStructure } from '@const'; class StorageManager> { private _storage: browser.Storage.StorageArea; @@ -36,6 +33,6 @@ class StorageManager> { const storage = { sync: new StorageManager(browser.storage.sync), - session: new StorageManager(browser.storage.session), + local: new StorageManager(browser.storage.local), }; export default storage; From b0b3c911107cbed589af421dc1280d85fb9ae27d Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:07:38 +0200 Subject: [PATCH 28/40] Update debug logging form description --- src/popup/components/forms/Developer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx index c06bfeb5..b5de75bf 100644 --- a/src/popup/components/forms/Developer.tsx +++ b/src/popup/components/forms/Developer.tsx @@ -67,7 +67,7 @@ export default () => { /> - Enable debug logging (session). + Enable debug logging. )} From b6a232d02ac423bf3c72f6831871ee300dd1ce4a Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:18:45 +0200 Subject: [PATCH 29/40] Update tsconfig paths --- tsconfig.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index b6e9185e..e7dac4cb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,9 +11,7 @@ "baseUrl": "./src", "paths": { "@/*": ["./*"], - "@components/*": ["./popup/components/*"], - "@const": ["./const"], - "@utils": ["./utils"] + "@/components/*": ["./popup/components/*"] } } } From 95cd33d76a4be0fc07e5db3ad5fc326f6262675e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:20:46 +0200 Subject: [PATCH 30/40] Update module aliases in config files --- components.json | 2 +- jest.config.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/components.json b/components.json index 8306e15f..ff9c6677 100644 --- a/components.json +++ b/components.json @@ -12,6 +12,6 @@ }, "aliases": { "components": "@/popup/components", - "utils": "@utils" + "utils": "@/utils" } } diff --git a/jest.config.js b/jest.config.js index d9ed0d07..9d9e02dd 100644 --- a/jest.config.js +++ b/jest.config.js @@ -8,8 +8,6 @@ module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], moduleNameMapper: { '^@/(.*)$': '/src/$1', - '^@const': '/src/const', - '^@utils': '/src/utils', - '^@components/(.*)$': '/src/components/$1', + '^@/components/(.*)$': '/src/popup/components/$1', }, }; From 3273e3b58cdd64cf2537c8127ec61faeb04a2aad Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:21:24 +0200 Subject: [PATCH 31/40] Update import paths to new module aliases --- src/background/background.ts | 4 ++-- src/balloon.ts | 2 +- src/popup/App.tsx | 4 ++-- src/popup/General.tsx | 4 ++-- src/popup/Settings.tsx | 16 ++++++++-------- src/popup/components/Footer.tsx | 2 +- src/popup/components/InfoIcon.tsx | 2 +- src/popup/components/Leaderboard.tsx | 6 +++--- src/popup/components/Main.tsx | 2 +- src/popup/components/forms/DeleteUser.tsx | 6 +++--- src/popup/components/forms/Developer.tsx | 4 ++-- src/popup/components/forms/LocalSettings.tsx | 8 ++++---- src/popup/components/forms/UpdateUser.tsx | 6 +++--- src/popup/components/ui/alert.tsx | 2 +- src/popup/components/ui/button.tsx | 2 +- src/popup/components/ui/checkbox.tsx | 2 +- src/popup/components/ui/dialog.tsx | 2 +- src/popup/components/ui/form.tsx | 4 ++-- src/popup/components/ui/hover-card.tsx | 2 +- src/popup/components/ui/input.tsx | 2 +- src/popup/components/ui/label.tsx | 2 +- src/popup/components/ui/scroll-area.tsx | 2 +- src/popup/components/ui/separator.tsx | 2 +- src/popup/components/ui/skeleton.tsx | 2 +- src/popup/components/ui/slider.tsx | 2 +- src/popup/components/ui/table.tsx | 2 +- src/popup/index.tsx | 4 ++-- src/storage.ts | 2 +- src/utils.ts | 2 +- tests/__mocks__/webextension-polyfill.ts | 2 +- tests/balloon.test.ts | 2 +- 31 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index 998e93aa..8e258208 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -2,9 +2,9 @@ import browser from 'webextension-polyfill'; import { abbreviateNumber } from 'js-abbreviation-number'; import log from 'loglevel'; import { type LogLevelNames } from '@/types'; -import { AlarmName, Message, initalConfig } from '@const'; import storage from '@/storage'; import remote from '@/remote'; +import { AlarmName, Message, initalConfig } from '@/const'; import { calculateBalloonSpawnDelay, random, @@ -12,7 +12,7 @@ import { isRunningInBackground, sendMessage, setupLogging, -} from '@utils'; +} from '@/utils'; console.log( "%cIf someone told you to copy/paste something here you have an 11/10 chance you're being scammed.", diff --git a/src/balloon.ts b/src/balloon.ts index b6ce2f40..c81e7c44 100644 --- a/src/balloon.ts +++ b/src/balloon.ts @@ -1,6 +1,6 @@ import browser from 'webextension-polyfill'; import storage from '@/storage'; -import { getBalloonContainer, random, sendMessage } from '@utils'; +import { getBalloonContainer, random, sendMessage } from '@/utils'; export const balloonResourceLocation = browser.runtime.getURL( 'resources/balloons/' diff --git a/src/popup/App.tsx b/src/popup/App.tsx index cd1f3654..27c973f5 100644 --- a/src/popup/App.tsx +++ b/src/popup/App.tsx @@ -1,8 +1,8 @@ import browser from 'webextension-polyfill'; import React, { useState, useEffect } from 'react'; import storage from '@/storage'; -import { Message } from '@const'; -import Main from '@components/Main'; +import { Message } from '@/const'; +import Main from '@/components/Main'; const App: React.FC = () => { const [balloonCount, setBalloonCount] = useState(0); diff --git a/src/popup/General.tsx b/src/popup/General.tsx index 10c4c3d7..af67ab9e 100644 --- a/src/popup/General.tsx +++ b/src/popup/General.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import Main from '@components/Main'; -import Leaderboard from '@components/Leaderboard'; +import Main from '@/components/Main'; +import Leaderboard from '@/components/Leaderboard'; export default () => { return ( diff --git a/src/popup/Settings.tsx b/src/popup/Settings.tsx index b41270bf..df9b526f 100644 --- a/src/popup/Settings.tsx +++ b/src/popup/Settings.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { AlertCircle } from 'lucide-react'; -import { Button } from '@components/ui/button'; +import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, @@ -8,13 +8,13 @@ import { DialogHeader, DialogTitle, DialogTrigger, -} from '@components/ui/dialog'; -import { Alert, AlertDescription, AlertTitle } from '@components/ui/alert'; -import { Separator } from '@components/ui/separator'; -import Main from '@components/Main'; -import LocalSettings from '@components/forms/LocalSettings'; -import UpdateUser from '@components/forms/UpdateUser'; -import DeleteUser from '@components/forms/DeleteUser'; +} from '@/components/ui/dialog'; +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; +import { Separator } from '@/components/ui/separator'; +import Main from '@/components/Main'; +import LocalSettings from '@/components/forms/LocalSettings'; +import UpdateUser from '@/components/forms/UpdateUser'; +import DeleteUser from '@/components/forms/DeleteUser'; import Developer from './components/forms/Developer'; export default () => { diff --git a/src/popup/components/Footer.tsx b/src/popup/components/Footer.tsx index 5f9f18af..4527a446 100644 --- a/src/popup/components/Footer.tsx +++ b/src/popup/components/Footer.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Separator } from '@components/ui/separator'; +import { Separator } from '@/components/ui/separator'; import { Button } from './ui/button'; import remote from '@/remote'; import { getBrowser } from '@/utils'; diff --git a/src/popup/components/InfoIcon.tsx b/src/popup/components/InfoIcon.tsx index 80555fd2..91618ed3 100644 --- a/src/popup/components/InfoIcon.tsx +++ b/src/popup/components/InfoIcon.tsx @@ -5,7 +5,7 @@ import { HoverCard, HoverCardContent, HoverCardTrigger, -} from '@components/ui/hover-card'; +} from '@/components/ui/hover-card'; import { cn } from '@/utils'; type InfoIconProps = { diff --git a/src/popup/components/Leaderboard.tsx b/src/popup/components/Leaderboard.tsx index d553368f..29e16bb6 100644 --- a/src/popup/components/Leaderboard.tsx +++ b/src/popup/components/Leaderboard.tsx @@ -8,11 +8,11 @@ import { TableHead, TableHeader, TableRow, -} from '@components/ui/table'; -import { Skeleton } from '@components/ui/skeleton'; +} from '@/components/ui/table'; +import { Skeleton } from '@/components/ui/skeleton'; import remote from '@/remote'; import { RemoteResponse } from '@/const'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const limit = 10; diff --git a/src/popup/components/Main.tsx b/src/popup/components/Main.tsx index 15d28d2c..c142124d 100644 --- a/src/popup/components/Main.tsx +++ b/src/popup/components/Main.tsx @@ -1,7 +1,7 @@ import React, { ReactNode } from 'react'; import { ClassValue } from 'clsx'; -import { ScrollArea, ScrollBar } from '@components/ui/scroll-area'; +import { ScrollArea, ScrollBar } from '@/components/ui/scroll-area'; import { cn } from '@/utils'; interface MainProps { diff --git a/src/popup/components/forms/DeleteUser.tsx b/src/popup/components/forms/DeleteUser.tsx index 15614c4e..3501f23a 100644 --- a/src/popup/components/forms/DeleteUser.tsx +++ b/src/popup/components/forms/DeleteUser.tsx @@ -11,9 +11,9 @@ import { FormItem, FormLabel, FormMessage, -} from '@components/ui/form'; -import { Input } from '@components/ui/input'; -import { Button } from '@components/ui/button'; +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; import storage from '@/storage'; import { User } from '@/const'; import remote from '@/remote'; diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx index b5de75bf..9c78cef6 100644 --- a/src/popup/components/forms/Developer.tsx +++ b/src/popup/components/forms/Developer.tsx @@ -11,8 +11,8 @@ import { FormItem, FormLabel, FormMessage, -} from '@components/ui/form'; -import { Checkbox } from '@components/ui/checkbox'; +} from '@/components/ui/form'; +import { Checkbox } from '@/components/ui/checkbox'; import { sendMessage } from '@/utils'; import storage from '@/storage'; diff --git a/src/popup/components/forms/LocalSettings.tsx b/src/popup/components/forms/LocalSettings.tsx index 9aea2216..cb4ce7be 100644 --- a/src/popup/components/forms/LocalSettings.tsx +++ b/src/popup/components/forms/LocalSettings.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import browser, { manifest, type Permissions } from 'webextension-polyfill'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; -import { Button } from '@components/ui/button'; +import { Button } from '@/components/ui/button'; import { Form, FormField, @@ -10,9 +10,9 @@ import { FormItem, FormLabel, FormMessage, -} from '@components/ui/form'; -import { Slider } from '@components/ui/slider'; -import InfoIcon from '@components/InfoIcon'; +} from '@/components/ui/form'; +import { Slider } from '@/components/ui/slider'; +import InfoIcon from '@/components/InfoIcon'; import { Default as DefaultBalloon } from '@/balloons'; import storage from '@/storage'; import log from 'loglevel'; diff --git a/src/popup/components/forms/UpdateUser.tsx b/src/popup/components/forms/UpdateUser.tsx index 06a6fd74..9ff77278 100644 --- a/src/popup/components/forms/UpdateUser.tsx +++ b/src/popup/components/forms/UpdateUser.tsx @@ -12,9 +12,9 @@ import { FormItem, FormLabel, FormMessage, -} from '@components/ui/form'; -import { Input } from '@components/ui/input'; -import { Button } from '@components/ui/button'; +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; import storage from '@/storage'; import { User } from '@/const'; import remote from '@/remote'; diff --git a/src/popup/components/ui/alert.tsx b/src/popup/components/ui/alert.tsx index bd1735b3..eebdb711 100644 --- a/src/popup/components/ui/alert.tsx +++ b/src/popup/components/ui/alert.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const alertVariants = cva( 'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', diff --git a/src/popup/components/ui/button.tsx b/src/popup/components/ui/button.tsx index 61e8b2e6..6b3dc03d 100644 --- a/src/popup/components/ui/button.tsx +++ b/src/popup/components/ui/button.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const buttonVariants = cva( 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', diff --git a/src/popup/components/ui/checkbox.tsx b/src/popup/components/ui/checkbox.tsx index 8fda91ba..8fb35b89 100644 --- a/src/popup/components/ui/checkbox.tsx +++ b/src/popup/components/ui/checkbox.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; import { Check } from 'lucide-react'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const Checkbox = React.forwardRef< React.ElementRef, diff --git a/src/popup/components/ui/dialog.tsx b/src/popup/components/ui/dialog.tsx index 148c9b85..ce90226e 100644 --- a/src/popup/components/ui/dialog.tsx +++ b/src/popup/components/ui/dialog.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import * as DialogPrimitive from '@radix-ui/react-dialog'; import { X } from 'lucide-react'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const Dialog = DialogPrimitive.Root; diff --git a/src/popup/components/ui/form.tsx b/src/popup/components/ui/form.tsx index b885ed80..779d783b 100644 --- a/src/popup/components/ui/form.tsx +++ b/src/popup/components/ui/form.tsx @@ -10,8 +10,8 @@ import { useFormContext, } from 'react-hook-form'; -import { cn } from '@utils'; -import { Label } from '@components/ui/label'; +import { cn } from '@/utils'; +import { Label } from '@/components/ui/label'; const Form = FormProvider; diff --git a/src/popup/components/ui/hover-card.tsx b/src/popup/components/ui/hover-card.tsx index 09558a95..1a7746fe 100644 --- a/src/popup/components/ui/hover-card.tsx +++ b/src/popup/components/ui/hover-card.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import * as HoverCardPrimitive from '@radix-ui/react-hover-card'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const HoverCard = HoverCardPrimitive.Root; diff --git a/src/popup/components/ui/input.tsx b/src/popup/components/ui/input.tsx index 417c89ec..d8103c86 100644 --- a/src/popup/components/ui/input.tsx +++ b/src/popup/components/ui/input.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { cn } from '@utils'; +import { cn } from '@/utils'; export interface InputProps extends React.InputHTMLAttributes {} diff --git a/src/popup/components/ui/label.tsx b/src/popup/components/ui/label.tsx index d0b2b9e8..e170bc32 100644 --- a/src/popup/components/ui/label.tsx +++ b/src/popup/components/ui/label.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import * as LabelPrimitive from '@radix-ui/react-label'; import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const labelVariants = cva( 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70' diff --git a/src/popup/components/ui/scroll-area.tsx b/src/popup/components/ui/scroll-area.tsx index 408be42e..9a4a69c6 100644 --- a/src/popup/components/ui/scroll-area.tsx +++ b/src/popup/components/ui/scroll-area.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const ScrollArea = React.forwardRef< React.ElementRef, diff --git a/src/popup/components/ui/separator.tsx b/src/popup/components/ui/separator.tsx index 40387853..e8d1ed62 100644 --- a/src/popup/components/ui/separator.tsx +++ b/src/popup/components/ui/separator.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import * as SeparatorPrimitive from '@radix-ui/react-separator'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const Separator = React.forwardRef< React.ElementRef, diff --git a/src/popup/components/ui/skeleton.tsx b/src/popup/components/ui/skeleton.tsx index 556d213b..56f1307a 100644 --- a/src/popup/components/ui/skeleton.tsx +++ b/src/popup/components/ui/skeleton.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { cn } from '@utils'; +import { cn } from '@/utils'; function Skeleton({ className, diff --git a/src/popup/components/ui/slider.tsx b/src/popup/components/ui/slider.tsx index b46933dc..59db8896 100644 --- a/src/popup/components/ui/slider.tsx +++ b/src/popup/components/ui/slider.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import * as SliderPrimitive from '@radix-ui/react-slider'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const Slider = React.forwardRef< React.ElementRef, diff --git a/src/popup/components/ui/table.tsx b/src/popup/components/ui/table.tsx index 5c3de3a0..2520bb17 100644 --- a/src/popup/components/ui/table.tsx +++ b/src/popup/components/ui/table.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; -import { cn } from '@utils'; +import { cn } from '@/utils'; const Table = React.forwardRef< HTMLTableElement, diff --git a/src/popup/index.tsx b/src/popup/index.tsx index 6324613d..3e5195fe 100644 --- a/src/popup/index.tsx +++ b/src/popup/index.tsx @@ -1,11 +1,11 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import { MemoryRouter as Router, Routes, Route } from 'react-router-dom'; -import Header from '@components/Header'; +import Header from '@/components/Header'; import App from './App'; import General from './General'; import Settings from './Settings'; -import Footer from '@components/Footer'; +import Footer from '@/components/Footer'; // Import stylesheet import './style.css'; diff --git a/src/storage.ts b/src/storage.ts index 14583e5d..096f66af 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -1,5 +1,5 @@ import browser from 'webextension-polyfill'; -import { type LocalStorageStructure, type SyncStorageStructure } from '@const'; +import { type LocalStorageStructure, type SyncStorageStructure } from '@/const'; class StorageManager> { private _storage: browser.Storage.StorageArea; diff --git a/src/utils.ts b/src/utils.ts index 86439ee2..44ca3f18 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ import browser from 'webextension-polyfill'; -import { Message, BalloonContainerId } from '@const'; +import { Message, BalloonContainerId } from '@/const'; import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; import storage from '@/storage'; diff --git a/tests/__mocks__/webextension-polyfill.ts b/tests/__mocks__/webextension-polyfill.ts index 23623e39..e138bac3 100644 --- a/tests/__mocks__/webextension-polyfill.ts +++ b/tests/__mocks__/webextension-polyfill.ts @@ -1,4 +1,4 @@ -import { initalConfig, SyncStorageKey, SyncStorageStructure } from '@const'; +import { initalConfig, SyncStorageKey, SyncStorageStructure } from '@/const'; const defaultStorage: SyncStorageStructure = { config: initalConfig, diff --git a/tests/balloon.test.ts b/tests/balloon.test.ts index f1dafc0b..95d9b378 100644 --- a/tests/balloon.test.ts +++ b/tests/balloon.test.ts @@ -1,5 +1,5 @@ import Balloon from '@/balloon'; -import { random } from '@utils'; +import { random } from '@/utils'; // Create a concrete subclass of Balloon for testing class TestBalloon extends Balloon { From 728e157330f7b6f9c7fc61df49d023c7aedc1bf1 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 10:25:39 +0200 Subject: [PATCH 32/40] Move storage manager to managers folder --- src/background/background.ts | 2 +- src/balloon.ts | 2 +- src/content/spawn-balloon.ts | 2 +- src/{ => managers}/storage.ts | 0 src/popup/App.tsx | 2 +- src/popup/components/forms/DeleteUser.tsx | 2 +- src/popup/components/forms/Developer.tsx | 2 +- src/popup/components/forms/LocalSettings.tsx | 2 +- src/popup/components/forms/UpdateUser.tsx | 2 +- src/remote.ts | 2 +- src/utils.ts | 2 +- 11 files changed, 10 insertions(+), 10 deletions(-) rename src/{ => managers}/storage.ts (100%) diff --git a/src/background/background.ts b/src/background/background.ts index 8e258208..611c8aba 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -2,7 +2,7 @@ import browser from 'webextension-polyfill'; import { abbreviateNumber } from 'js-abbreviation-number'; import log from 'loglevel'; import { type LogLevelNames } from '@/types'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import remote from '@/remote'; import { AlarmName, Message, initalConfig } from '@/const'; import { diff --git a/src/balloon.ts b/src/balloon.ts index c81e7c44..090a9cef 100644 --- a/src/balloon.ts +++ b/src/balloon.ts @@ -1,5 +1,5 @@ import browser from 'webextension-polyfill'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import { getBalloonContainer, random, sendMessage } from '@/utils'; export const balloonResourceLocation = browser.runtime.getURL( diff --git a/src/content/spawn-balloon.ts b/src/content/spawn-balloon.ts index ff231ffd..491a2ade 100644 --- a/src/content/spawn-balloon.ts +++ b/src/content/spawn-balloon.ts @@ -7,7 +7,7 @@ import { weightedRandom, } from '@/utils'; import log from 'loglevel'; -import storage from '@/storage'; +import storage from '@/managers/storage'; (async () => { // Prevent running in popup diff --git a/src/storage.ts b/src/managers/storage.ts similarity index 100% rename from src/storage.ts rename to src/managers/storage.ts diff --git a/src/popup/App.tsx b/src/popup/App.tsx index 27c973f5..005627b8 100644 --- a/src/popup/App.tsx +++ b/src/popup/App.tsx @@ -1,6 +1,6 @@ import browser from 'webextension-polyfill'; import React, { useState, useEffect } from 'react'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import { Message } from '@/const'; import Main from '@/components/Main'; diff --git a/src/popup/components/forms/DeleteUser.tsx b/src/popup/components/forms/DeleteUser.tsx index 3501f23a..3447b13f 100644 --- a/src/popup/components/forms/DeleteUser.tsx +++ b/src/popup/components/forms/DeleteUser.tsx @@ -14,7 +14,7 @@ import { } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import { User } from '@/const'; import remote from '@/remote'; diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx index 9c78cef6..ddc4d20e 100644 --- a/src/popup/components/forms/Developer.tsx +++ b/src/popup/components/forms/Developer.tsx @@ -14,7 +14,7 @@ import { } from '@/components/ui/form'; import { Checkbox } from '@/components/ui/checkbox'; import { sendMessage } from '@/utils'; -import storage from '@/storage'; +import storage from '@/managers/storage'; const formSchema = z.object({ loglevel: z.boolean(), diff --git a/src/popup/components/forms/LocalSettings.tsx b/src/popup/components/forms/LocalSettings.tsx index cb4ce7be..7d5d38e4 100644 --- a/src/popup/components/forms/LocalSettings.tsx +++ b/src/popup/components/forms/LocalSettings.tsx @@ -14,7 +14,7 @@ import { import { Slider } from '@/components/ui/slider'; import InfoIcon from '@/components/InfoIcon'; import { Default as DefaultBalloon } from '@/balloons'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import log from 'loglevel'; const MIN_POP_VOLUME = 0; diff --git a/src/popup/components/forms/UpdateUser.tsx b/src/popup/components/forms/UpdateUser.tsx index 9ff77278..ec0f3edd 100644 --- a/src/popup/components/forms/UpdateUser.tsx +++ b/src/popup/components/forms/UpdateUser.tsx @@ -15,7 +15,7 @@ import { } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import { User } from '@/const'; import remote from '@/remote'; diff --git a/src/remote.ts b/src/remote.ts index 0f024b8a..2d38619d 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -1,5 +1,5 @@ import { RemoteResponse, devRemoteResponse, Prettify, Endpoint } from '@/const'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import log from 'loglevel'; interface RequestParams { diff --git a/src/utils.ts b/src/utils.ts index 44ca3f18..880992ab 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,7 +2,7 @@ import browser from 'webextension-polyfill'; import { Message, BalloonContainerId } from '@/const'; import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; -import storage from '@/storage'; +import storage from '@/managers/storage'; import log from 'loglevel'; export function cn(...inputs: ClassValue[]) { From 406c50053895ec31fdc31a829e05e67aee50212a Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 12:15:28 +0200 Subject: [PATCH 33/40] Add log manager --- src/managers/log.ts | 180 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 src/managers/log.ts diff --git a/src/managers/log.ts b/src/managers/log.ts new file mode 100644 index 00000000..8ef0659f --- /dev/null +++ b/src/managers/log.ts @@ -0,0 +1,180 @@ +import loglevel from 'loglevel'; +import storage from '@/managers/storage'; + +export interface LogLevel extends loglevel.LogLevel { + SOFTWARN: typeof loglevel.levels.WARN; + SOFTERROR: typeof loglevel.levels.ERROR; +} +export type LogLevelNumbers = LogLevel[keyof LogLevel]; +export type LogLevelDesc = + | LogLevelNumbers + | LogLevelNames + | 'silent' + | keyof LogLevel; + +export type LogLevelNames = loglevel.LogLevelNames | 'softwarn' | 'softerror'; + +const styles: Record = { + trace: 'color: #888;', + debug: 'color: #888;', + info: 'color: #4d0;', + warn: 'color: #fa0;', + softwarn: 'color: #fa0;', + error: 'color: #d00;', + softerror: 'color: #d00;', +}; + +const originalFactory = loglevel.methodFactory; + +class CustomLog implements loglevel.Logger { + public readonly levels = { + ...loglevel.levels, + SOFTWARN: loglevel.levels.WARN, + SOFTERROR: loglevel.levels.ERROR, + }; + + constructor() { + loglevel.methodFactory = this.methodFactory.bind(this); + + if (process.env.NODE_ENV === 'development') + this.setLevel(this.levels.DEBUG); + storage.local.set('loglevel', this.getLevel()); + + const loglevelName = Object.keys(this.levels).find( + (key) => this.levels[key as keyof typeof this.levels] === this.getLevel() + ); + } + + private toLogLevelDesc(level: LogLevelDesc): loglevel.LogLevelDesc { + if (typeof level === 'string') + level = this.levels[level.toUpperCase() as keyof LogLevel]; + return level; + } + private toLogLevelName(level: LogLevelNames): loglevel.LogLevelNames { + if (level === 'softwarn') return 'warn'; + if (level === 'softerror') return 'error'; + return level; + } + private toLogLevelNumber(level: LogLevelNames): loglevel.LogLevelNumbers { + return this.levels[level.toUpperCase() as keyof LogLevel]; + } + + private shouldLog(level: LogLevelNames): boolean { + return this.toLogLevelNumber(level) >= this.getLevel(); + } + + // + // * Original methods + // + + private createLogMethod(level: LogLevelNames) { + return (...msg: any[]) => { + if (this.shouldLog(level)) { + loglevel[this.toLogLevelName(level)](...msg); + } + }; + } + + public trace = this.createLogMethod('trace'); + public debug = this.createLogMethod('debug'); + public log = this.debug; + public info = this.createLogMethod('info'); + public warn = this.createLogMethod('warn'); + public error = this.createLogMethod('error'); + + public getLogger = (name: string | symbol) => loglevel.getLogger(name); + public getLoggers = () => loglevel.getLoggers(); + public noConflict = () => loglevel.noConflict(); + public rebuild = () => loglevel.rebuild(); + public enableAll = (persist?: boolean) => loglevel.enableAll(persist); + public disableAll = (persist?: boolean) => loglevel.disableAll(persist); + public resetLevel = () => loglevel.resetLevel(); + + // + // * Custom method factory + // + + public methodFactory( + methodName: LogLevelNames, + level: LogLevelNumbers, + loggerName: string | symbol + ): loglevel.LoggingMethod { + const rawMethod = originalFactory( + (() => { + // Trigger loglelvel.info for softwarn and softerror + if (methodName == 'softwarn') return 'info'; + if (methodName == 'softerror') return 'info'; + return methodName; + })(), + level, + loggerName + ); + + return (...message) => { + let lvl = methodName; + // If the first argument is 'softwarn' or 'softerror', change the log level + if ( + message.length > 0 && + (message[0] === 'softwarn' || message[0] == 'softerror') + ) { + lvl = this.toLogLevelName(message[0]); + message.shift(); + } + + // Add styling to the log level and log the rest of the messages + let prefix = '%c' + lvl.toUpperCase(); + rawMethod(`${prefix.padStart(7)}:`, styles[lvl], ...message); + }; + } + + public getLevel = loglevel.getLevel; + + public setLevel(level: LogLevelDesc): void { + loglevel.setLevel(this.toLogLevelDesc(level)); + if (typeof level === 'string') + level = this.toLogLevelNumber(level.toLowerCase() as LogLevelNames); + if (typeof level !== 'number') + throw new TypeError('Invalid log level', level); + storage.local.set('loglevel', level); + } + + public setDefaultLevel(level: LogLevelDesc): void { + loglevel.setDefaultLevel(this.toLogLevelDesc(level)); + } + + // + // * Custom methods + // + + // Add methods for console.time and console.group + public time(level: LogLevelNames, label: string) { + if (!this.shouldLog(level)) return; + console.time(label); + } + public timeEnd(level: LogLevelNames, label: string) { + if (!this.shouldLog(level)) return; + console.timeEnd(label); + } + public group(level: LogLevelNames, label: string) { + if (!this.shouldLog(level)) return; + console.group(label); + } + public groupCollapsed(level: LogLevelNames, label: string) { + if (!this.shouldLog(level)) return; + console.groupCollapsed(label); + } + public groupEnd(level: LogLevelNames) { + if (!this.shouldLog(level)) return; + console.groupEnd(); + } + public softwarn(...msg: any[]) { + this.info('softwarn', ...msg); + } + public softerror(...msg: any[]) { + this.info('softerror', ...msg); + } +} + +const log = new CustomLog(); +log.rebuild(); +export default log; From 66fed9a8786157f0f4f8922ffc6f74a762f04c48 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 12:15:49 +0200 Subject: [PATCH 34/40] Use new log manager --- src/background/background.ts | 7 +- src/const.ts | 6 +- src/content/spawn-balloon.ts | 10 +-- src/popup/components/forms/Developer.tsx | 2 +- src/popup/components/forms/LocalSettings.tsx | 2 +- src/remote.ts | 2 +- src/types/index.d.ts | 15 ---- src/utils.ts | 80 +------------------- 8 files changed, 10 insertions(+), 114 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index 611c8aba..071f4d24 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -1,8 +1,7 @@ import browser from 'webextension-polyfill'; import { abbreviateNumber } from 'js-abbreviation-number'; -import log from 'loglevel'; -import { type LogLevelNames } from '@/types'; import storage from '@/managers/storage'; +import log, { type LogLevelNames } from '@/managers/log'; import remote from '@/remote'; import { AlarmName, Message, initalConfig } from '@/const'; import { @@ -11,7 +10,6 @@ import { getBrowser, isRunningInBackground, sendMessage, - setupLogging, } from '@/utils'; console.log( @@ -44,9 +42,6 @@ const updateBadgeColors = () => { let spawnTimeout: number | null = null; const setup = async () => { - setupLogging(); - await storage.local.set('loglevel', log.getLevel()); - log.info('Pop-a-loon version:', process.env.npm_package_version); log.debug(`Mode: ${process.env.NODE_ENV}`); log.debug('Browser:', getBrowser()); diff --git a/src/const.ts b/src/const.ts index 0102a457..ab3253fd 100644 --- a/src/const.ts +++ b/src/const.ts @@ -1,4 +1,4 @@ -import log from 'loglevel'; +import { LogLevelNumbers } from '@/managers/log'; // // * Config types @@ -91,7 +91,7 @@ export type SyncStorageStructure = { export type SyncStorageKey = keyof SyncStorageStructure; export type LocalStorageStructure = { - loglevel?: log.LogLevelNumbers; + loglevel?: LogLevelNumbers; }; export type LocalStorageKey = keyof LocalStorageStructure; @@ -114,7 +114,7 @@ type SpawnBalloonMessage = { type SetLogLevelMessage = { action: 'setLogLevel'; - level: log.LogLevelNumbers; + level: LogLevelNumbers; }; export type Message = diff --git a/src/content/spawn-balloon.ts b/src/content/spawn-balloon.ts index 491a2ade..fd97baf5 100644 --- a/src/content/spawn-balloon.ts +++ b/src/content/spawn-balloon.ts @@ -1,18 +1,12 @@ import browser from 'webextension-polyfill'; import * as balloons from '@/balloons'; -import { - getBalloonContainer, - importStylesheet, - setupLogging, - weightedRandom, -} from '@/utils'; -import log from 'loglevel'; +import { getBalloonContainer, importStylesheet, weightedRandom } from '@/utils'; +import log from '@/managers/log'; import storage from '@/managers/storage'; (async () => { // Prevent running in popup if (document.body.id === 'pop-a-loon') return; - setupLogging(); log.setLevel((await storage.local.get('loglevel')) || 'info'); log.groupCollapsed('debug', 'Pop-a-loon: Spawning balloon'); log.time('debug', 'Balloon spawn time'); diff --git a/src/popup/components/forms/Developer.tsx b/src/popup/components/forms/Developer.tsx index ddc4d20e..e27b3f36 100644 --- a/src/popup/components/forms/Developer.tsx +++ b/src/popup/components/forms/Developer.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import log from 'loglevel'; +import log from '@/managers/log'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; diff --git a/src/popup/components/forms/LocalSettings.tsx b/src/popup/components/forms/LocalSettings.tsx index 7d5d38e4..5d993e67 100644 --- a/src/popup/components/forms/LocalSettings.tsx +++ b/src/popup/components/forms/LocalSettings.tsx @@ -15,7 +15,7 @@ import { Slider } from '@/components/ui/slider'; import InfoIcon from '@/components/InfoIcon'; import { Default as DefaultBalloon } from '@/balloons'; import storage from '@/managers/storage'; -import log from 'loglevel'; +import log from '@/managers/log'; const MIN_POP_VOLUME = 0; const VOLUME_STEP = 20; diff --git a/src/remote.ts b/src/remote.ts index 2d38619d..a3b3464a 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -1,6 +1,6 @@ import { RemoteResponse, devRemoteResponse, Prettify, Endpoint } from '@/const'; import storage from '@/managers/storage'; -import log from 'loglevel'; +import log from '@/managers/log'; interface RequestParams { [key: string]: string | number | undefined; diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 8d9af455..e69de29b 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,15 +0,0 @@ -import log from 'loglevel'; - -declare module 'loglevel' { - export interface RootLogger { - time: (level: log.LogLevelNames, label: string) => void; - timeEnd: (level: log.LogLevelNames, label: string) => void; - group: (level: log.LogLevelNames, label: string) => void; - groupCollapsed: (level: log.LogLevelNames, label: string) => void; - groupEnd: (level: log.LogLevelNames) => void; - softwarn: (message?: any, ...optionalParams: any[]) => void; - softerror: (message?: any, ...optionalParams: any[]) => void; - } -} - -export type LogLevelNames = log.LogLevelNames | 'softwarn' | 'softerror'; diff --git a/src/utils.ts b/src/utils.ts index 880992ab..a0e722e4 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,7 +3,7 @@ import { Message, BalloonContainerId } from '@/const'; import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; import storage from '@/managers/storage'; -import log from 'loglevel'; +import log from '@/managers/log'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -130,81 +130,3 @@ export async function importStylesheet(id: string, href: string) { document.head.appendChild(style); } } - -export function setupLogging() { - if (process.env.NODE_ENV === 'development') log.setLevel(log.levels.DEBUG); - - // Save the original factory method - const originalFactory = log.methodFactory; - - // Modify the method factory - log.methodFactory = ( - methodName: log.LogLevelNames | 'softwarn' | 'softerror', - logLevel, - loggerName - ) => { - const rawMethod = originalFactory( - (() => { - if (methodName == 'softwarn') return 'info'; - if (methodName == 'softerror') return 'info'; - return methodName; - })(), - logLevel, - loggerName - ); - - return (...message) => { - let lvl = methodName; - if (message.length > 0 && message[0] == 'softwarn') lvl = 'warn'; - if (message.length > 0 && message[0] == 'softerror') lvl = 'error'; - - let prefix = '%c' + lvl.toUpperCase(); - const styles: Record = { - trace: 'color: #888;', - debug: 'color: #888;', - info: 'color: #4d0;', - warn: 'color: #fa0;', - softwarn: 'color: #fa0;', - error: 'color: #d00;', - softerror: 'color: #d00;', - }; - rawMethod(`${prefix.padStart(7)}:`, styles[lvl], ...message); - }; - }; - - const shouldLog = (level: log.LogLevelNames): boolean => { - return ( - log.levels[level.toUpperCase() as keyof log.LogLevel] >= log.getLevel() - ); - }; - - // Add methods for console.time and console.group - log.time = (level: log.LogLevelNames, label: string) => { - if (!shouldLog(level)) return; - console.time(label); - }; - log.timeEnd = (level: log.LogLevelNames, label: string) => { - if (!shouldLog(level)) return; - console.timeEnd(label); - }; - log.group = (level: log.LogLevelNames, label: string) => { - if (!shouldLog(level)) return; - console.group(label); - }; - log.groupCollapsed = (level: log.LogLevelNames, label: string) => { - if (!shouldLog(level)) return; - console.groupCollapsed(label); - }; - log.groupEnd = (level: log.LogLevelNames) => { - if (!shouldLog(level)) return; - console.groupEnd(); - }; - log.softwarn = (message?: any, ...optionalParams: any[]) => { - log.info('softwarn', message, ...optionalParams); - }; - log.softerror = (message?: any, ...optionalParams: any[]) => { - log.info('softerror', message, ...optionalParams); - }; - - log.rebuild(); -} From 8ea7d40a3bce490c47ac9cd71c7d976bbbcff5d7 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 12:19:48 +0200 Subject: [PATCH 35/40] Set log level in backround setup --- src/background/background.ts | 3 ++- src/managers/log.ts | 11 ++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/background/background.ts b/src/background/background.ts index 071f4d24..6b44d9b0 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -37,6 +37,8 @@ const updateBadgeColors = () => { // Check if the background script is running in the background if (!isRunningInBackground()) return; + if (process.env.NODE_ENV === 'development') log.setLevel('debug'); + const rapidSpawnPenalty = 5 * 60 * 1000; // 5 minutes let lastSpawn: number; let spawnTimeout: number | null = null; @@ -231,7 +233,6 @@ const updateBadgeColors = () => { break; case 'setLogLevel': log.setLevel(message.level); - await storage.local.set('loglevel', message.level); break; } }); diff --git a/src/managers/log.ts b/src/managers/log.ts index 8ef0659f..05a5e187 100644 --- a/src/managers/log.ts +++ b/src/managers/log.ts @@ -35,14 +35,7 @@ class CustomLog implements loglevel.Logger { constructor() { loglevel.methodFactory = this.methodFactory.bind(this); - - if (process.env.NODE_ENV === 'development') - this.setLevel(this.levels.DEBUG); storage.local.set('loglevel', this.getLevel()); - - const loglevelName = Object.keys(this.levels).find( - (key) => this.levels[key as keyof typeof this.levels] === this.getLevel() - ); } private toLogLevelDesc(level: LogLevelDesc): loglevel.LogLevelDesc { @@ -129,13 +122,13 @@ class CustomLog implements loglevel.Logger { public getLevel = loglevel.getLevel; - public setLevel(level: LogLevelDesc): void { + public async setLevel(level: LogLevelDesc): Promise { loglevel.setLevel(this.toLogLevelDesc(level)); if (typeof level === 'string') level = this.toLogLevelNumber(level.toLowerCase() as LogLevelNames); if (typeof level !== 'number') throw new TypeError('Invalid log level', level); - storage.local.set('loglevel', level); + await storage.local.set('loglevel', level); } public setDefaultLevel(level: LogLevelDesc): void { From 6f8b3b67d27329ed1d60b0dd718465f25505af8e Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 13:40:28 +0200 Subject: [PATCH 36/40] Add loglevel translator methods --- src/managers/log.ts | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/managers/log.ts b/src/managers/log.ts index 05a5e187..93172787 100644 --- a/src/managers/log.ts +++ b/src/managers/log.ts @@ -38,19 +38,11 @@ class CustomLog implements loglevel.Logger { storage.local.set('loglevel', this.getLevel()); } - private toLogLevelDesc(level: LogLevelDesc): loglevel.LogLevelDesc { - if (typeof level === 'string') - level = this.levels[level.toUpperCase() as keyof LogLevel]; - return level; - } - private toLogLevelName(level: LogLevelNames): loglevel.LogLevelNames { + private toOriginalLogLevelName(level: LogLevelNames): loglevel.LogLevelNames { if (level === 'softwarn') return 'warn'; if (level === 'softerror') return 'error'; return level; } - private toLogLevelNumber(level: LogLevelNames): loglevel.LogLevelNumbers { - return this.levels[level.toUpperCase() as keyof LogLevel]; - } private shouldLog(level: LogLevelNames): boolean { return this.toLogLevelNumber(level) >= this.getLevel(); @@ -63,7 +55,7 @@ class CustomLog implements loglevel.Logger { private createLogMethod(level: LogLevelNames) { return (...msg: any[]) => { if (this.shouldLog(level)) { - loglevel[this.toLogLevelName(level)](...msg); + loglevel[this.toOriginalLogLevelName(level)](...msg); } }; } @@ -110,7 +102,7 @@ class CustomLog implements loglevel.Logger { message.length > 0 && (message[0] === 'softwarn' || message[0] == 'softerror') ) { - lvl = this.toLogLevelName(message[0]); + lvl = this.toOriginalLogLevelName(message[0]); message.shift(); } @@ -129,6 +121,8 @@ class CustomLog implements loglevel.Logger { if (typeof level !== 'number') throw new TypeError('Invalid log level', level); await storage.local.set('loglevel', level); + + // this.info('Log level set to', this.toLogLevelName(level)); } public setDefaultLevel(level: LogLevelDesc): void { @@ -136,7 +130,27 @@ class CustomLog implements loglevel.Logger { } // - // * Custom methods + // * Conversion methods + // + + public toLogLevelDesc(level: LogLevelDesc): loglevel.LogLevelDesc { + if (typeof level === 'string') + level = this.levels[level.toUpperCase() as keyof LogLevel]; + return level; + } + + public toLogLevelName(level: LogLevelDesc): loglevel.LogLevelNames { + return Object.keys(this.levels).find( + (key) => this.levels[key as keyof LogLevel] === level + ) as loglevel.LogLevelNames; + } + + public toLogLevelNumber(level: LogLevelNames): loglevel.LogLevelNumbers { + return this.levels[level.toUpperCase() as keyof LogLevel]; + } + + // + // * Custom log methods // // Add methods for console.time and console.group From acee71b3b46c519ec5ea7bc4151b6c0a2f591545 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 13:45:55 +0200 Subject: [PATCH 37/40] Don't set log level in loglevel manager constructor it causes bugs --- src/background/background.ts | 1 + src/managers/log.ts | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/background.ts b/src/background/background.ts index 6b44d9b0..64aa6c16 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -38,6 +38,7 @@ const updateBadgeColors = () => { if (!isRunningInBackground()) return; if (process.env.NODE_ENV === 'development') log.setLevel('debug'); + else log.setLevel('info'); const rapidSpawnPenalty = 5 * 60 * 1000; // 5 minutes let lastSpawn: number; diff --git a/src/managers/log.ts b/src/managers/log.ts index 93172787..4c7e2e0d 100644 --- a/src/managers/log.ts +++ b/src/managers/log.ts @@ -35,7 +35,6 @@ class CustomLog implements loglevel.Logger { constructor() { loglevel.methodFactory = this.methodFactory.bind(this); - storage.local.set('loglevel', this.getLevel()); } private toOriginalLogLevelName(level: LogLevelNames): loglevel.LogLevelNames { From 3b4b7987b14202663feb0274d3ba55bb7c41b843 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 14:17:47 +0200 Subject: [PATCH 38/40] Setup logging in popup --- src/popup/index.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/popup/index.tsx b/src/popup/index.tsx index 3e5195fe..c82e39aa 100644 --- a/src/popup/index.tsx +++ b/src/popup/index.tsx @@ -9,6 +9,12 @@ import Footer from '@/components/Footer'; // Import stylesheet import './style.css'; +import log from '@/managers/log'; +import storage from '@/managers/storage'; + +(async () => { + log.setLevel((await storage.local.get('loglevel')) ?? log.getLevel()); +})(); const root = ReactDOM.createRoot(document.getElementById('root')!); root.render( From c845fed66a550fc4bfda337bebec8d4fd48dc080 Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 14:23:05 +0200 Subject: [PATCH 39/40] Update logging level display in background.ts --- src/background/background.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/background/background.ts b/src/background/background.ts index 64aa6c16..d50c442e 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -49,7 +49,13 @@ const updateBadgeColors = () => { log.debug(`Mode: ${process.env.NODE_ENV}`); log.debug('Browser:', getBrowser()); log.debug('Running in background:', isRunningInBackground()); - log.debug('Logging level:', log.getLevel()); + log.debug( + 'Logging level:', + log.toLogLevelName(log.getLevel()), + '(', + log.getLevel(), + ')' + ); log.debug(''); // Clear all alarms From 3fc41d39e789ccfb894b7cd20fa7956f6ddbd83b Mon Sep 17 00:00:00 2001 From: SimonStnn Date: Fri, 31 May 2024 23:35:39 +0200 Subject: [PATCH 40/40] Bump package version to 1.10.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2466daa3..d862a803 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pop-a-loon", - "version": "1.10.0", + "version": "1.10.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pop-a-loon", - "version": "1.10.0", + "version": "1.10.1", "license": "Apache-2.0", "dependencies": { "@hookform/resolvers": "^3.3.4", diff --git a/package.json b/package.json index c97f8da0..a7ac6cc9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pop-a-loon", - "version": "1.10.0", + "version": "1.10.1", "description": "The new rising trend (literally) that changes the browser game completely.", "private": true, "scripts": {