Compare commits
2 Commits
latest
...
2849ed3bb2
Author | SHA1 | Date | |
---|---|---|---|
2849ed3bb2 | |||
f1c1b0c6c6 |
30
App.tsx
30
App.tsx
@@ -94,7 +94,8 @@ const App: React.FC = () => {
|
|||||||
const updateWallpaper = () => {
|
const updateWallpaper = () => {
|
||||||
const availableWallpapers = allWallpapers.filter(w => config.backgroundUrls.includes(w.url || w.base64));
|
const availableWallpapers = allWallpapers.filter(w => config.backgroundUrls.includes(w.url || w.base64));
|
||||||
if (availableWallpapers.length > 0) {
|
if (availableWallpapers.length > 0) {
|
||||||
const currentIndex = availableWallpapers.findIndex(w => (w.url || w.base64) === wallpaperState.current);
|
const currentWallpaperFromState = allWallpapers.find(w => w.name === wallpaperState.current);
|
||||||
|
const currentIndex = currentWallpaperFromState ? availableWallpapers.findIndex(w => w.name === currentWallpaperFromState.name) : -1;
|
||||||
const nextIndex = (currentIndex + 1) % availableWallpapers.length;
|
const nextIndex = (currentIndex + 1) % availableWallpapers.length;
|
||||||
const newWallpaper = availableWallpapers[nextIndex];
|
const newWallpaper = availableWallpapers[nextIndex];
|
||||||
const newWallpaperUrl = newWallpaper.url || newWallpaper.base64;
|
const newWallpaperUrl = newWallpaper.url || newWallpaper.base64;
|
||||||
@@ -102,24 +103,20 @@ const App: React.FC = () => {
|
|||||||
localStorage.setItem('wallpaperState', JSON.stringify({ current: newWallpaper.name, lastChanged: new Date().toISOString() }));
|
localStorage.setItem('wallpaperState', JSON.stringify({ current: newWallpaper.name, lastChanged: new Date().toISOString() }));
|
||||||
} else {
|
} else {
|
||||||
setCurrentWallpaper('');
|
setCurrentWallpaper('');
|
||||||
|
localStorage.removeItem('wallpaperState');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Date.now() - lastChanged > frequency) {
|
const currentWallpaperDetails = allWallpapers.find(w => w.name === wallpaperState.current);
|
||||||
|
const isCurrentWallpaperValid = currentWallpaperDetails && config.backgroundUrls.includes(currentWallpaperDetails.url || currentWallpaperDetails.base64 || '');
|
||||||
|
|
||||||
|
if (!isCurrentWallpaperValid || Date.now() - lastChanged > frequency) {
|
||||||
updateWallpaper();
|
updateWallpaper();
|
||||||
|
} else if (currentWallpaperDetails) {
|
||||||
|
setCurrentWallpaper(currentWallpaperDetails.url || currentWallpaperDetails.base64 || '');
|
||||||
} else {
|
} else {
|
||||||
const currentWallpaperName = wallpaperState.current;
|
// Fallback for when there's no valid wallpaper state
|
||||||
const wallpaper = allWallpapers.find(w => w.name === currentWallpaperName);
|
updateWallpaper();
|
||||||
if (wallpaper) {
|
|
||||||
setCurrentWallpaper(wallpaper.url || wallpaper.base64 || '');
|
|
||||||
} else {
|
|
||||||
const firstWallpaperUrl = config.backgroundUrls[0] || '';
|
|
||||||
const firstWallpaper = allWallpapers.find(w => (w.url || w.base64) === firstWallpaperUrl);
|
|
||||||
setCurrentWallpaper(firstWallpaperUrl);
|
|
||||||
if (firstWallpaper) {
|
|
||||||
localStorage.setItem('wallpaperState', JSON.stringify({ current: firstWallpaper.name, lastChanged: new Date().toISOString() }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [config.backgroundUrls, config.wallpaperFrequency, allWallpapers]);
|
}, [config.backgroundUrls, config.wallpaperFrequency, allWallpapers]);
|
||||||
|
|
||||||
@@ -133,6 +130,10 @@ const App: React.FC = () => {
|
|||||||
setIsConfigModalOpen(false);
|
setIsConfigModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleWallpaperChange = (newConfig: Partial<Config>) => {
|
||||||
|
setConfig(prev => ({ ...prev, ...newConfig }));
|
||||||
|
};
|
||||||
|
|
||||||
const handleSaveWebsite = (website: Partial<Website>) => {
|
const handleSaveWebsite = (website: Partial<Website>) => {
|
||||||
if (editingWebsite) {
|
if (editingWebsite) {
|
||||||
const newCategories = categories.map(category => ({
|
const newCategories = categories.map(category => ({
|
||||||
@@ -341,6 +342,7 @@ const App: React.FC = () => {
|
|||||||
currentConfig={config}
|
currentConfig={config}
|
||||||
onClose={() => setIsConfigModalOpen(false)}
|
onClose={() => setIsConfigModalOpen(false)}
|
||||||
onSave={handleSaveConfig}
|
onSave={handleSaveConfig}
|
||||||
|
onWallpaperChange={handleWallpaperChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
34
README.md
34
README.md
@@ -17,6 +17,38 @@
|
|||||||
`npm run dev`
|
`npm run dev`
|
||||||
|
|
||||||
## to-do
|
## to-do
|
||||||
* [] Multiple wallpapers
|
* [x] Multiple Wallpapers
|
||||||
* [x] Remake icons
|
* [x] Remake icons
|
||||||
* [] Increase offline compatibility
|
* [] Increase offline compatibility
|
||||||
|
* Use chrome.storage.local for wallpapers
|
||||||
|
* Use chrome.storage.local for some logos
|
||||||
|
* Some logos have CORS enabled, we can add `"<all_urls>"` to the manifest.json file and cache them on storage local
|
||||||
|
* Dynamic Weather Widget
|
||||||
|
* A box with information about the current weather, with manual entry on the location
|
||||||
|
* Display current temperature, weather condition (e.g., "Sunny," "Cloudy"), and a corresponding icon
|
||||||
|
* Optionally, show a 3-day forecast when clicked or hovered
|
||||||
|
* Search Bar Widget
|
||||||
|
* Positioned to the right or left side of the clock, display a nice search bar
|
||||||
|
* Behaviour:
|
||||||
|
* When not in focus, it could be highly transparent with just a faint border and a search icon.
|
||||||
|
* When clicked, it would smoothly expand and become slightly more opaque, with a soft glow around the border (similar to the existing ones)
|
||||||
|
* Config to allow changing the default search engine
|
||||||
|
* Draggable & Resizable Grid System
|
||||||
|
* Allow users to drag and drop all widgets (Clock, Website Tiles, Weather, Title, etc.) into any position on a grid
|
||||||
|
* Notes / Scratchpad Widget
|
||||||
|
* A simple text area that saves its content to local storage automatically.
|
||||||
|
* Maybe some extra formatting (bold, italic, increase font size, etc).
|
||||||
|
* Theme-ing
|
||||||
|
* A Light/Dark Mode toggle
|
||||||
|
* Custom Accent Colors
|
||||||
|
* Selection of 6-8 accent colors that are guaranteed to look good with both Light and Dark themes
|
||||||
|
* Define CSS variables for the accent color
|
||||||
|
* Dynamic Wallpaper-Based Theming
|
||||||
|
* Automatically adapt the UI's accent color to match the current wallpaper
|
||||||
|
* Minimal feel toggle
|
||||||
|
* Disable title & subtitle and search widget
|
||||||
|
* Tiles become small stylish lines
|
||||||
|
|
||||||
|
From a technical side:
|
||||||
|
* Refactor everything :(
|
||||||
|
* Add small nginx demo (with docker)
|
@@ -10,9 +10,10 @@ interface ConfigurationModalProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSave: (config: any) => void;
|
onSave: (config: any) => void;
|
||||||
currentConfig: any;
|
currentConfig: any;
|
||||||
|
onWallpaperChange: (newConfig: Partial<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave, currentConfig }) => {
|
const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave, currentConfig, onWallpaperChange }) => {
|
||||||
const [config, setConfig] = useState({
|
const [config, setConfig] = useState({
|
||||||
...currentConfig,
|
...currentConfig,
|
||||||
titleSize: currentConfig.titleSize || 'medium',
|
titleSize: currentConfig.titleSize || 'medium',
|
||||||
@@ -47,6 +48,7 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave
|
|||||||
const [userWallpapers, setUserWallpapers] = useState<Wallpaper[]>([]);
|
const [userWallpapers, setUserWallpapers] = useState<Wallpaper[]>([]);
|
||||||
const menuRef = useRef<HTMLDivElement>(null);
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const isSaving = useRef(false);
|
||||||
const [isVisible, setIsVisible] = useState(false);
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -64,6 +66,14 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave
|
|||||||
return () => clearTimeout(timer);
|
return () => clearTimeout(timer);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (!isSaving.current) {
|
||||||
|
onWallpaperChange({ backgroundUrls: currentConfig.backgroundUrls });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setIsVisible(false);
|
setIsVisible(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -90,6 +100,10 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onWallpaperChange({ backgroundUrls: config.backgroundUrls });
|
||||||
|
}, [config.backgroundUrls]);
|
||||||
|
|
||||||
const handleClockToggleChange = (checked: boolean) => {
|
const handleClockToggleChange = (checked: boolean) => {
|
||||||
setConfig({ ...config, clock: { ...config.clock, enabled: checked } });
|
setConfig({ ...config, clock: { ...config.clock, enabled: checked } });
|
||||||
};
|
};
|
||||||
@@ -201,7 +215,10 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave
|
|||||||
localStorage.setItem('userWallpapers', JSON.stringify(updatedUserWallpapers));
|
localStorage.setItem('userWallpapers', JSON.stringify(updatedUserWallpapers));
|
||||||
|
|
||||||
const newBackgroundUrls = config.backgroundUrls.filter((url: string) => url !== wallpaperIdentifier);
|
const newBackgroundUrls = config.backgroundUrls.filter((url: string) => url !== wallpaperIdentifier);
|
||||||
setConfig({ ...config, backgroundUrls: newBackgroundUrls });
|
|
||||||
|
const newConfig = { ...config, backgroundUrls: newBackgroundUrls };
|
||||||
|
setConfig(newConfig);
|
||||||
|
onWallpaperChange({ backgroundUrls: newBackgroundUrls });
|
||||||
};
|
};
|
||||||
|
|
||||||
const allWallpapers = [...baseWallpapers, ...userWallpapers];
|
const allWallpapers = [...baseWallpapers, ...userWallpapers];
|
||||||
@@ -629,7 +646,7 @@ const ConfigurationModal: React.FC<ConfigurationModalProps> = ({ onClose, onSave
|
|||||||
</div>
|
</div>
|
||||||
<div className="p-8 border-t border-white/10">
|
<div className="p-8 border-t border-white/10">
|
||||||
<div className="flex justify-end gap-4">
|
<div className="flex justify-end gap-4">
|
||||||
<button onClick={() => onSave(config)} className="bg-green-500 hover:bg-green-400 text-white font-bold py-2 px-6 rounded-lg">
|
<button onClick={() => { isSaving.current = true; onSave(config); }} className="bg-green-500 hover:bg-green-400 text-white font-bold py-2 px-6 rounded-lg">
|
||||||
Save & Close
|
Save & Close
|
||||||
</button>
|
</button>
|
||||||
<button onClick={handleClose} className="bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-6 rounded-lg">
|
<button onClick={handleClose} className="bg-gray-600 hover:bg-gray-500 text-white font-bold py-2 px-6 rounded-lg">
|
||||||
|
Reference in New Issue
Block a user