fixing wallpaper
All checks were successful
Build and Release to Staging / Build Vision Start (push) Successful in 31s
Build and Release to Staging / Build Vision Start Image (push) Successful in 2m54s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 1m10s

This commit is contained in:
2026-07-02 19:22:19 -03:00
parent c397e77c01
commit ddf2f2a416
4 changed files with 115 additions and 37 deletions

24
App.tsx
View File

@@ -31,6 +31,7 @@ const App: React.FC = () => {
const [editingCategory, setEditingCategory] = useState<Category | null>(null); const [editingCategory, setEditingCategory] = useState<Category | null>(null);
const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false); const [isCategoryModalOpen, setIsCategoryModalOpen] = useState(false);
const [config, setConfig] = useState<Config>(() => ConfigurationService.loadConfig()); const [config, setConfig] = useState<Config>(() => ConfigurationService.loadConfig());
const [wallpaperVersion, setWallpaperVersion] = useState(0);
useEffect(() => { useEffect(() => {
ConfigurationService.saveConfig(config); ConfigurationService.saveConfig(config);
@@ -53,6 +54,27 @@ const App: React.FC = () => {
setConfig(prev => ({ ...prev, ...newConfig })); setConfig(prev => ({ ...prev, ...newConfig }));
}; };
const handleNextWallpaper = () => {
const names = config.currentWallpapers;
if (names.length === 0) return;
try {
const state = JSON.parse(localStorage.getItem('wallpaperState') || '{}');
const current = typeof state.currentIndex === 'number' ? state.currentIndex : 0;
const safeCurrent = current < 0 || current >= names.length ? 0 : current;
const nextIndex = (safeCurrent + 1) % names.length;
localStorage.setItem(
'wallpaperState',
JSON.stringify({
lastWallpaperChange: new Date().toISOString(),
currentIndex: nextIndex,
}),
);
} catch (error) {
console.error('Error advancing wallpaper state', error);
}
setWallpaperVersion(v => v + 1);
};
const handleSaveWebsite = (website: Partial<Website>) => { const handleSaveWebsite = (website: Partial<Website>) => {
if (editingWebsite) { if (editingWebsite) {
const idToUpdate = website.id ?? editingWebsite.id; const idToUpdate = website.id ?? editingWebsite.id;
@@ -185,6 +207,7 @@ const App: React.FC = () => {
brightness={config.wallpaperBrightness} brightness={config.wallpaperBrightness}
opacity={config.wallpaperOpacity} opacity={config.wallpaperOpacity}
wallpaperFrequency={config.wallpaperFrequency} wallpaperFrequency={config.wallpaperFrequency}
wallpaperVersion={wallpaperVersion}
/> />
<EditButton isEditing={isEditing} onClick={() => setIsEditing(!isEditing)} /> <EditButton isEditing={isEditing} onClick={() => setIsEditing(!isEditing)} />
<ConfigurationButton onClick={() => setIsConfigModalOpen(true)} /> <ConfigurationButton onClick={() => setIsConfigModalOpen(true)} />
@@ -258,6 +281,7 @@ const App: React.FC = () => {
onClose={() => setIsConfigModalOpen(false)} onClose={() => setIsConfigModalOpen(false)}
onSave={handleSaveConfig} onSave={handleSaveConfig}
onWallpaperChange={handleWallpaperChange} onWallpaperChange={handleWallpaperChange}
onNextWallpaper={handleNextWallpaper}
/> />
)} )}
</main> </main>

View File

@@ -13,6 +13,7 @@ interface ConfigurationModalProps {
onSave: (config: Config) => void; onSave: (config: Config) => void;
currentConfig: Config; currentConfig: Config;
onWallpaperChange: (newConfig: Partial<Config>) => void; onWallpaperChange: (newConfig: Partial<Config>) => void;
onNextWallpaper: () => void;
} }
const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({
@@ -20,6 +21,7 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({
onSave, onSave,
currentConfig, currentConfig,
onWallpaperChange, onWallpaperChange,
onNextWallpaper,
}) => { }) => {
const [config, setConfig] = useState<Config>(currentConfig); const [config, setConfig] = useState<Config>(currentConfig);
const [activeTab, setActiveTab] = useState('general'); const [activeTab, setActiveTab] = useState('general');
@@ -175,6 +177,7 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({
onAddWallpaper={handleAddWallpaper} onAddWallpaper={handleAddWallpaper}
onAddWallpaperFile={handleAddWallpaperFile} onAddWallpaperFile={handleAddWallpaperFile}
onDeleteWallpaper={handleDeleteWallpaper} onDeleteWallpaper={handleDeleteWallpaper}
onNextWallpaper={onNextWallpaper}
/> />
)} )}
{activeTab === 'clock' && ( {activeTab === 'clock' && (

View File

@@ -10,35 +10,41 @@ interface WallpaperProps {
brightness: number; brightness: number;
opacity: number; opacity: number;
wallpaperFrequency: string; wallpaperFrequency: string;
wallpaperVersion: number;
} }
const getWallpaperUrlByName = async (name: string): Promise<string | undefined> => { const getWallpaperUrlByName = async (name: string): Promise<string | undefined> => {
if (!name) return undefined;
const foundInBase = baseWallpapers.find((w: WallpaperType) => w.name === name); const foundInBase = baseWallpapers.find((w: WallpaperType) => w.name === name);
if (foundInBase) { if (foundInBase) {
return foundInBase.url || foundInBase.base64; return foundInBase.url || foundInBase.base64;
} }
const userWallpapers: WallpaperType[] = JSON.parse(localStorage.getItem('userWallpapers') || '[]'); try {
const foundInUser = userWallpapers.find((w: WallpaperType) => w.name === name); const storedUserWallpapers: WallpaperType[] =
if (foundInUser) { JSON.parse(localStorage.getItem('userWallpapers') || '[]');
try { const foundInUser = storedUserWallpapers.find((w: WallpaperType) => w.name === name);
const wallpaperData = await getWallpaperFromChromeStorageLocal(name); if (foundInUser) {
if (wallpaperData && wallpaperData.startsWith('http')) { try {
return wallpaperData; const wallpaperData = await getWallpaperFromChromeStorageLocal(name);
if (wallpaperData && wallpaperData.startsWith('http')) {
return wallpaperData;
}
return wallpaperData || undefined;
} catch (error) {
console.error('Error getting wallpaper from chrome storage', error);
return undefined;
} }
return wallpaperData || undefined;
} catch (error) {
console.error('Error getting wallpaper from chrome storage', error);
return undefined;
} }
} catch (error) {
console.error('Error reading userWallpapers from localStorage', error);
} }
return undefined; return undefined;
}; };
const Wallpaper: React.FC<WallpaperProps> = ({ wallpaperNames, blur, brightness, opacity, wallpaperFrequency }) => { const Wallpaper: React.FC<WallpaperProps> = ({ wallpaperNames, blur, brightness, opacity, wallpaperFrequency, wallpaperVersion }) => {
const [imageUrl, setImageUrl] = useState<string | undefined>(undefined); const [imageUrl, setImageUrl] = useState<string | undefined>(undefined);
const [currentWallpaperIndex, setCurrentWallpaperIndex] = useState<number>(0);
// Helper to parse wallpaperFrequency string to ms // Helper to parse wallpaperFrequency string to ms
const parseFrequencyToMs = (freq: string): number => { const parseFrequencyToMs = (freq: string): number => {
@@ -54,36 +60,61 @@ const Wallpaper: React.FC<WallpaperProps> = ({ wallpaperNames, blur, brightness,
useEffect(() => { useEffect(() => {
const updateWallpaper = async () => { const updateWallpaper = async () => {
if (wallpaperNames.length === 0) return; if (wallpaperNames.length === 0) {
// Read wallpaperState from localStorage setImageUrl(undefined);
localStorage.setItem(
'wallpaperState',
JSON.stringify({ lastWallpaperChange: new Date().toISOString(), currentIndex: 0 }),
);
return;
}
const wallpaperState = JSON.parse(localStorage.getItem('wallpaperState') || '{}'); const wallpaperState = JSON.parse(localStorage.getItem('wallpaperState') || '{}');
const lastChange = wallpaperState.lastWallpaperChange ? new Date(wallpaperState.lastWallpaperChange).getTime() : 0; const lastChange = wallpaperState.lastWallpaperChange
? new Date(wallpaperState.lastWallpaperChange).getTime()
: 0;
const now = Date.now(); const now = Date.now();
const freqMs = parseFrequencyToMs(wallpaperFrequency); const freqMs = parseFrequencyToMs(wallpaperFrequency);
let currentIndex = typeof wallpaperState.currentIndex === 'number' ? wallpaperState.currentIndex : 0;
// If enough time has passed, pick a new wallpaper let storedIndex =
if (now - lastChange >= freqMs) { typeof wallpaperState.currentIndex === 'number' ? wallpaperState.currentIndex : 0;
currentIndex = (currentIndex + 1) % wallpaperNames.length; if (storedIndex < 0 || storedIndex >= wallpaperNames.length) storedIndex = 0;
localStorage.setItem('wallpaperState', JSON.stringify({
lastWallpaperChange: new Date().toISOString(), const shouldRotate = now - lastChange >= freqMs;
currentIndex let resolvedIndex = shouldRotate
})); ? (storedIndex + 1) % wallpaperNames.length
} else { : storedIndex;
// Keep currentIndex in sync with localStorage if not updating
localStorage.setItem('wallpaperState', JSON.stringify({ const tried = new Set<number>();
lastWallpaperChange: wallpaperState.lastWallpaperChange || new Date().toISOString(), let resolvedUrl: string | undefined;
currentIndex
})); for (let i = 0; i < wallpaperNames.length; i++) {
if (tried.has(resolvedIndex)) break;
tried.add(resolvedIndex);
const url = await getWallpaperUrlByName(wallpaperNames[resolvedIndex]);
if (url) {
resolvedUrl = url;
break;
}
resolvedIndex = (resolvedIndex + 1) % wallpaperNames.length;
} }
setCurrentWallpaperIndex(currentIndex);
const wallpaperName = wallpaperNames[currentIndex]; const nextLastChange = shouldRotate
const url = await getWallpaperUrlByName(wallpaperName); ? new Date().toISOString()
setImageUrl(url); : wallpaperState.lastWallpaperChange || new Date().toISOString();
localStorage.setItem(
'wallpaperState',
JSON.stringify({
lastWallpaperChange: nextLastChange,
currentIndex: resolvedIndex,
}),
);
setImageUrl(resolvedUrl);
}; };
updateWallpaper(); updateWallpaper();
// No timer, just run on render/dependency change }, [wallpaperNames, wallpaperFrequency, wallpaperVersion]);
}, [wallpaperNames, wallpaperFrequency]);
if (!imageUrl) return null; if (!imageUrl) return null;

View File

@@ -11,6 +11,7 @@ interface ThemeTabProps {
onAddWallpaper: (name: string, url: string) => Promise<void>; onAddWallpaper: (name: string, url: string) => Promise<void>;
onAddWallpaperFile: (file: File) => Promise<void>; onAddWallpaperFile: (file: File) => Promise<void>;
onDeleteWallpaper: (wallpaper: Wallpaper) => Promise<void>; onDeleteWallpaper: (wallpaper: Wallpaper) => Promise<void>;
onNextWallpaper: () => void;
} }
const ThemeTab: React.FC<ThemeTabProps> = ({ const ThemeTab: React.FC<ThemeTabProps> = ({
@@ -22,6 +23,7 @@ const ThemeTab: React.FC<ThemeTabProps> = ({
onAddWallpaper, onAddWallpaper,
onAddWallpaperFile, onAddWallpaperFile,
onDeleteWallpaper, onDeleteWallpaper,
onNextWallpaper,
}) => { }) => {
const [newWallpaperName, setNewWallpaperName] = useState(''); const [newWallpaperName, setNewWallpaperName] = useState('');
const [newWallpaperUrl, setNewWallpaperUrl] = useState(''); const [newWallpaperUrl, setNewWallpaperUrl] = useState('');
@@ -177,7 +179,7 @@ const ThemeTab: React.FC<ThemeTabProps> = ({
/> />
<button <button
onClick={handleAddWallpaper} onClick={handleAddWallpaper}
className="bg-cyan-500 hover:bg-cyan-400 text-white font-bold py-2 px-4 rounded-lg" className="bg-cyan-500 hover:bg-cyan-400 active:scale-95 text-white font-bold py-2 px-4 rounded-lg transition-all duration-150 ease-ios"
> >
Add Add
</button> </button>
@@ -221,6 +223,24 @@ const ThemeTab: React.FC<ThemeTabProps> = ({
</div> </div>
</> </>
)} )}
<div className="flex justify-center pt-2">
<button
onClick={onNextWallpaper}
disabled={config.currentWallpapers.length === 0}
className="flex items-center gap-2 bg-black/25 backdrop-blur-md border border-white/10 hover:bg-white/25 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed text-white text-sm font-semibold py-2 px-4 rounded-xl transition-all duration-150 ease-ios"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path d="M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zM4.5 7.5a.5.5 0 0 1 .5-.5h5.379L8.646 5.354a.5.5 0 1 1 .708-.708l2.5 2.5a.5.5 0 0 1 0 .708l-2.5 2.5a.5.5 0 0 1-.708-.708L10.379 8H5a.5.5 0 0 1-.5-.5z" />
</svg>
Next Wallpaper
</button>
</div>
</div> </div>
); );
}; };