From c9431de33fb724e7f2d0ec8fa390977fe6a0319e Mon Sep 17 00:00:00 2001 From: SethBurkart123 Date: Mon, 1 Apr 2024 15:34:58 +1100 Subject: [PATCH] add theme saving and indexing --- package.json | 2 ++ src/interface/hooks/ThemeManagment.tsx | 45 +++++++++++++++++++---- src/interface/pages/ThemeCreator.tsx | 49 ++++++++++++++++++++------ src/interface/types/CustomThemes.ts | 3 +- 4 files changed, 82 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index ad5d7839..12eff5fb 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@types/react": "^18.2.55", "@types/react-dom": "^18.2.19", "@types/sortablejs": "^1.15.7", + "@types/uuid": "^9.0.8", "@types/webextension-polyfill": "^0.10.7", "@uiw/codemirror-extensions-color": "^4.21.25", "@uiw/codemirror-theme-github": "^4.21.25", @@ -72,6 +73,7 @@ "tailwindcss": "^3.4.1", "ts-loader": "^9.5.1", "typescript": "^5.3.3", + "uuid": "^9.0.1", "vite": "^5.2.2", "webextension-polyfill": "^0.10.0" } diff --git a/src/interface/hooks/ThemeManagment.tsx b/src/interface/hooks/ThemeManagment.tsx index 147977f3..729e1727 100644 --- a/src/interface/hooks/ThemeManagment.tsx +++ b/src/interface/hooks/ThemeManagment.tsx @@ -57,10 +57,43 @@ export const deleteTheme = async (themeName: string) => { } export const sendThemeUpdate = debounce((updatedTheme: CustomTheme) => { - // Send the updated theme to the content script for live preview - browser.runtime.sendMessage({ - type: 'currentTab', - info: 'UpdateThemePreview', - body: updatedTheme, + // Create a copy of the updatedTheme object + const updatedThemeCopy: CustomTheme = { ...updatedTheme }; + + // Convert image blobs to base64 + const base64ConversionPromises = updatedThemeCopy.CustomImages.map(async (image) => { + const base64 = await blobToBase64(image.blob); + return { ...image, base64 }; }); -}, 100); \ No newline at end of file + + Promise.all(base64ConversionPromises) + .then((convertedImages) => { + // Update the CustomImages array with the converted base64 images + updatedThemeCopy.CustomImages = convertedImages; + + // Send the updated theme to the content script for live preview + browser.runtime.sendMessage({ + type: 'currentTab', + info: 'UpdateThemePreview', + body: updatedThemeCopy, + }); + }) + .catch((error) => { + console.error('Error converting image blobs to base64:', error); + }); +}, 100); + +// Helper function to convert a Blob to base64 +const blobToBase64 = (blob: Blob): Promise => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + const base64 = reader.result as string; + resolve(base64); + }; + reader.onerror = (error) => { + reject(error); + }; + reader.readAsDataURL(blob); + }); +}; \ No newline at end of file diff --git a/src/interface/pages/ThemeCreator.tsx b/src/interface/pages/ThemeCreator.tsx index 9d98211e..ec825a7e 100644 --- a/src/interface/pages/ThemeCreator.tsx +++ b/src/interface/pages/ThemeCreator.tsx @@ -5,9 +5,12 @@ import Accordion from '../components/Accordian'; import Switch from '../components/Switch'; import { sendThemeUpdate } from '../hooks/ThemeManagment'; import { XMarkIcon } from '@heroicons/react/24/outline'; +import localforage from 'localforage'; +import { v4 as uuidv4 } from 'uuid'; -function ThemeCreator() { +function ThemeCreator({ themeID }: { themeID?: string }) { const [theme, setTheme] = useState({ + id: uuidv4(), name: '', description: '', defaultColour: '', @@ -16,28 +19,38 @@ function ThemeCreator() { CustomImages: [] }); + useEffect(() => { + if (themeID) { + localforage.getItem(themeID).then((theme) => { + if (theme) { + setTheme(theme as CustomTheme); + } + }); + } + }); + const generateImageId = () => { return '_' + Math.random().toString(36).substr(2, 9); - }; + }; const handleImageUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { const reader = new FileReader(); - reader.onload = () => { - const imageUrl = reader.result as string; + reader.onload = async () => { + const imageBlob = await fetch(reader.result as string).then(res => res.blob()); const imageId = generateImageId(); const variableName = `custom-image-${theme.CustomImages.length}`; const updatedTheme = { ...theme, - CustomImages: [...theme.CustomImages, { id: imageId, url: imageUrl, variableName }], + CustomImages: [...theme.CustomImages, { id: imageId, blob: imageBlob, variableName }], }; setTheme(updatedTheme); sendThemeUpdate(updatedTheme); }; reader.readAsDataURL(file); } - }; + }; const handleRemoveImage = (imageId: string) => { const updatedTheme = { @@ -64,9 +77,25 @@ function ThemeCreator() { })); } - const saveTheme = () => { - // Save the theme to the database - } + 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); + } + }; useEffect(() => { sendThemeUpdate(theme); @@ -131,7 +160,7 @@ function ThemeCreator() { {theme.CustomImages.map((image) => (
- {image.variableName} + {image.variableName}