diff --git a/README.md b/README.md index b9ed90e..ae66f86 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ npm run dev * [x] Multiple Wallpapers * [x] Remake icons * [/] Increase offline compatibility (might not be possible) - - [x] Use chrome.storage.local for user wallpapers -- this one is + - [x] Use chrome.storage.local for uploaded wallpaper files; remote wallpapers stay as URLs - [ ] Use chrome.storage.local for some logos -- a bit hard - Some logos have CORS enabled, we can add `""` to the manifest.json file and cache them on storage local * Dynamic Weather Widget diff --git a/components/Wallpaper.tsx b/components/Wallpaper.tsx index cd4082e..003cf12 100644 --- a/components/Wallpaper.tsx +++ b/components/Wallpaper.tsx @@ -43,16 +43,14 @@ const getWallpaperUrlByName = async (name: string): Promise JSON.parse(localStorage.getItem('userWallpapers') || '[]'); const foundInUser = storedUserWallpapers.find((w: WallpaperType) => w.name === name); if (foundInUser) { - try { - const wallpaperData = await getWallpaperFromChromeStorageLocal(name); - if (wallpaperData && wallpaperData.startsWith('http')) { - resolved = wallpaperData; - } else { - resolved = wallpaperData || undefined; + resolved = foundInUser.url || foundInUser.base64; + if (!resolved) { + try { + resolved = (await getWallpaperFromChromeStorageLocal(name)) || undefined; + } catch (error) { + console.error('Error getting wallpaper from chrome storage', error); + resolved = undefined; } - } catch (error) { - console.error('Error getting wallpaper from chrome storage', error); - resolved = undefined; } } } catch (error) { diff --git a/components/WebsiteTile.tsx b/components/WebsiteTile.tsx index c90e63a..e1397c3 100644 --- a/components/WebsiteTile.tsx +++ b/components/WebsiteTile.tsx @@ -1,5 +1,6 @@ -import React, { memo, useState } from 'react'; +import React, { memo, useEffect, useState } from 'react'; import { Website } from '../types'; +import { cacheWebsiteIcon, getCachedWebsiteIcon, removeCachedWebsiteIcon } from './utils/iconService'; interface WebsiteTileProps { website: Website; @@ -52,6 +53,46 @@ const getIconLoadingPixelSize = (size: string | undefined): number => { const WebsiteTile: React.FC = ({ website, isEditing, onEdit, onMove, tileSize }) => { const [isLoading, setIsLoading] = useState(false); + const [iconSource, setIconSource] = useState(null); + const [usingCachedIcon, setUsingCachedIcon] = useState(false); + + useEffect(() => { + let cancelled = false; + + setIconSource(null); + setUsingCachedIcon(false); + + const loadIcon = async () => { + const cachedIcon = await getCachedWebsiteIcon(website.icon); + if (cancelled) return; + + if (cachedIcon) { + setIconSource(cachedIcon); + setUsingCachedIcon(cachedIcon !== website.icon); + return; + } + + setIconSource(website.icon); + const newlyCachedIcon = await cacheWebsiteIcon(website.icon); + if (!cancelled && newlyCachedIcon) { + setIconSource(newlyCachedIcon); + setUsingCachedIcon(newlyCachedIcon !== website.icon); + } + }; + + void loadIcon(); + + return () => { + cancelled = true; + }; + }, [website.icon]); + + const handleIconError = () => { + if (!usingCachedIcon) return; + setIconSource(website.icon); + setUsingCachedIcon(false); + void removeCachedWebsiteIcon(website.icon); + }; const handleClick = (e: React.MouseEvent) => { if (isEditing) { @@ -84,7 +125,14 @@ const WebsiteTile: React.FC = ({ website, isEditing, onEdit, o )}
- {`${website.name} + {iconSource && ( + {`${website.name} + )}
{website.name} diff --git a/components/configuration/ThemeTab.tsx b/components/configuration/ThemeTab.tsx index 33223bb..ae90a9f 100644 --- a/components/configuration/ThemeTab.tsx +++ b/components/configuration/ThemeTab.tsx @@ -62,7 +62,11 @@ const ThemeTab: React.FC = ({ setNewWallpaperName(''); setNewWallpaperUrl(''); } catch (error) { - alert('Error adding wallpaper. Please check the URL and try again.'); + alert( + error instanceof Error + ? error.message + : 'Error adding wallpaper. Please check the URL and try again.', + ); console.error(error); } }; @@ -160,105 +164,103 @@ const ThemeTab: React.FC = ({ {config.wallpaperOpacity}%
- {chromeStorageAvailable && ( - <> -
-

User Wallpapers

-
- {userWallpapers.map((wallpaper) => ( -
+

User Wallpapers

+
+ {userWallpapers.map((wallpaper) => ( +
+ {wallpaper.name} + -
- ))} -
-
-
-

Add New Wallpaper

-
- setNewWallpaperName(e.target.value)} - className="liquid-input p-2.5" - /> -
- setNewWallpaperUrl(e.target.value)} - className="liquid-input p-2.5" - /> - -
-
- -
+ +
+ ))} +
+
+
+

Add New Wallpaper

+
+ setNewWallpaperName(e.target.value)} + className="liquid-input p-2.5" + /> +
+ setNewWallpaperUrl(e.target.value)} + className="liquid-input p-2.5" + /> +
- - )} + {chromeStorageAvailable && ( +
+ +
+ )} +
+