more robust theme selector

This commit is contained in:
SethBurkart123
2023-11-02 17:11:02 +11:00
parent 46e86b9643
commit 8508169cd7
7 changed files with 246 additions and 109 deletions
+25 -94
View File
@@ -1,5 +1,6 @@
import { ChangeEvent, useEffect, useState } from "react";
import { downloadPresetBackground, openDB, readAllData, writeData } from "../hooks/BackgroundDataLoader";
import presetBackgrounds from "../assets/presetBackgrounds";
import "./BackgroundSelector.css";
// Custom Types and Interfaces
@@ -8,7 +9,7 @@ export interface Background {
type: string;
blob: Blob;
url?: string;
previewUrl?: string; // New field
previewUrl?: string;
isPreset?: boolean;
isDownloaded?: boolean;
}
@@ -20,76 +21,6 @@ export default function BackgroundSelector() {
const [downloadProgress, setDownloadProgress] = useState<Record<string, number>>({});
const [isEditMode, setIsEditMode] = useState<boolean>(false);
const presetBackgrounds = [
// Images
{
id: 'image-preset-1',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-1-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-2',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-2-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-3',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-3-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-4',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-4-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-5',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-5-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-6',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-6-thumb.jpg',
isPreset: true
},
{
id: 'image-preset-7',
type: 'image',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7.jpg',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/images/background-7-thumb.jpg',
isPreset: true
},
// Videos
{
id: 'video-preset-1',
type: 'video',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animated-1.mp4',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-1-thumb.mp4',
isPreset: true
},
{
id: 'video-preset-2',
type: 'video',
url: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2.mp4',
previewUrl: 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/backgrounds/videos/animation-2-thumb.mp4',
isPreset: true
}
];
const handleFileChange = async (e: ChangeEvent<HTMLInputElement>): Promise<void> => {
const file = e.target.files?.[0];
if (!file) return;
@@ -112,30 +43,30 @@ export default function BackgroundSelector() {
setBackgrounds(dataWithUrls);
};
const handlePresetClick = async (bg: Background): Promise<void> => {
if (bg.isPreset) {
// Check if already exists in IndexedDB or is currently being downloaded
const existingBackgrounds = await readAllData();
const alreadyExists = existingBackgrounds.some(ebg => ebg.id === bg.id) || downloadProgress[bg.id] !== undefined;
if (!alreadyExists) {
setDownloadProgress(prev => ({ ...prev, [bg.id]: 0 }));
const downloadedBg = await downloadPresetBackground(bg, progress => {
console.log(`${bg}, ${progress}`);
setDownloadProgress(prev => ({ ...prev, [bg.id]: progress }));
});
setDownloadProgress(prev => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { [bg.id]: _, ...rest } = prev;
return rest;
});
await writeData(downloadedBg.id, downloadedBg.type, downloadedBg.blob);
setBackgrounds(prev => [...prev, downloadedBg]);
setDownloadedPresetIds(prev => [...prev, downloadedBg.id]);
const handlePresetClick = async (bg: Background): Promise<void> => {
if (bg.isPreset) {
// Check if already exists in IndexedDB or is currently being downloaded
const existingBackgrounds = await readAllData();
const alreadyExists = existingBackgrounds.some(ebg => ebg.id === bg.id) || downloadProgress[bg.id] !== undefined;
if (!alreadyExists) {
setDownloadProgress(prev => ({ ...prev, [bg.id]: 0 }));
const downloadedBg = await downloadPresetBackground(bg, progress => {
console.log(`${bg}, ${progress}`);
setDownloadProgress(prev => ({ ...prev, [bg.id]: progress }));
});
setDownloadProgress(prev => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { [bg.id]: _, ...rest } = prev;
return rest;
});
await writeData(downloadedBg.id, downloadedBg.type, downloadedBg.blob);
setBackgrounds(prev => [...prev, downloadedBg]);
setDownloadedPresetIds(prev => [...prev, downloadedBg.id]);
}
selectBackground(bg.id);
}
selectBackground(bg.id);
}
};
};
const selectBackground = (fileId: string): void => {
setSelectedBackground(fileId);
+117 -6
View File
@@ -1,6 +1,35 @@
const downloadTheme = (themeName: string, themeURL: string) => {
import { useEffect, useState } from "react";
import themesList from '../assets/themes';
interface Theme {
name: string;
url: string;
isDownloaded: boolean;
isLoading: boolean;
coverImage: JSX.Element;
}
interface ThemeList {
themes: string[];
}
const downloadTheme = async (themeName: string, themeURL: string) => {
// send message to the background script
chrome.runtime.sendMessage({
const response = await chrome.runtime.sendMessage({
type: 'currentTab',
info: 'DownloadTheme',
body: {
themeName: themeName,
themeURL: themeURL
}
});
console.log("Response: ", response);
}
const setTheme = async (themeName: string, themeURL: string) => {
// send message to the background script
const response = await chrome.runtime.sendMessage({
type: 'currentTab',
info: 'SetTheme',
body: {
@@ -8,11 +37,93 @@ const downloadTheme = (themeName: string, themeURL: string) => {
themeURL: themeURL
}
});
console.log("Response: ", response);
}
const listThemes = async () => {
// send message to the background script
const response: ThemeList = await chrome.runtime.sendMessage({
type: 'currentTab',
info: 'ListThemes',
body: {}
});
// response.themes is an array of strings that are identical to the theme names that we loop over. Use this list to see which ones are downloaded and which ones need to see the download icon.
console.log("Response: ", response);
return response.themes;
}
const ThemeSelector = () => {
const [themes, setThemes] = useState<Theme[]>([]);
useEffect(() => {
const initializeThemes = async () => {
const downloaded = await listThemes();
const initializedThemes = themesList.map(theme => ({
...theme,
isDownloaded: downloaded.includes(theme.name),
isLoading: false
}));
setThemes(initializedThemes);
};
initializeThemes();
}, []);
const handleThemeAction = async (themeName: string, themeURL: string) => {
// Find the theme in the state and set its loading property to true
setThemes(prevThemes => prevThemes.map(theme =>
theme.name === themeName ? { ...theme, isLoading: true } : theme
));
// Call the appropriate method based on whether the theme is downloaded
const theme = themes.find(t => t.name === themeName);
if (theme && theme.isDownloaded) {
await setTheme(themeName, themeURL);
} else {
await downloadTheme(themeName, themeURL);
// After downloading, update the theme to be marked as downloaded
setThemes(prevThemes => prevThemes.map(t =>
t.name === themeName ? { ...t, isDownloaded: true } : t
));
}
// Once the action is complete, set the theme's loading property to false
setThemes(prevThemes => prevThemes.map(theme =>
theme.name === themeName ? { ...theme, isLoading: false } : theme
));
};
export default function ThemeSelector() {
return (
<button onClick={() => downloadTheme('Dark', 'https://raw.githubusercontent.com/SethBurkart123/BetterSEQTA-Themes/main/themes/test.json')}>Dark</button>
)
}
<div className="flex flex-col gap-4">
{themes.map((theme) => (
<button
key={theme.name}
className={`relative w-full h-16 flex justify-center items-center rounded-md overflow-hidden ${theme.isDownloaded ? 'bg-blue-500' : 'bg-green-500'} ${theme.isLoading ? 'opacity-50 cursor-not-allowed' : ''}`}
onClick={() => handleThemeAction(theme.name, theme.url)}
disabled={theme.isLoading}
>
{/* Position the cover image absolutely so that it doesn't affect the button's content layout */}
<div className="absolute inset-0 z-0">
{theme.coverImage}
</div>
{/* Content */}
{theme.isLoading ? (
<div className="z-10 inline-block w-6 h-6 border-4 border-current rounded-full animate-spin border-t-transparent" role="status">
<span className="sr-only">Loading...</span>
</div>
) : (
<span className="z-10 text-lg font-bold text-white">{theme.name}</span>
)}
</button>
))}
</div>
);
};
export default ThemeSelector;