import * as React from 'react'; import {useEffect, useState} from 'react'; import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; import {ThemeProvider} from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; import Drawer from '@mui/material/Drawer'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import ChatBubbleOutlineIcon from '@mui/icons-material/ChatBubbleOutline'; import List from '@mui/material/List'; import Divider from '@mui/material/Divider'; import IconButton from '@mui/material/IconButton'; import MenuIcon from '@mui/icons-material/Menu'; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; import ListItemButton from "@mui/material/ListItemButton"; import SettingsIcon from "@mui/icons-material/Settings"; import AddIcon from "@mui/icons-material/Add"; import SubscribeDialog from "./SubscribeDialog"; import NotificationList from "./NotificationList"; import IconSubscribeSettings from "./IconSubscribeSettings"; import theme from "./theme"; import api from "../app/Api"; import repository from "../app/Repository"; import connectionManager from "../app/ConnectionManager"; import Subscriptions from "../app/Subscriptions"; const drawerWidth = 240; const NavSubscriptionList = (props) => { const subscriptions = props.subscriptions; return ( <> {subscriptions.map((id, subscription) => props.onSubscriptionClick(id)} />) } ); } const NavSubscriptionItem = (props) => { const subscription = props.subscription; return ( ); } const NavList = (props) => { const [subscribeDialogOpen, setSubscribeDialogOpen] = useState(false); const handleSubscribeSubmit = (subscription) => { setSubscribeDialogOpen(false); props.onSubscribeSubmit(subscription); } return ( <> setSubscribeDialogOpen(true)}> setSubscribeDialogOpen(false)} onSubmit={handleSubscribeSubmit} /> ); }; const ActionBar = (props) => { const title = (props.selectedSubscription !== null) ? props.selectedSubscription.shortUrl() : "ntfy"; return ( {title} {props.selectedSubscription !== null && } ); }; const Sidebar = (props) => { const navigationList = ; return ( <> {/* Mobile drawer; only shown if menu icon clicked (mobile open) and display is small */} {navigationList} {/* Big screen drawer; persistent, shown if screen is big */} {navigationList} ); }; const App = () => { console.log(`[App] Rendering main view`); const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false); const [subscriptions, setSubscriptions] = useState(new Subscriptions()); const [selectedSubscription, setSelectedSubscription] = useState(null); const handleNotification = (subscriptionId, notification) => { setSubscriptions(prev => { const newSubscription = prev.get(subscriptionId).addNotification(notification); return prev.update(newSubscription).clone(); }); }; const handleSubscribeSubmit = (subscription) => { console.log(`[App] New subscription: ${subscription.id}`); setSubscriptions(prev => prev.add(subscription).clone()); setSelectedSubscription(subscription); api.poll(subscription.baseUrl, subscription.topic) .then(messages => { setSubscriptions(prev => { const newSubscription = prev.get(subscription.id).addNotifications(messages); return prev.update(newSubscription).clone(); }); }); }; const handleDeleteNotification = (subscriptionId, notificationId) => { console.log(`[App] Deleting notification ${notificationId} from ${subscriptionId}`); setSubscriptions(prev => { const newSubscription = prev.get(subscriptionId).deleteNotification(notificationId); return prev.update(newSubscription).clone(); }); }; const handleDeleteAllNotifications = (subscriptionId) => { console.log(`[App] Deleting all notifications from ${subscriptionId}`); setSubscriptions(prev => { const newSubscription = prev.get(subscriptionId).deleteAllNotifications(); return prev.update(newSubscription).clone(); }); }; const handleUnsubscribe = (subscriptionId) => { console.log(`[App] Unsubscribing from ${subscriptionId}`); setSubscriptions(prev => { const newSubscriptions = prev.remove(subscriptionId).clone(); setSelectedSubscription(newSubscriptions.firstOrNull()); return newSubscriptions; }); }; useEffect(() => { setSubscriptions(repository.loadSubscriptions()); }, [/* initial render only */]); useEffect(() => { connectionManager.refresh(subscriptions, handleNotification); repository.saveSubscriptions(subscriptions); }, [subscriptions]); return ( setMobileDrawerOpen(!mobileDrawerOpen)} /> setMobileDrawerOpen(!mobileDrawerOpen)} onSubscriptionClick={(subscriptionId) => setSelectedSubscription(subscriptions.get(subscriptionId))} onSubscribeSubmit={handleSubscribeSubmit} /> theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900] }}> {selectedSubscription !== null && } ); } export default App;