mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
add theme saving and indexing
This commit is contained in:
@@ -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"
|
||||
}
|
||||
|
||||
@@ -57,10 +57,43 @@ export const deleteTheme = async (themeName: string) => {
|
||||
}
|
||||
|
||||
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
|
||||
browser.runtime.sendMessage({
|
||||
type: 'currentTab',
|
||||
info: 'UpdateThemePreview',
|
||||
body: updatedTheme,
|
||||
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<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);
|
||||
});
|
||||
};
|
||||
@@ -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<CustomTheme>({
|
||||
id: uuidv4(),
|
||||
name: '',
|
||||
description: '',
|
||||
defaultColour: '',
|
||||
@@ -16,6 +19,16 @@ 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);
|
||||
};
|
||||
@@ -24,13 +37,13 @@ function ThemeCreator() {
|
||||
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);
|
||||
@@ -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) => (
|
||||
<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 ">
|
||||
<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>
|
||||
<input
|
||||
type="text"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
type CustomTheme = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
defaultColour: string;
|
||||
@@ -9,6 +10,6 @@ type CustomTheme = {
|
||||
|
||||
type CustomImage = {
|
||||
id: string;
|
||||
url: string;
|
||||
blob: Blob;
|
||||
variableName: string;
|
||||
}
|
||||
Reference in New Issue
Block a user