mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
improve theme selection + bug fixes
This commit is contained in:
@@ -56,6 +56,10 @@ html {
|
||||
background-color: rgb(28 28 30);
|
||||
}
|
||||
|
||||
.timetablepage .days .scrollspacer {
|
||||
width: 0 !important;
|
||||
}
|
||||
|
||||
.themeCloseButton {
|
||||
position: absolute !important;
|
||||
color: var(--text-primary) !important;
|
||||
|
||||
@@ -11,7 +11,8 @@ import SpinnerIcon from './LoadingSpinner';
|
||||
import { toast } from 'react-toastify';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
import useVisibility from './useVisibility';
|
||||
import { debounce } from 'lodash';
|
||||
import { debounce, throttle } from 'lodash';
|
||||
import { Mutex } from '../../seqta/utils/mutex';
|
||||
|
||||
interface ThemeSelectorProps {
|
||||
isEditMode: boolean;
|
||||
@@ -30,6 +31,8 @@ const ThemeSelector: ForwardRefExoticComponent<Omit<ThemeSelectorProps, "ref"> &
|
||||
threshold: 0.1, // 10% of the element needs to be visible
|
||||
});
|
||||
|
||||
const mutex = new Mutex();
|
||||
|
||||
const setSelectedTheme = (themeId: string) => {
|
||||
setSettingsState((prevState: SettingsState) => ({
|
||||
...prevState,
|
||||
@@ -114,6 +117,8 @@ const ThemeSelector: ForwardRefExoticComponent<Omit<ThemeSelectorProps, "ref"> &
|
||||
|
||||
const handleThemeSelect = useCallback(
|
||||
async (themeId: string) => {
|
||||
const unlock = await mutex.lock();
|
||||
try {
|
||||
if (themeId === settingsState.selectedTheme) {
|
||||
await disableTheme();
|
||||
setSelectedTheme('');
|
||||
@@ -124,11 +129,17 @@ const ThemeSelector: ForwardRefExoticComponent<Omit<ThemeSelectorProps, "ref"> &
|
||||
setSelectedTheme(themeId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
},
|
||||
[settingsState.selectedTheme, themes]
|
||||
);
|
||||
|
||||
const handleThemeSelectDebounced = debounce(handleThemeSelect, 50);
|
||||
const handleThemeSelectDebounced = useCallback(
|
||||
debounce(handleThemeSelect, 100),
|
||||
[handleThemeSelect]
|
||||
);
|
||||
|
||||
const handleThemeDelete = useCallback(
|
||||
async (themeId: string) => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import browser from 'webextension-polyfill';
|
||||
import { CustomImage, CustomTheme } from '../../../interface/types/CustomThemes';
|
||||
import { applyCustomCSS } from './Themes';
|
||||
|
||||
@@ -6,20 +5,13 @@ import { applyCustomCSS } from './Themes';
|
||||
export const applyTheme = async (theme: CustomTheme) => {
|
||||
let CustomCSS = '';
|
||||
let CustomImages: CustomImage[] = [];
|
||||
let defaultColour = '';
|
||||
|
||||
if (theme?.CustomCSS) CustomCSS = theme.CustomCSS;
|
||||
if (theme?.CustomImages) CustomImages = theme.CustomImages;
|
||||
if (theme?.defaultColour) defaultColour = theme.defaultColour;
|
||||
|
||||
// Apply custom CSS
|
||||
applyCustomCSS(CustomCSS);
|
||||
|
||||
// Apply default color
|
||||
if (defaultColour !== '') {
|
||||
browser.storage.local.set({ selectedColor: defaultColour });
|
||||
}
|
||||
|
||||
// Apply custom images
|
||||
CustomImages.forEach((image) => {
|
||||
const imageUrl = URL.createObjectURL(image.blob);
|
||||
|
||||
@@ -2,19 +2,35 @@ import browser from 'webextension-polyfill';
|
||||
import localforage from 'localforage';
|
||||
import { CustomTheme } from '../../../interface/types/CustomThemes';
|
||||
import { removeTheme } from './removeTheme';
|
||||
import { Mutex } from '../../utils/mutex';
|
||||
|
||||
const mutex = new Mutex();
|
||||
let isDisabling = false;
|
||||
|
||||
export const disableTheme = async () => {
|
||||
if (isDisabling) return;
|
||||
|
||||
const { selectedTheme } = await browser.storage.local.get('selectedTheme') as { selectedTheme: string; };
|
||||
if (!selectedTheme || selectedTheme === '') {
|
||||
// Theme is already disabled, exit early
|
||||
return;
|
||||
}
|
||||
isDisabling = true;
|
||||
const unlock = await mutex.lock();
|
||||
try {
|
||||
const enabledTheme = await browser.storage.local.get('selectedTheme') as { selectedTheme: string; };
|
||||
if (enabledTheme.selectedTheme) {
|
||||
const theme = await localforage.getItem(enabledTheme.selectedTheme) as CustomTheme;
|
||||
await browser.storage.local.set({ selectedTheme: '' });
|
||||
|
||||
if (selectedTheme) {
|
||||
const theme = await localforage.getItem(selectedTheme) as CustomTheme;
|
||||
if (theme) {
|
||||
removeTheme(theme);
|
||||
await removeTheme(theme);
|
||||
}
|
||||
}
|
||||
await browser.storage.local.set({ selectedTheme: '' });
|
||||
} catch (error) {
|
||||
console.error('Error disabling theme:', error);
|
||||
} finally {
|
||||
unlock();
|
||||
isDisabling = false;
|
||||
}
|
||||
};
|
||||
@@ -5,9 +5,9 @@ import { applyTheme } from './applyTheme';
|
||||
|
||||
|
||||
export const enableCurrentTheme = async () => {
|
||||
const themeId = await browser.storage.local.get('selectedTheme') as { selectedTheme: string; };
|
||||
if (themeId.selectedTheme) {
|
||||
const theme = await localforage.getItem(themeId.selectedTheme) as CustomTheme;
|
||||
const { selectedTheme } = await browser.storage.local.get('selectedTheme') as { selectedTheme: string; };
|
||||
if (selectedTheme) {
|
||||
const theme = await localforage.getItem(selectedTheme) as CustomTheme;
|
||||
if (theme) {
|
||||
await applyTheme(theme);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ export const removeTheme = async (theme: CustomTheme) => {
|
||||
// Remove custom images
|
||||
const customImageVariables = theme.CustomImages.map((image) => image.variableName);
|
||||
customImageVariables.forEach((variableName) => {
|
||||
const blobUrl = document.documentElement.style.getPropertyValue('--' + variableName);
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
|
||||
document.documentElement.style.removeProperty('--' + variableName);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Simple mutex implementation
|
||||
export class Mutex {
|
||||
private mutex = Promise.resolve();
|
||||
|
||||
lock(): PromiseLike<() => void> {
|
||||
let begin: (unlock: () => void) => void;
|
||||
|
||||
this.mutex = this.mutex.then(() => new Promise(begin));
|
||||
|
||||
return new Promise(res => begin = res);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user