fixing wallpaper
This commit is contained in:
24
App.tsx
24
App.tsx
@@ -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>
|
||||||
|
|||||||
@@ -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' && (
|
||||||
|
|||||||
@@ -10,16 +10,20 @@ 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[] =
|
||||||
|
JSON.parse(localStorage.getItem('userWallpapers') || '[]');
|
||||||
|
const foundInUser = storedUserWallpapers.find((w: WallpaperType) => w.name === name);
|
||||||
if (foundInUser) {
|
if (foundInUser) {
|
||||||
try {
|
try {
|
||||||
const wallpaperData = await getWallpaperFromChromeStorageLocal(name);
|
const wallpaperData = await getWallpaperFromChromeStorageLocal(name);
|
||||||
@@ -32,13 +36,15 @@ const getWallpaperUrlByName = async (name: string): Promise<string | undefined>
|
|||||||
return undefined;
|
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;
|
||||||
}
|
}
|
||||||
setCurrentWallpaperIndex(currentIndex);
|
resolvedIndex = (resolvedIndex + 1) % wallpaperNames.length;
|
||||||
const wallpaperName = wallpaperNames[currentIndex];
|
}
|
||||||
const url = await getWallpaperUrlByName(wallpaperName);
|
|
||||||
setImageUrl(url);
|
const nextLastChange = shouldRotate
|
||||||
|
? new Date().toISOString()
|
||||||
|
: 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;
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user