improve theme selection + bug fixes

This commit is contained in:
SethBurkart123
2024-05-29 08:01:44 +10:00
parent 4e5a912cbb
commit 026033ad57
7 changed files with 64 additions and 26 deletions
+4
View File
@@ -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;
+21 -10
View File
@@ -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,21 +117,29 @@ const ThemeSelector: ForwardRefExoticComponent<Omit<ThemeSelectorProps, "ref"> &
const handleThemeSelect = useCallback(
async (themeId: string) => {
if (themeId === settingsState.selectedTheme) {
await disableTheme();
setSelectedTheme('');
} else {
const selectedTheme = themes.find((theme) => theme.id === themeId);
if (selectedTheme) {
await setTheme(selectedTheme.id);
setSelectedTheme(themeId);
const unlock = await mutex.lock();
try {
if (themeId === settingsState.selectedTheme) {
await disableTheme();
setSelectedTheme('');
} else {
const selectedTheme = themes.find((theme) => theme.id === themeId);
if (selectedTheme) {
await setTheme(selectedTheme.id);
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) => {
-8
View File
@@ -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);
+21 -5
View File
@@ -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;
}
};
};
+3 -3
View File
@@ -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);
}
+3
View File
@@ -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);
});
};
+12
View File
@@ -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);
}
}