import React, { useContext, useEffect, useRef, useState, VoidFunctionComponent } from 'react'; import useMenu from '../Hooks/useMenu'; import Alert from '../Components/Alert'; import Menu from '../Components/Menu'; import MenuItem from '../Components/Menu/Item'; import { AuthContext } from '../Context/AuthContext'; import useEcho from '../Hooks/useEcho'; import { Event, EventResponse } from '../Package/Models/ScheduledView'; import { View } from '../Package/Models/View'; import SolarCast from '../Package/Pages/SolarCast'; import Connect from './Connect'; import { useOnline } from '../Hooks/useOnline'; import usePrevious from '../Hooks/usePrevious'; import { Screen } from '../Package/Models/Screen'; import useFetch from '../Hooks/useFetch'; import { useVersion } from '../Hooks/useVersion'; import { AxiosError } from 'axios'; const Fetcher: VoidFunctionComponent = () => { // Use global state const { screen, subscribe, unsubscribe } = useEcho(); const { auth, setAuth } = useContext(AuthContext); const fetch = useFetch(); const prevAuth = usePrevious(auth); const prevScreen = usePrevious(screen); // App status const online = useOnline(); const version = useVersion('onbekend'); const mounted = useRef(false); // Content to be displayed: events and views const [views, setViews] = useState([]); const [events, setEvents] = useState[]>([]); const [guestMode, setGuestMode] = useState(false); const { menuOpen, mouseInteraction, setMouseInteraction, handleMouseMove } = useMenu(false); /** Timeout for the getContent function if the request fails. */ const retryTimerRef = useRef(null); const cancelRetryTimer = () => { retryTimerRef.current && clearTimeout(retryTimerRef.current); retryTimerRef.current = null; }; /** Get the content to display by the access token and screen. */ const getContent = async (screen: Screen) => { cancelRetryTimer(); try { const response = await fetch.get(`/api/screen/${screen.id}`); const { events, views, guestMode } = response.data; setGuestMode(guestMode); views && setViews(views); setEvents(events.map(event => ({ ...event, start: new Date(event.start.date), end: new Date(event.end.date), }))); // Refresh the schedule every 24h if the websocket did not refresh, to // prevent the schedule from ending after 7 days. retryTimerRef.current = setTimeout(() => getContent(screen), 1000 * 60 * 60 * 24); } catch (error) { const status = (error as AxiosError)?.response?.status; if (status !== 401) { retryTimerRef.current = setTimeout(() => getContent(screen), 5000); } if (status !== 429) { setViews([]); setEvents([]); } } }; const identify = async (stopTrying = false) => { cancelRetryTimer(); if (!auth) { logout(); return; } try { const response = await fetch.get(`/api/identify/${auth.deviceCode}`); const screen = response.data; subscribe(screen, () => getContent(screen)); } catch (error) { const status = (error as AxiosError)?.response?.status; if (!stopTrying && (status === 400 || status === 429)) { unsubscribe(() => identify(false)); retryTimerRef.current = setTimeout(() => identify(true), 10 * 60 * 1000); return; } logout(); } }; const logout = () => setAuth && setAuth(); const openScreenInBrowser = (screenId?: number) => window.electron?.open( new URL(screenId ? `/screens/${screenId}` : '/screens', window.electron?.url).href ); useEffect(() => { if (online && mounted.current) { if (screen) { getContent(screen); } else { identify(false); } } }, [online]); useEffect(() => { if (!prevAuth && auth) { identify(); } else if (prevAuth && !auth) { setViews([]); setEvents([]); unsubscribe(); } mounted.current = true; }, [auth]); useEffect(() => { if (screen && prevScreen?.id !== screen.id) { getContent(screen); } }, [screen]); return (
{ !auth && } openScreenInBrowser(screen?.id) }> { screen ? ( <> Verbonden met scherm { screen.name } ) : ( { auth ? 'Verbinding maken...' : 'Niet verbonden' } ) } setMouseInteraction(!mouseInteraction) }> Interactie { mouseInteraction ? 'uitzetten' : 'aanzetten' } window.electron.closeApp() }> Afsluiten { auth && ( Uitloggen ) }
Versie { version }
{ !online && (
Geen verbinding met internet
) }
); }; export default Fetcher;