From b7e7c24727ce329c7978f45f53790493a254fc8f Mon Sep 17 00:00:00 2001 From: SethBurkart123 Date: Sun, 7 Apr 2024 15:05:11 +1000 Subject: [PATCH] add custom cover images to themes. --- src/interface/components/ThemeCover.tsx | 9 +++---- src/interface/hooks/ThemeManagment.ts | 32 ++++++++++++++++++----- src/interface/pages/ThemeCreator.tsx | 22 ++++++++++++++-- src/interface/types/CustomThemes.ts | 2 +- src/seqta/ui/themes/getAvailableThemes.ts | 7 ++++- src/seqta/ui/themes/getTheme.ts | 1 + src/seqta/ui/themes/saveTheme.ts | 1 + 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/interface/components/ThemeCover.tsx b/src/interface/components/ThemeCover.tsx index bc086970..9363173c 100644 --- a/src/interface/components/ThemeCover.tsx +++ b/src/interface/components/ThemeCover.tsx @@ -54,16 +54,13 @@ export const ThemeCover: React.FC = ({ }
- {/* Render theme cover image or placeholder */} - {/* {theme.CustomImages.length > 0 ? ( + {theme.coverImage && {theme.name} - ) : ( -
- )} */} + }
{theme.name}
diff --git a/src/interface/hooks/ThemeManagment.ts b/src/interface/hooks/ThemeManagment.ts index 425c54e3..4c1bbcee 100644 --- a/src/interface/hooks/ThemeManagment.ts +++ b/src/interface/hooks/ThemeManagment.ts @@ -30,8 +30,19 @@ export const listThemes = async (): Promise => { browser.runtime.sendMessage({ type: 'currentTab', info: 'ListThemes' - }).then((response) => { + }).then(async (response) => { if (response) { + // convert the response themes coverImage to a bloburl + response.themes = await Promise.all( + response.themes.map(async (theme: Omit) => { + if (theme.coverImage) { + const blob = await fetch(theme.coverImage as string).then((res) => res.blob()); + theme.coverImage = URL.createObjectURL(blob); + } + return theme; + }) + ); + resolve(response); } else { reject(new Error('Failed to get response')); @@ -81,15 +92,22 @@ export const sendThemeUpdate = (updatedTheme: CustomTheme, saveTheme?: boolean, }; }); - Promise.all(imageDataPromises).then((imageData) => { - // Send the updated theme with image data to the content script for live preview or saving + Promise.all(imageDataPromises).then(async (imageData) => { + const themeData = { + ...updatedTheme, + CustomImages: imageData, + }; + + if (saveTheme) { + themeData.coverImage = await blobToBase64(updatedTheme.coverImage as Blob); + } else { + themeData.coverImage = null; + } + browser.runtime.sendMessage({ type: 'currentTab', info: 'UpdateThemePreview', - body: { - ...updatedTheme, - CustomImages: imageData, - }, + body: themeData, save: saveTheme, }); diff --git a/src/interface/pages/ThemeCreator.tsx b/src/interface/pages/ThemeCreator.tsx index 4293a6ed..1237fded 100644 --- a/src/interface/pages/ThemeCreator.tsx +++ b/src/interface/pages/ThemeCreator.tsx @@ -33,7 +33,7 @@ function ThemeCreator() { } }) as CustomThemeBase64 | undefined; - if (theme) { + if (theme) { // base64toblob to convert it to a blob url const CustomImages = theme.CustomImages.map((image) => { const base64Index = image.url.indexOf(',') + 1; @@ -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({ ...theme, CustomImages, + coverImage: coverImageBlob }); sendThemeUpdate({ @@ -189,7 +207,7 @@ function ThemeCreator() { theme.coverImage && ( <>
- Cover Image + Cover Image ) } diff --git a/src/interface/types/CustomThemes.ts b/src/interface/types/CustomThemes.ts index b88c6771..88f8dccc 100644 --- a/src/interface/types/CustomThemes.ts +++ b/src/interface/types/CustomThemes.ts @@ -7,7 +7,7 @@ export type CustomTheme = { allowBackgrounds: boolean; CustomCSS: string; CustomImages: CustomImage[]; - coverImage: Blob | null; + coverImage: Blob | string | null; isEditable: boolean; } diff --git a/src/seqta/ui/themes/getAvailableThemes.ts b/src/seqta/ui/themes/getAvailableThemes.ts index 8f1bb2d3..82978d47 100644 --- a/src/seqta/ui/themes/getAvailableThemes.ts +++ b/src/seqta/ui/themes/getAvailableThemes.ts @@ -1,6 +1,7 @@ import browser from 'webextension-polyfill'; import localforage from 'localforage'; import { CustomTheme, ThemeList } from '../../../interface/types/CustomThemes'; +import { blobToBase64 } from '../../utils/blobToBase64'; export const getAvailableThemes = async (): Promise => { @@ -11,8 +12,12 @@ export const getAvailableThemes = async (): Promise => { const themes = await Promise.all( themeIds.map(async (id) => { const theme = await localforage.getItem(id) as CustomTheme; + console.log('CoverImage: ', theme.coverImage) const { CustomImages, ...themeWithoutImages } = theme; - return themeWithoutImages; + return { + ...themeWithoutImages, + coverImage: theme.coverImage ? await blobToBase64(theme.coverImage as Blob) : '', + }; }) ); diff --git a/src/seqta/ui/themes/getTheme.ts b/src/seqta/ui/themes/getTheme.ts index 6f07c098..ffd24c01 100644 --- a/src/seqta/ui/themes/getTheme.ts +++ b/src/seqta/ui/themes/getTheme.ts @@ -20,6 +20,7 @@ export const getTheme = async (themeId: string): Promise { try { const updatedTheme: CustomTheme = { ...theme, + coverImage: theme.coverImage ? await fetch(theme.coverImage).then((res) => res.blob()) : null, CustomImages: await Promise.all( theme.CustomImages.map(async (image) => ({ id: image.id,