feat: enhance login page with random theme and background features

- Added RandomThemeApplier to apply a random theme on login.
- Introduced RandomBackground component for setting a random background from presets.
- Updated GlobalKeyboardShortcuts import in RootLayout for consistent keyboard shortcut handling.
- Refactored BackgroundContext to include cycleBackground functionality for dynamic background changes.
- Removed deprecated useBackgroundCycle hook to streamline background management.
This commit is contained in:
Julien Froidefond
2025-10-03 17:11:02 +02:00
parent aae35aa811
commit 48e3822696
6 changed files with 119 additions and 58 deletions

View File

@@ -2,11 +2,14 @@
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { useUserPreferences } from './UserPreferencesContext';
import { PRESET_BACKGROUNDS } from '@/lib/ui-config';
import { PRESET_BACKGROUNDS, BACKGROUND_NAMES, TOAST_ICONS, getNextBackground } from '@/lib/ui-config';
import { useSession } from 'next-auth/react';
import { useToast } from '@/components/ui/Toast';
interface BackgroundContextType {
backgroundImage: string | undefined;
setBackgroundImage: (image: string | undefined) => void;
cycleBackground: () => void;
}
const BackgroundContext = createContext<BackgroundContextType | undefined>(undefined);
@@ -16,7 +19,9 @@ interface BackgroundProviderProps {
}
export function BackgroundProvider({ children }: BackgroundProviderProps) {
const { preferences } = useUserPreferences();
const { preferences, updateViewPreferences } = useUserPreferences();
const { data: session } = useSession();
const { showToast } = useToast();
const [backgroundImage, setBackgroundImageState] = useState<string | undefined>(
preferences?.viewPreferences?.backgroundImage
);
@@ -33,9 +38,10 @@ export function BackgroundProvider({ children }: BackgroundProviderProps) {
setMounted(true);
}, []);
// Sync with preferences
// Sync with preferences (only for authenticated users)
useEffect(() => {
if (preferences?.viewPreferences?.backgroundImage !== backgroundImage) {
// Only sync if user is authenticated
if (session?.user?.id && preferences?.viewPreferences?.backgroundImage !== backgroundImage) {
setBackgroundImageState(preferences?.viewPreferences?.backgroundImage);
}
if (preferences?.viewPreferences?.backgroundBlur !== backgroundBlur) {
@@ -44,7 +50,7 @@ export function BackgroundProvider({ children }: BackgroundProviderProps) {
if (preferences?.viewPreferences?.backgroundOpacity !== backgroundOpacity) {
setBackgroundOpacityState(preferences?.viewPreferences?.backgroundOpacity || 100);
}
}, [preferences?.viewPreferences?.backgroundImage, preferences?.viewPreferences?.backgroundBlur, preferences?.viewPreferences?.backgroundOpacity, backgroundImage, backgroundBlur, backgroundOpacity]);
}, [preferences?.viewPreferences?.backgroundImage, preferences?.viewPreferences?.backgroundBlur, preferences?.viewPreferences?.backgroundOpacity, backgroundImage, backgroundBlur, backgroundOpacity, session?.user?.id]);
// Apply background image to document body
useEffect(() => {
@@ -58,6 +64,7 @@ export function BackgroundProvider({ children }: BackgroundProviderProps) {
}
if (backgroundImage) {
console.log('Creating background element for:', backgroundImage);
// Créer un élément div pour l'image de fond avec les effets
const backgroundElement = document.createElement('div');
backgroundElement.id = 'custom-background';
@@ -76,11 +83,15 @@ export function BackgroundProvider({ children }: BackgroundProviderProps) {
// Trouver le preset correspondant
const preset = PRESET_BACKGROUNDS.find(p => p.id === backgroundImage);
if (preset) {
backgroundElement.style.backgroundImage = preset.preview;
// Appliquer le gradient directement
backgroundElement.style.background = preset.preview;
// Ajouter une classe pour identifier le type de background
backgroundElement.className = `preset-background preset-${preset.id}`;
}
} else {
// Appliquer l'URL d'image personnalisée
backgroundElement.style.backgroundImage = `url(${backgroundImage})`;
backgroundElement.className = 'custom-background';
}
// Appliquer les propriétés communes
@@ -104,8 +115,27 @@ export function BackgroundProvider({ children }: BackgroundProviderProps) {
setBackgroundImageState(image);
};
const cycleBackground = () => {
const currentBackground = backgroundImage; // Utiliser le state local au lieu des préférences
const customImages = preferences?.viewPreferences?.customImages || [];
const nextBackground = getNextBackground(currentBackground || 'none', customImages);
const newBackgroundImage = nextBackground === 'none' ? undefined : nextBackground;
setBackgroundImageState(newBackgroundImage);
// Sauvegarder seulement si l'utilisateur est authentifié
if (session?.user?.id) {
updateViewPreferences({ backgroundImage: newBackgroundImage });
}
// Afficher le toast avec le nom du background
const backgroundName = BACKGROUND_NAMES[nextBackground] || 'Image personnalisée';
showToast(`Background: ${backgroundName}`, 2000, TOAST_ICONS.background);
};
return (
<BackgroundContext.Provider value={{ backgroundImage, setBackgroundImage }}>
<BackgroundContext.Provider value={{ backgroundImage, setBackgroundImage, cycleBackground }}>
{children}
</BackgroundContext.Provider>
);