diff --git a/src/frontend/apps/impress/src/core/AppProvider.tsx b/src/frontend/apps/impress/src/core/AppProvider.tsx index 596217c2..9c6df080 100644 --- a/src/frontend/apps/impress/src/core/AppProvider.tsx +++ b/src/frontend/apps/impress/src/core/AppProvider.tsx @@ -1,8 +1,10 @@ import { CunninghamProvider } from '@openfun/cunningham-react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { useEffect } from 'react'; import { useCunninghamTheme } from '@/cunningham'; import '@/i18n/initI18n'; +import { useResponsiveStore } from '@/stores/'; import { Auth } from './auth/'; @@ -25,6 +27,15 @@ const queryClient = new QueryClient({ export function AppProvider({ children }: { children: React.ReactNode }) { const { theme } = useCunninghamTheme(); + const initializeResizeListener = useResponsiveStore( + (state) => state.initializeResizeListener, + ); + + useEffect(() => { + const cleanupResizeListener = initializeResizeListener(); + return cleanupResizeListener; + }, [initializeResizeListener]); + return ( diff --git a/src/frontend/apps/impress/src/stores/index.ts b/src/frontend/apps/impress/src/stores/index.ts new file mode 100644 index 00000000..ca763337 --- /dev/null +++ b/src/frontend/apps/impress/src/stores/index.ts @@ -0,0 +1 @@ +export * from './useResponsiveStore'; diff --git a/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx new file mode 100644 index 00000000..1ca49370 --- /dev/null +++ b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx @@ -0,0 +1,61 @@ +import { create } from 'zustand'; + +export type ScreenSize = 'small-mobile' | 'mobile' | 'tablet' | 'desktop'; + +export interface UseResponsiveStore { + isMobile: boolean; + isSmallMobile: boolean; + screenSize: ScreenSize; + screenWidth: number; + setScreenSize: (size: ScreenSize) => void; + initializeResizeListener: () => () => void; +} + +const initialState = { + isMobile: false, + isSmallMobile: false, + screenSize: 'desktop' as ScreenSize, + screenWidth: 0, +}; + +export const useResponsiveStore = create((set) => ({ + isMobile: initialState.isMobile, + isSmallMobile: initialState.isSmallMobile, + screenSize: initialState.screenSize, + screenWidth: initialState.screenWidth, + setScreenSize: (size: ScreenSize) => set(() => ({ screenSize: size })), + initializeResizeListener: () => { + const resizeHandler = () => { + const width = window.innerWidth; + if (width < 560) { + set({ + screenSize: 'small-mobile', + isMobile: true, + isSmallMobile: true, + }); + } else if (width < 768) { + set({ screenSize: 'mobile', isMobile: true, isSmallMobile: false }); + } else if (width >= 768 && width < 1024) { + set({ screenSize: 'tablet', isMobile: false, isSmallMobile: false }); + } else { + set({ screenSize: 'desktop', isMobile: false, isSmallMobile: false }); + } + + set({ screenWidth: width }); + }; + + const debouncedResizeHandler = () => { + setTimeout(() => { + resizeHandler(); + }, 300); + }; + + window.addEventListener('resize', debouncedResizeHandler); + + resizeHandler(); + + return () => { + window.removeEventListener('resize', debouncedResizeHandler); + }; + }, +}));