From 6c799ba3469fa34442009969bb97cbadf90eaa7b Mon Sep 17 00:00:00 2001 From: SethBurkart123 Date: Mon, 1 Apr 2024 20:24:51 +1100 Subject: [PATCH] add theme saving (This took hours) --- src/interface/components/ThemeCover.tsx | 58 ++++ src/interface/components/ThemeSelector.tsx | 243 +++++--------- src/interface/hooks/ThemeManagment.tsx | 52 ++- src/interface/pages/SettingsPage/Themes.tsx | 6 +- src/interface/pages/ThemeCreator.tsx | 21 +- src/interface/types/CustomThemes.ts | 19 +- src/seqta/ui/Themes.ts | 323 +++++++++---------- src/seqta/utils/listeners/MessageListener.ts | 112 ++++--- 8 files changed, 427 insertions(+), 407 deletions(-) create mode 100644 src/interface/components/ThemeCover.tsx diff --git a/src/interface/components/ThemeCover.tsx b/src/interface/components/ThemeCover.tsx new file mode 100644 index 00000000..d55bb408 --- /dev/null +++ b/src/interface/components/ThemeCover.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { CustomTheme } from '../types/CustomThemes'; + +type ThemeCoverProps = { + theme: Omit; + isSelected: boolean; + isEditMode: boolean; + onThemeSelect: (themeId: string) => void; + onThemeDelete: (themeId: string) => void; +}; + +export const ThemeCover: React.FC = ({ + theme, + isSelected, + isEditMode, + onThemeSelect, + onThemeDelete, +}) => { + const handleThemeClick = () => { + onThemeSelect(theme.id); + }; + + const handleDeleteClick = (e: React.MouseEvent) => { + e.stopPropagation(); + onThemeDelete(theme.id); + }; + + return ( + + ); +}; \ No newline at end of file diff --git a/src/interface/components/ThemeSelector.tsx b/src/interface/components/ThemeSelector.tsx index ecee28d5..f4251d76 100644 --- a/src/interface/components/ThemeSelector.tsx +++ b/src/interface/components/ThemeSelector.tsx @@ -1,177 +1,106 @@ -import { memo, useEffect, useState } from "react"; -import themesList from '../assets/themes'; -import { listThemes, disableTheme, downloadTheme, setTheme, deleteTheme } from "../hooks/ThemeManagment"; -import Browser from "webextension-polyfill"; - -interface Theme { - name: string; - url: string; - isDownloaded: boolean; - isLoading: boolean; - coverImage: JSX.Element; -} +import React, { useEffect, useState, useCallback } from 'react'; +import { listThemes, deleteTheme, setTheme, disableTheme } from '../hooks/ThemeManagment'; +import { ThemeCover } from './ThemeCover'; +import Browser from 'webextension-polyfill'; +import { CustomTheme } from '../types/CustomThemes'; interface ThemeSelectorProps { - selectedType: "background" | "theme"; - setSelectedType: (type: "background" | "theme") => void; + setSelectedType: React.Dispatch>; + selectedType: 'background' | 'theme'; isEditMode: boolean; } -const ThemeSelector = ({ selectedType, setSelectedType, isEditMode }: ThemeSelectorProps) => { - const [themes, setThemes] = useState([]); - const [enabledThemeName, setEnabledThemeName] = useState(''); - - useEffect(() => { - const initializeThemes = async () => { - const downloaded = (await listThemes()); - const initializedThemes = themesList.map(theme => ({ - ...theme, - isDownloaded: downloaded.themes.includes(theme.name), - isLoading: false - })); - - if (downloaded.selectedTheme !== '') { - setEnabledThemeName(downloaded.selectedTheme); - } - - initializedThemes.sort((a, b) => Number(b.isDownloaded) - Number(a.isDownloaded)); - - setThemes(initializedThemes); - }; - - initializeThemes(); - }, []); - - const handleDeleteTheme = async (themeName: string) => { - await deleteTheme(themeName); - setThemes(prevThemes => { - // Update the theme's isDownloaded property to false - const updatedThemes = prevThemes.map(theme => { - if (theme.name === themeName) { - return { ...theme, isDownloaded: false }; - } - return theme; - }); - - // Sort themes so non-downloaded ones appear last - updatedThemes.sort((a, b) => Number(b.isDownloaded) - Number(a.isDownloaded)); - - return updatedThemes; - }); - - // Reset the enabled theme name if the deleted theme was the currently enabled one - if (enabledThemeName === themeName) { - setEnabledThemeName(''); - setSelectedType('background'); - } - }; - - const handleThemeAction = async (themeName: string, themeURL: string) => { - const startLoading = (name: string) => ( - setThemes(prevThemes => prevThemes.map(theme => - theme.name === name ? { ...theme, isLoading: true } : theme - )) - ); - - // Stop loading for the selected theme. - const stopLoading = (name: string) => ( - setThemes(prevThemes => prevThemes.map(theme => - theme.name === name ? { ...theme, isLoading: false } : theme - )) - ); - - // Update the theme as downloaded. - const markAsDownloaded = (name: string) => ( - setThemes(prevThemes => prevThemes.map(theme => - theme.name === name ? { ...theme, isDownloaded: true } : theme - )) - ); - - startLoading(themeName); - - // Early return if theme is not found. - const theme = themes.find(t => t.name === themeName); - if (!theme) { - stopLoading(themeName); - return; - } - - // If theme is downloaded and is the currently enabled theme, disable it. - if (theme.isDownloaded && themeName === enabledThemeName) { - await disableTheme(); - setEnabledThemeName(''); - setSelectedType('background'); - stopLoading(themeName); - return; - } - - // If theme is downloaded but not enabled, enable it. - if (theme.isDownloaded && themeName !== enabledThemeName) { - await setTheme(themeName, themeURL); - setEnabledThemeName(themeName); - setSelectedType('theme'); - stopLoading(themeName); - return; - } - - // If theme is not downloaded, download and enable it. - if (!theme.isDownloaded) { - await downloadTheme(themeName, themeURL); - markAsDownloaded(themeName); - setSelectedType('theme'); - setEnabledThemeName(themeName); - } - - stopLoading(themeName); - }; +const ThemeSelector: React.FC = ({ + setSelectedType, + selectedType, + isEditMode, +}) => { + const [themes, setThemes] = useState[]>([]); + const [isLoading, setIsLoading] = useState(true); + const [selectedThemeId, setSelectedThemeId] = useState(null); useEffect(() => { if (selectedType === 'background') { - setEnabledThemeName(''); + setSelectedThemeId(null); } }, [selectedType]); + useEffect(() => { + const fetchThemes = async () => { + try { + const { themes, selectedTheme } = await listThemes(); + + console.log(await listThemes()); + + setThemes(themes); + setSelectedThemeId(selectedTheme ? selectedTheme : null); + } catch (error) { + console.error('Error fetching themes:', error); + } finally { + setIsLoading(false); + } + }; + + fetchThemes(); + }, []); + + const handleThemeSelect = useCallback( + async (themeId: string) => { + if (themeId === selectedThemeId) { + await disableTheme(); + setSelectedThemeId(null); + setSelectedType('background'); + } else { + const selectedTheme = themes.find((theme) => theme.id === themeId); + if (selectedTheme) { + await setTheme(selectedTheme.id); + setSelectedThemeId(themeId); + setSelectedType('theme'); + } + } + }, + [selectedThemeId, themes, setSelectedType] + ); + + const handleThemeDelete = useCallback( + async (themeId: string) => { + try { + await deleteTheme(themeId); + setThemes((prevThemes) => prevThemes.filter((theme) => theme.id !== themeId)); + if (themeId === selectedThemeId) { + setSelectedThemeId(null); + setSelectedType('background'); + } + } catch (error) { + console.error('Error deleting theme:', error); + } + }, + [selectedThemeId, setSelectedType] + ); + + if (isLoading) { + return
Loading themes...
; + } + return (
- {(isEditMode ? themes.some(theme => theme.isDownloaded) : themes.length > 0) && ( -

Themes

- )} +

Themes

- {themes - .filter(theme => !isEditMode || theme.isDownloaded) // Only show downloaded themes in edit mode - .map((theme) => ( - + {themes.map((theme) => ( + ))} @@ -180,4 +109,4 @@ const ThemeSelector = ({ selectedType, setSelectedType, isEditMode }: ThemeSelec ); }; -export default memo(ThemeSelector); \ No newline at end of file +export default ThemeSelector; \ No newline at end of file diff --git a/src/interface/hooks/ThemeManagment.tsx b/src/interface/hooks/ThemeManagment.tsx index 729e1727..fa2059f5 100644 --- a/src/interface/hooks/ThemeManagment.tsx +++ b/src/interface/hooks/ThemeManagment.tsx @@ -1,9 +1,6 @@ import { debounce } from 'lodash'; import browser from 'webextension-polyfill' -interface ThemeList { - themes: string[]; - selectedTheme: string; -} +import { CustomTheme, ThemeList } from '../types/CustomThemes'; export const downloadTheme = async (themeName: string, themeURL: string) => { // send message to the background script @@ -17,23 +14,32 @@ export const downloadTheme = async (themeName: string, themeURL: string) => { }); } -export const setTheme = async (themeName: string, themeURL: string) => { +export const setTheme = async (themeID: string) => { // send message to the background script await browser.runtime.sendMessage({ type: 'currentTab', info: 'SetTheme', body: { - themeName: themeName, - themeURL: themeURL + themeID: themeID } }); } -export const listThemes = async () => { +export const listThemes = async (): Promise => { // send message to the background script - const response: ThemeList = await browser.runtime.sendMessage({ - type: 'currentTab', - info: 'ListThemes' + const response: ThemeList = await new Promise((resolve, reject) => { + browser.runtime.sendMessage({ + type: 'currentTab', + info: 'ListThemes' + }).then((response) => { + if (response) { + resolve(response); + } else { + reject(new Error('Failed to get response')); + } + }).catch((error: any) => { + reject(error); + }); }); return response; @@ -46,20 +52,22 @@ export const disableTheme = async () => { }); }; -export const deleteTheme = async (themeName: string) => { +export const deleteTheme = async (themeID: string) => { await browser.runtime.sendMessage({ type: 'currentTab', info: 'DeleteTheme', body: { - themeName: themeName + themeID: themeID } }); } -export const sendThemeUpdate = debounce((updatedTheme: CustomTheme) => { +export const sendThemeUpdate = debounce((updatedTheme: CustomTheme, saveTheme?: boolean) => { // Create a copy of the updatedTheme object const updatedThemeCopy: CustomTheme = { ...updatedTheme }; + saveTheme = saveTheme || false; + // Convert image blobs to base64 const base64ConversionPromises = updatedThemeCopy.CustomImages.map(async (image) => { const base64 = await blobToBase64(image.blob); @@ -76,6 +84,7 @@ export const sendThemeUpdate = debounce((updatedTheme: CustomTheme) => { type: 'currentTab', info: 'UpdateThemePreview', body: updatedThemeCopy, + save: saveTheme, }); }) .catch((error) => { @@ -96,4 +105,19 @@ const blobToBase64 = (blob: Blob): Promise => { }; reader.readAsDataURL(blob); }); +}; + +export const enableCurrentTheme = async () => { + await browser.runtime.sendMessage({ + type: 'currentTab', + info: 'EnableCurrentTheme', + }); +}; + +export const saveUpdatedTheme = async (updatedTheme: CustomTheme) => { + await browser.runtime.sendMessage({ + type: 'currentTab', + info: 'SaveTheme', + body: updatedTheme, + }); }; \ No newline at end of file diff --git a/src/interface/pages/SettingsPage/Themes.tsx b/src/interface/pages/SettingsPage/Themes.tsx index 0fb3d1f8..c83a283c 100644 --- a/src/interface/pages/SettingsPage/Themes.tsx +++ b/src/interface/pages/SettingsPage/Themes.tsx @@ -9,7 +9,7 @@ const Themes: FC = () => { useEffect(() => { listThemes().then(themes => { - if (themes.selectedTheme) { + if (themes?.selectedTheme) { setSelectedType('theme'); } else { setSelectedType('background'); @@ -18,12 +18,12 @@ const Themes: FC = () => { }, []) return ( -
+
- +
); }; diff --git a/src/interface/pages/ThemeCreator.tsx b/src/interface/pages/ThemeCreator.tsx index ec825a7e..afb5a036 100644 --- a/src/interface/pages/ThemeCreator.tsx +++ b/src/interface/pages/ThemeCreator.tsx @@ -7,6 +7,7 @@ import { sendThemeUpdate } from '../hooks/ThemeManagment'; import { XMarkIcon } from '@heroicons/react/24/outline'; import localforage from 'localforage'; import { v4 as uuidv4 } from 'uuid'; +import { CustomTheme } from '../types/CustomThemes'; function ThemeCreator({ themeID }: { themeID?: string }) { const [theme, setTheme] = useState({ @@ -77,24 +78,8 @@ function ThemeCreator({ themeID }: { themeID?: string }) { })); } - const saveTheme = async () => { - try { - await localforage.setItem(theme.id, theme); - await localforage.getItem('customThemes').then((themes: unknown) => { - const themeList = themes as string[] | null; - if (themeList) { - if (!themeList.includes(theme.id)) { - themeList.push(theme.id); - localforage.setItem('customThemes', themeList); - } - } else { - localforage.setItem('customThemes', [theme.id]); - } - }); - console.log('Theme saved successfully!'); - } catch (error) { - console.error('Error saving theme:', error); - } + const saveTheme = () => { + sendThemeUpdate(theme, true); }; useEffect(() => { diff --git a/src/interface/types/CustomThemes.ts b/src/interface/types/CustomThemes.ts index 913da6fc..c7226104 100644 --- a/src/interface/types/CustomThemes.ts +++ b/src/interface/types/CustomThemes.ts @@ -1,4 +1,4 @@ -type CustomTheme = { +export type CustomTheme = { id: string; name: string; description: string; @@ -8,8 +8,23 @@ type CustomTheme = { CustomImages: CustomImage[]; } -type CustomImage = { +export type CustomImage = { id: string; blob: Blob; variableName: string; +} + +export type CustomImageBase64 = { + id: string; + url: string; + variableName: string; +} + +export type CustomThemeBase64 = Omit & { + CustomImages: CustomImageBase64[]; +} + +export type ThemeList = { + themes: Omit[]; + selectedTheme: string; } \ No newline at end of file diff --git a/src/seqta/ui/Themes.ts b/src/seqta/ui/Themes.ts index 93af8c5d..94e9e8ba 100644 --- a/src/seqta/ui/Themes.ts +++ b/src/seqta/ui/Themes.ts @@ -1,169 +1,97 @@ import browser from 'webextension-polyfill' import localforage from 'localforage'; - -let currentThemeClass = ''; - -// Utility function to fetch and parse JSON -const fetchJSON = async (url: any) => { - const res = await fetch(url, {cache: 'no-store'}); - return await res.json(); -}; - -// Utility function to fetch and parse text -const fetchText = async (url: any) => { - const res = await fetch(url); - return await res.text(); -}; - -// Check if the theme already exists in IndexedDB -const themeExistsInDB = async (themeName: any) => { - return (await localforage.getItem(`css_${themeName}`)) !== null; -}; - -// Fetch theme details (CSS, images, className, darkMode, defaultColour) from a given URL -const fetchThemeJSON = async (url: any) => { - const { css, images, className, darkMode, defaultColour } = await fetchJSON(url); - const cssText = await fetchText(css); - return { css: cssText, images, className, darkMode, defaultColour }; -}; - -// Save individual image to IndexedDB -const saveImageToDB = async (themeName: any, cssVar: any, imageUrl: any) => { - try { - const response = await fetch(imageUrl); - if (!response.ok) throw new Error(response.statusText); - const blob = await response.blob(); - await localforage.setItem(`images_${themeName}_${cssVar}`, blob); - } catch (error) { - console.error(`Failed to save image for ${cssVar}: ${error}`); - } -}; - -// Save theme details to storage via localForage -const saveToIndexedDB = async (theme: any, themeName: any) => { - await localforage.setItem(`css_${themeName}`, theme); - await Promise.all(Object.entries(theme.images).map(([cssVar, imageUrl]) => saveImageToDB(themeName, cssVar, imageUrl))); -}; - -declare global { - interface Window { - currentThemeStyle: any; - currentThemeClass: any; - } -} - -// Apply theme from storage via localForage to document, including dark mode and default color -const applyTheme = async (themeName: any) => { - const { css, className, images, darkMode, defaultColour }: any = await localforage.getItem(`css_${themeName}`); - - const newStyle = document.createElement('style'); - newStyle.innerHTML = css; - document.head.appendChild(newStyle); - - if (window.currentThemeStyle) { - document.head.removeChild(window.currentThemeStyle); - } - - window.currentThemeStyle = newStyle; - - if (window.currentThemeClass) { - document.body.classList.remove(window.currentThemeClass); - } - if (className) { - document.body.classList.add(className); - window.currentThemeClass = className; - } - - if (images) { - await Promise.all( - Object.keys(images).map(async (cssVar) => { - const imageData: any = await localforage.getItem(`images_${themeName}_${cssVar}`); - const objectURL = URL.createObjectURL(imageData); - document.documentElement.style.setProperty(cssVar, `url(${objectURL})`); - }) - ); - } - - browser.storage.local.set({ DarkMode: darkMode, selectedColor: defaultColour }); -}; - -export const listThemes = async () => { - const themes = await localforage.keys(); - return { - themes: themes.filter((key) => key.startsWith('css_')).map((key) => key.replace('css_', '')), - selectedTheme: await localforage.getItem('selectedTheme') - }; -}; - -export const downloadTheme = async (themeName: any, themeUrl: any) => { - const themeData = await fetchThemeJSON(themeUrl); - await saveToIndexedDB(themeData, themeName); - await setTheme(themeName, themeUrl); -}; - -export const deleteTheme = async (themeName: any) => { - const currentTheme = await localforage.getItem('selectedTheme'); - if (currentTheme === themeName) { - await disableTheme(); - } - await localforage.removeItem(`css_${themeName}`); - await Promise.all( - (await localforage.keys()).filter((key) => key.startsWith(`images_${themeName}`)).map((key) => localforage.removeItem(key)) - ); -}; - -export const setTheme = async (themeName: any, themeUrl: any) => { - if (!(await themeExistsInDB(themeName))) { - await downloadTheme(themeName, themeUrl); - } - - await localforage.setItem('selectedTheme', themeName); - await applyTheme(themeName).catch((error) => { - console.error(`Failed to apply theme: ${error}`); - }); -}; - -export const enableCurrentTheme = async () => { - const currentTheme = await localforage.getItem('selectedTheme'); - - if (currentTheme) { - await applyTheme(currentTheme).catch((error) => { - console.error(`Failed to apply current theme: ${error}`); - }); - } -}; - -export const disableTheme = async () => { - // Remove current theme's style if it exists - if (window.currentThemeStyle) { - document.head.removeChild(window.currentThemeStyle); - window.currentThemeStyle = null; - } - - // Remove current theme's class if it exists - if (currentThemeClass) { - document.body.classList.remove(currentThemeClass); - currentThemeClass = ''; - } - - // Remove any applied image URLs from the root element - const currentTheme = await localforage.getItem('selectedTheme'); - if (currentTheme) { - const themeData: any = await localforage.getItem(`css_${currentTheme}`); - if (themeData && themeData.images) { - Object.keys(themeData.images).forEach(cssVar => { - document.documentElement.style.removeProperty(cssVar); - }); - } - } - - // Clear the selected theme from localforage - localforage.removeItem('selectedTheme'); -}; +import { CustomImageBase64, CustomTheme, CustomThemeBase64, ThemeList } from '../../interface/types/CustomThemes'; const imageData: Record = {}; -export const UpdateThemePreview = async (updatedTheme: CustomTheme) => { +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; + if (theme) { + await applyTheme(theme); + } + } +} + +export const deleteTheme = async (themeId: string) => { + try { + await localforage.removeItem(themeId); + const themeIds = await localforage.getItem('customThemes') as string[] | null; + if (themeIds) { + const updatedThemeIds = themeIds.filter((id) => id !== themeId); + await localforage.setItem('customThemes', updatedThemeIds); + } + console.log('Theme deleted successfully!'); + } catch (error) { + console.error('Error deleting theme:', error); + } +}; + +export const getAvailableThemes = async (): Promise => { + try { + const themeIds = await localforage.getItem('customThemes') as string[] | null; + console.log('Available themes:', themeIds); + if (themeIds) { + const themes = await Promise.all( + themeIds.map(async (id) => { + const theme = await localforage.getItem(id) as CustomTheme; + const { CustomImages, ...themeWithoutImages } = theme; + return themeWithoutImages; + }) + ); + + const selectedTheme = await browser.storage.local.get('selectedTheme') as { selectedTheme: string }; + + return { themes, selectedTheme: selectedTheme.selectedTheme ? selectedTheme.selectedTheme : '' }; + } + return { + themes: [], + selectedTheme: '', + }; + } catch (error) { + console.error('Error getting available themes:', error); + return { + themes: [], + selectedTheme: '' + }; + } +}; + +export const saveTheme = async (theme: CustomThemeBase64) => { + try { + const updatedTheme: CustomTheme = { + ...theme, + CustomImages: await Promise.all( + theme.CustomImages.map(async (image) => ({ + id: image.id, + blob: await fetch(image.url).then((res) => res.blob()), + variableName: image.variableName, + })) + ), + }; + + console.log('Theme to save:', updatedTheme) + + await localforage.setItem(updatedTheme.id, updatedTheme); + await localforage.getItem('customThemes').then((themes: unknown) => { + const themeList = themes as string[] | null; + if (themeList) { + if (!themeList.includes(updatedTheme.id)) { + themeList.push(updatedTheme.id); + localforage.setItem('customThemes', themeList); + } + } else { + localforage.setItem('customThemes', [updatedTheme.id]); + } + }); + console.log('Theme saved successfully!'); + } catch (error) { + console.error('Error saving theme:', error); + } +}; + +export const UpdateThemePreview = async (updatedTheme: CustomThemeBase64) => { const { CustomCSS, CustomImages, defaultColour } = updatedTheme; // Update image data @@ -225,7 +153,7 @@ function removeImageFromDocument(variableName: string) { document.documentElement.style.removeProperty('--' + variableName); } -export function updateImage(image: CustomImage) { +export function updateImage(image: CustomImageBase64) { // Extract base64 data from the data URI const base64Index = image.url.indexOf(',') + 1; const imageBase64 = image.url.substring(base64Index); @@ -243,4 +171,75 @@ export function updateImage(image: CustomImage) { const imageUrl = URL.createObjectURL(blob); return imageUrl; +} + +const applyTheme = async (theme: CustomTheme) => { + const { CustomCSS, CustomImages, defaultColour } = theme; + + // 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); + document.documentElement.style.setProperty('--' + image.variableName, `url(${imageUrl})`); + }); +}; + +const removeTheme = (theme: CustomTheme) => { + // Remove custom CSS + const styleElement = document.getElementById('theme-preview-styles'); + if (styleElement) { + styleElement.parentNode?.removeChild(styleElement); + } + + // Reset default color + //browser.storage.local.set({ selectedColor: '' }); + + // Remove custom images + const customImageVariables = theme.CustomImages.map((image) => image.variableName); + customImageVariables.forEach((variableName) => { + document.documentElement.style.removeProperty('--' + variableName); + }); +}; + +export const setTheme = async (themeId: string) => { + try { + const enabledTheme = await browser.storage.local.get('selectedTheme') as { selectedTheme: string }; + const theme = await localforage.getItem(themeId) as CustomTheme; + + // Remove the currently enabled theme + if (enabledTheme.selectedTheme) { + const currentTheme = await localforage.getItem(enabledTheme.selectedTheme) as CustomTheme; + if (currentTheme) { + removeTheme(currentTheme); + } + } + + await applyTheme(theme); + await browser.storage.local.set({ selectedTheme: themeId }); + + } catch (error) { + console.error('Error setting theme:', error); + } +} + +export const disableTheme = async () => { + try { + const enabledTheme = await browser.storage.local.get('selectedTheme') as { selectedTheme: string }; + if (enabledTheme.selectedTheme) { + const theme = await localforage.getItem(enabledTheme.selectedTheme) as CustomTheme; + if (theme) { + removeTheme(theme); + } + } + await browser.storage.local.set({ selectedTheme: '' }); + } catch (error) { + console.error('Error disabling theme:', error); + } } \ No newline at end of file diff --git a/src/seqta/utils/listeners/MessageListener.ts b/src/seqta/utils/listeners/MessageListener.ts index 8bc74023..5db7c810 100644 --- a/src/seqta/utils/listeners/MessageListener.ts +++ b/src/seqta/utils/listeners/MessageListener.ts @@ -1,7 +1,7 @@ import browser from 'webextension-polyfill' import { MenuOptionsOpen, OpenMenuOptions, OpenWhatsNewPopup, closeSettings } from '../../../SEQTA'; -import { deleteTheme, disableTheme, downloadTheme, listThemes, setTheme, UpdateThemePreview } from '../../ui/Themes'; +import { UpdateThemePreview, deleteTheme, disableTheme, enableCurrentTheme, getAvailableThemes, saveTheme, setTheme } from '../../ui/Themes'; import { OpenThemeCreator } from '../../ui/ThemeCreator'; export class MessageHandler { @@ -10,59 +10,69 @@ export class MessageHandler { } routeMessage(request: any, _sender: any, sendResponse: any) { switch (request.info) { + case 'EditSidebar': + this.editSidebar(); + closeSettings(); + sendResponse({ status: 'success' }); + break; + + case 'UpdateThemePreview': + if (request?.save == true) { + saveTheme(request.body).then(() => { + setTheme(request.body.themeID).then(() => { + sendResponse({ status: 'success' }); + }); + }); + } else { + UpdateThemePreview(request.body); + sendResponse({ status: 'success' }); + } + break; + + case 'SaveTheme': + saveTheme(request.body).then(() => { + sendResponse({ status: 'success' }); + }); + break; + + case 'SetTheme': + setTheme(request.body.themeID).then(() => { + sendResponse({ status: 'success' }); + }); + break; + + case 'DisableTheme': + disableTheme().then(() => { + sendResponse({ status: 'success' }); + }); + break; + + case 'DeleteTheme': + deleteTheme(request.body.themeID).then(() => { + sendResponse({ status: 'success' }); + }); + break; - case 'EditSidebar': - this.editSidebar(); - closeSettings(); - sendResponse({ status: 'success' }); - break; - - /* Theme related */ - case 'SetTheme': - console.log(request); - setTheme(request.body.themeName, request.body.themeURL).then(() => { + case 'ListThemes': + getAvailableThemes().then((themes) => { + sendResponse(themes); + }); + return true; + + case 'OpenChangelog': + OpenWhatsNewPopup(); + closeSettings(); sendResponse({ status: 'success' }); - }); - return true; - case 'DownloadTheme': - downloadTheme(request.body.themeName, request.body.themeURL).then(() => { + break; + + case 'OpenThemeCreator': + OpenThemeCreator(); + closeSettings(); sendResponse({ status: 'success' }); - }); - return true; - case 'ListThemes': - listThemes().then((response) => { - sendResponse(response); - }); - return true; - case 'DisableTheme': - disableTheme().then(() => { - sendResponse({ status: 'success' }); - }); - return true; - case 'DeleteTheme': - deleteTheme(request.body.themeName).then(() => { - sendResponse({ status: 'success' }); - }); - return true; - case 'UpdateThemePreview': - UpdateThemePreview(request.body).then(() => { - sendResponse({ status: 'success' }); - }); - break; - case 'OpenChangelog': - OpenWhatsNewPopup(); - closeSettings(); - sendResponse({ status: 'success' }); - break; - case 'OpenThemeCreator': - OpenThemeCreator(); - closeSettings(); - sendResponse({ status: 'success' }); - break; - - default: - console.log('Unknown request info:', request.info); - + break; + + default: + console.log('Unknown request info:', request.info); } }