add custom cover images to themes.

This commit is contained in:
SethBurkart123
2024-04-07 15:05:11 +10:00
parent 7305b0da67
commit b7e7c24727
7 changed files with 57 additions and 17 deletions
+3 -6
View File
@@ -54,16 +54,13 @@ export const ThemeCover: React.FC<ThemeCoverProps> = ({
} }
<div className="relative top-0 z-10 flex justify-center w-full h-full overflow-hidden transition dark:text-white rounded-xl group place-items-center bg-zinc-100 dark:bg-zinc-900"> <div className="relative top-0 z-10 flex justify-center w-full h-full overflow-hidden transition dark:text-white rounded-xl group place-items-center bg-zinc-100 dark:bg-zinc-900">
{/* Render theme cover image or placeholder */} {theme.coverImage &&
{/* {theme.CustomImages.length > 0 ? (
<img <img
src={URL.createObjectURL(theme.CustomImages[0].blob)} src={theme.coverImage as string}
alt={theme.name} alt={theme.name}
className="absolute inset-0 z-0 object-cover" className="absolute inset-0 z-0 object-cover"
/> />
) : ( }
<div className="absolute inset-0 z-0 bg-gray-300 rounded-lg"></div>
)} */}
<div className="z-10">{theme.name}</div> <div className="z-10">{theme.name}</div>
</div> </div>
</button> </button>
+25 -7
View File
@@ -30,8 +30,19 @@ export const listThemes = async (): Promise<ThemeList> => {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
type: 'currentTab', type: 'currentTab',
info: 'ListThemes' info: 'ListThemes'
}).then((response) => { }).then(async (response) => {
if (response) { if (response) {
// convert the response themes coverImage to a bloburl
response.themes = await Promise.all(
response.themes.map(async (theme: Omit<CustomTheme, 'CustomImages'>) => {
if (theme.coverImage) {
const blob = await fetch(theme.coverImage as string).then((res) => res.blob());
theme.coverImage = URL.createObjectURL(blob);
}
return theme;
})
);
resolve(response); resolve(response);
} else { } else {
reject(new Error('Failed to get response')); reject(new Error('Failed to get response'));
@@ -81,15 +92,22 @@ export const sendThemeUpdate = (updatedTheme: CustomTheme, saveTheme?: boolean,
}; };
}); });
Promise.all(imageDataPromises).then((imageData) => { Promise.all(imageDataPromises).then(async (imageData) => {
// Send the updated theme with image data to the content script for live preview or saving const themeData = {
...updatedTheme,
CustomImages: imageData,
};
if (saveTheme) {
themeData.coverImage = await blobToBase64(updatedTheme.coverImage as Blob);
} else {
themeData.coverImage = null;
}
browser.runtime.sendMessage({ browser.runtime.sendMessage({
type: 'currentTab', type: 'currentTab',
info: 'UpdateThemePreview', info: 'UpdateThemePreview',
body: { body: themeData,
...updatedTheme,
CustomImages: imageData,
},
save: saveTheme, save: saveTheme,
}); });
+19 -1
View File
@@ -55,9 +55,27 @@ function ThemeCreator() {
}; };
}); });
const coverImageBase64 = theme.coverImage;
let coverImageBlob = null;
if (coverImageBase64) {
const base64Index = coverImageBase64.indexOf(',') + 1;
const imageBase64 = coverImageBase64.substring(base64Index);
// Convert base64 to blob
const byteCharacters = atob(imageBase64);
const byteNumbers = new Uint8Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
coverImageBlob = new Blob([byteArray], { type: 'image/png' });
}
setTheme({ setTheme({
...theme, ...theme,
CustomImages, CustomImages,
coverImage: coverImageBlob
}); });
sendThemeUpdate({ sendThemeUpdate({
@@ -189,7 +207,7 @@ function ThemeCreator() {
theme.coverImage && ( theme.coverImage && (
<> <>
<div className="absolute z-20 w-full h-full transition-opacity opacity-0 pointer-events-none group-hover:opacity-100 bg-black/20"></div> <div className="absolute z-20 w-full h-full transition-opacity opacity-0 pointer-events-none group-hover:opacity-100 bg-black/20"></div>
<img src={URL.createObjectURL(theme.coverImage)} alt='Cover Image' className="absolute z-0 object-cover w-full h-full rounded" /> <img src={URL.createObjectURL(theme.coverImage as Blob)} alt='Cover Image' className="absolute z-0 object-cover w-full h-full rounded" />
</> </>
) )
} }
+1 -1
View File
@@ -7,7 +7,7 @@ export type CustomTheme = {
allowBackgrounds: boolean; allowBackgrounds: boolean;
CustomCSS: string; CustomCSS: string;
CustomImages: CustomImage[]; CustomImages: CustomImage[];
coverImage: Blob | null; coverImage: Blob | string | null;
isEditable: boolean; isEditable: boolean;
} }
+6 -1
View File
@@ -1,6 +1,7 @@
import browser from 'webextension-polyfill'; import browser from 'webextension-polyfill';
import localforage from 'localforage'; import localforage from 'localforage';
import { CustomTheme, ThemeList } from '../../../interface/types/CustomThemes'; import { CustomTheme, ThemeList } from '../../../interface/types/CustomThemes';
import { blobToBase64 } from '../../utils/blobToBase64';
export const getAvailableThemes = async (): Promise<ThemeList | {}> => { export const getAvailableThemes = async (): Promise<ThemeList | {}> => {
@@ -11,8 +12,12 @@ export const getAvailableThemes = async (): Promise<ThemeList | {}> => {
const themes = await Promise.all( const themes = await Promise.all(
themeIds.map(async (id) => { themeIds.map(async (id) => {
const theme = await localforage.getItem(id) as CustomTheme; const theme = await localforage.getItem(id) as CustomTheme;
console.log('CoverImage: ', theme.coverImage)
const { CustomImages, ...themeWithoutImages } = theme; const { CustomImages, ...themeWithoutImages } = theme;
return themeWithoutImages; return {
...themeWithoutImages,
coverImage: theme.coverImage ? await blobToBase64(theme.coverImage as Blob) : '',
};
}) })
); );
+1
View File
@@ -20,6 +20,7 @@ export const getTheme = async (themeId: string): Promise<CustomThemeBase64 | nul
return { return {
...theme, ...theme,
coverImage: theme.coverImage ? await blobToBase64(theme.coverImage as Blob) : null,
CustomImages, CustomImages,
}; };
} catch (error) { } catch (error) {
+1
View File
@@ -7,6 +7,7 @@ export const saveTheme = async (theme: CustomThemeBase64) => {
try { try {
const updatedTheme: CustomTheme = { const updatedTheme: CustomTheme = {
...theme, ...theme,
coverImage: theme.coverImage ? await fetch(theme.coverImage).then((res) => res.blob()) : null,
CustomImages: await Promise.all( CustomImages: await Promise.all(
theme.CustomImages.map(async (image) => ({ theme.CustomImages.map(async (image) => ({
id: image.id, id: image.id,