add theme saving and indexing

This commit is contained in:
SethBurkart123
2024-04-01 15:34:58 +11:00
parent 3c67356f47
commit c9431de33f
4 changed files with 82 additions and 17 deletions
+2
View File
@@ -45,6 +45,7 @@
"@types/react": "^18.2.55", "@types/react": "^18.2.55",
"@types/react-dom": "^18.2.19", "@types/react-dom": "^18.2.19",
"@types/sortablejs": "^1.15.7", "@types/sortablejs": "^1.15.7",
"@types/uuid": "^9.0.8",
"@types/webextension-polyfill": "^0.10.7", "@types/webextension-polyfill": "^0.10.7",
"@uiw/codemirror-extensions-color": "^4.21.25", "@uiw/codemirror-extensions-color": "^4.21.25",
"@uiw/codemirror-theme-github": "^4.21.25", "@uiw/codemirror-theme-github": "^4.21.25",
@@ -72,6 +73,7 @@
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"ts-loader": "^9.5.1", "ts-loader": "^9.5.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"uuid": "^9.0.1",
"vite": "^5.2.2", "vite": "^5.2.2",
"webextension-polyfill": "^0.10.0" "webextension-polyfill": "^0.10.0"
} }
+34 -1
View File
@@ -57,10 +57,43 @@ export const deleteTheme = async (themeName: string) => {
} }
export const sendThemeUpdate = debounce((updatedTheme: CustomTheme) => { export const sendThemeUpdate = debounce((updatedTheme: CustomTheme) => {
// 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 };
});
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 // Send the updated theme to the content script for live preview
browser.runtime.sendMessage({ browser.runtime.sendMessage({
type: 'currentTab', type: 'currentTab',
info: 'UpdateThemePreview', info: 'UpdateThemePreview',
body: updatedTheme, body: updatedThemeCopy,
});
})
.catch((error) => {
console.error('Error converting image blobs to base64:', error);
}); });
}, 100); }, 100);
// Helper function to convert a Blob to base64
const blobToBase64 = (blob: Blob): Promise<string> => {
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);
});
};
+36 -7
View File
@@ -5,9 +5,12 @@ import Accordion from '../components/Accordian';
import Switch from '../components/Switch'; import Switch from '../components/Switch';
import { sendThemeUpdate } from '../hooks/ThemeManagment'; import { sendThemeUpdate } from '../hooks/ThemeManagment';
import { XMarkIcon } from '@heroicons/react/24/outline'; 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<CustomTheme>({ const [theme, setTheme] = useState<CustomTheme>({
id: uuidv4(),
name: '', name: '',
description: '', description: '',
defaultColour: '', defaultColour: '',
@@ -16,6 +19,16 @@ function ThemeCreator() {
CustomImages: [] CustomImages: []
}); });
useEffect(() => {
if (themeID) {
localforage.getItem(themeID).then((theme) => {
if (theme) {
setTheme(theme as CustomTheme);
}
});
}
});
const generateImageId = () => { const generateImageId = () => {
return '_' + Math.random().toString(36).substr(2, 9); return '_' + Math.random().toString(36).substr(2, 9);
}; };
@@ -24,13 +37,13 @@ function ThemeCreator() {
const file = event.target.files?.[0]; const file = event.target.files?.[0];
if (file) { if (file) {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => { reader.onload = async () => {
const imageUrl = reader.result as string; const imageBlob = await fetch(reader.result as string).then(res => res.blob());
const imageId = generateImageId(); const imageId = generateImageId();
const variableName = `custom-image-${theme.CustomImages.length}`; const variableName = `custom-image-${theme.CustomImages.length}`;
const updatedTheme = { const updatedTheme = {
...theme, ...theme,
CustomImages: [...theme.CustomImages, { id: imageId, url: imageUrl, variableName }], CustomImages: [...theme.CustomImages, { id: imageId, blob: imageBlob, variableName }],
}; };
setTheme(updatedTheme); setTheme(updatedTheme);
sendThemeUpdate(updatedTheme); sendThemeUpdate(updatedTheme);
@@ -64,9 +77,25 @@ function ThemeCreator() {
})); }));
} }
const saveTheme = () => { const saveTheme = async () => {
// Save the theme to the database 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(() => { useEffect(() => {
sendThemeUpdate(theme); sendThemeUpdate(theme);
@@ -131,7 +160,7 @@ function ThemeCreator() {
{theme.CustomImages.map((image) => ( {theme.CustomImages.map((image) => (
<div key={image.id} className="flex items-center h-16 py-2 mb-4 bg-white rounded-lg shadow-lg dark:bg-zinc-900"> <div key={image.id} className="flex items-center h-16 py-2 mb-4 bg-white rounded-lg shadow-lg dark:bg-zinc-900">
<div className="flex-1 h-full "> <div className="flex-1 h-full ">
<img src={image.url} alt={image.variableName} className="object-contain h-full rounded" /> <img src={URL.createObjectURL(image.blob)} alt={image.variableName} className="object-contain h-full rounded" />
</div> </div>
<input <input
type="text" type="text"
+2 -1
View File
@@ -1,4 +1,5 @@
type CustomTheme = { type CustomTheme = {
id: string;
name: string; name: string;
description: string; description: string;
defaultColour: string; defaultColour: string;
@@ -9,6 +10,6 @@ type CustomTheme = {
type CustomImage = { type CustomImage = {
id: string; id: string;
url: string; blob: Blob;
variableName: string; variableName: string;
} }