import * as React from 'react'; import {useEffect, useState} from 'react'; import Box from '@mui/material/Box'; import {ThemeProvider} from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; import Toolbar from '@mui/material/Toolbar'; import Notifications from "./Notifications"; import theme from "./theme"; import connectionManager from "../app/ConnectionManager"; import Navigation from "./Navigation"; import ActionBar from "./ActionBar"; import notifier from "../app/Notifier"; import Preferences from "./Preferences"; import {useLiveQuery} from "dexie-react-hooks"; import subscriptionManager from "../app/SubscriptionManager"; import userManager from "../app/UserManager"; import {BrowserRouter, Route, Routes, useNavigate, useParams} from "react-router-dom"; import {expandUrl, subscriptionRoute} from "../app/utils"; // TODO support unsubscribed routes // TODO "copy url" toast // TODO "copy link url" button // TODO races when two tabs are open // TODO investigate service workers const App = () => { return ( ); } const Content = () => { const subscriptions = useLiveQuery(() => subscriptionManager.all()); // const context = { subscriptions }; return ( } /> } /> } /> } /> } /> ) }; const AllSubscriptions = (props) => { return ( ); } const SingleSubscription = (props) => { const params = useParams(); const [selected] = (props.subscriptions || []).filter(s => { return (params.baseUrl && expandUrl(params.baseUrl).includes(s.baseUrl) && params.topic === s.topic) || (window.location.origin === s.baseUrl && params.topic === s.topic) }); return ( ); } const PrefLayout = (props) => { return ( ); } const Layout = (props) => { const subscriptions = props.subscriptions; // May be null/undefined const selected = props.selected; // May be null/undefined const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false); const [notificationsGranted, setNotificationsGranted] = useState(notifier.granted()); const users = useLiveQuery(() => userManager.all()); const newNotificationsCount = subscriptions?.reduce((prev, cur) => prev + cur.new, 0) || 0; useConnectionListeners(); useEffect(() => connectionManager.refresh(subscriptions, users), [subscriptions, users]); useEffect(() => updateTitle(newNotificationsCount), [newNotificationsCount]); return ( setMobileDrawerOpen(!mobileDrawerOpen)} /> setMobileDrawerOpen(!mobileDrawerOpen)} onNotificationGranted={setNotificationsGranted} />
{props.children}
); } const Main = (props) => { return ( theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900] }} > {props.children} ); }; const useConnectionListeners = () => { const navigate = useNavigate(); useEffect(() => { const handleNotification = async (subscriptionId, notification) => { const added = await subscriptionManager.addNotification(subscriptionId, notification); if (added) { const defaultClickAction = (subscription) => navigate(subscriptionRoute(subscription)); await notifier.notify(subscriptionId, notification, defaultClickAction) } }; connectionManager.registerStateListener(subscriptionManager.updateState); connectionManager.registerNotificationListener(handleNotification); return () => { connectionManager.resetStateListener(); connectionManager.resetNotificationListener(); } }, // We have to disable dep checking for "navigate". This is fine, it never changes. // eslint-disable-next-line []); }; const updateTitle = (newNotificationsCount) => { document.title = (newNotificationsCount > 0) ? `(${newNotificationsCount}) ntfy web` : "ntfy web"; } export default App;