import React, { Component } from 'react'; import { Typography, AppBar, Toolbar, IconButton, InputBase, Avatar, ListItemText, Divider, List, ListItemIcon, Hidden, Drawer, ListSubheader, ListItemAvatar, withStyles, Menu, MenuItem, ClickAwayListener, Badge, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Button, ListItem, Tooltip } from '@material-ui/core'; import MenuIcon from '@material-ui/icons/Menu'; import SearchIcon from '@material-ui/icons/Search'; import NotificationsIcon from '@material-ui/icons/Notifications'; import MailIcon from '@material-ui/icons/Mail'; import HomeIcon from '@material-ui/icons/Home'; import DomainIcon from '@material-ui/icons/Domain'; import PublicIcon from '@material-ui/icons/Public'; import GroupIcon from '@material-ui/icons/Group'; import SettingsIcon from '@material-ui/icons/Settings'; import InfoIcon from '@material-ui/icons/Info'; import CreateIcon from '@material-ui/icons/Create'; //import SupervisedUserCircleIcon from '@material-ui/icons/SupervisedUserCircle'; import ExitToAppIcon from '@material-ui/icons/ExitToApp'; import {styles} from './AppLayout.styles'; import { UAccount } from '../../types/Account'; import {LinkableListItem, LinkableIconButton, LinkableFab} from '../../interfaces/overrides'; import Mastodon from 'megalodon'; import { Notification } from '../../types/Notification'; import {sendNotificationRequest} from '../../utilities/notifications'; import {withSnackbar} from 'notistack'; import { getConfig, getUserDefaultBool } from '../../utilities/settings'; import { isDesktopApp, isDarwinApp } from '../../utilities/desktop'; import { Config } from '../../types/Config'; interface IAppLayoutState { acctMenuOpen: boolean; drawerOpenOnMobile: boolean; currentUser?: UAccount; notificationCount: number; logOutOpen: boolean; enableFederation?: boolean; brandName?: string; developerMode?: boolean; } export class AppLayout extends Component { client: Mastodon; streamListener: any; constructor(props: any) { super(props); this.client = new Mastodon(localStorage.getItem('access_token') as string, localStorage.getItem('baseurl') as string + "/api/v1"); this.state = { drawerOpenOnMobile: false, acctMenuOpen: false, notificationCount: 0, logOutOpen: false } this.toggleDrawerOnMobile = this.toggleDrawerOnMobile.bind(this); this.toggleAcctMenu = this.toggleAcctMenu.bind(this); this.clearBadge = this.clearBadge.bind(this); } componentDidMount() { let acct = localStorage.getItem('account'); if (acct) { this.setState({ currentUser: JSON.parse(acct) }); } else { this.client.get('/accounts/verify_credentials').then((resp: any) => { let data: UAccount = resp.data; this.setState({ currentUser: data }); }).catch((err: Error) => { this.props.enqueueSnackbar("Couldn't find profile info: " + err.name); console.error(err.message); }) } getConfig().then((result: any) => { if (result !== undefined) { let config: Config = result; this.setState({ enableFederation: config.federation.enablePublicTimeline, brandName: config.branding? config.branding.name: "Hyperspace", developerMode: config.developer }); } }) this.streamNotifications() } streamNotifications() { this.streamListener = this.client.stream('/streaming/user'); if (getUserDefaultBool('displayAllOnNotificationBadge')) { this.client.get('/notifications').then((resp: any) => { let notifArray = resp.data; this.setState({ notificationCount: notifArray.length }); }) } this.streamListener.on('notification', (notif: Notification) => { const notificationCount = this.state.notificationCount + 1; this.setState({ notificationCount }); if (!document.hasFocus()) { let primaryMessage = ""; let secondaryMessage = ""; switch(notif.type) { case "favourite": primaryMessage = (notif.account.display_name || "@" + notif.account.username) + " favorited your post."; if (notif.status) { const div = document.createElement('div'); div.innerHTML = notif.status.content; secondaryMessage = (div.textContent || div.innerText || "").slice(0, 100) + "..." } break; case "follow": primaryMessage = (notif.account.display_name || "@" + notif.account.username) + " is now following you."; break; case "mention": primaryMessage = (notif.account.display_name || "@" + notif.account.username) + " mentioned you in a post."; if (notif.status) { const div = document.createElement('div'); div.innerHTML = notif.status.content; secondaryMessage = (div.textContent || div.innerText || "").slice(0, 100) + "..." } break; case "reblog": primaryMessage = (notif.account.display_name || "@" + notif.account.username) + " reblogged your post."; if (notif.status) { const div = document.createElement('div'); div.innerHTML = notif.status.content; secondaryMessage = (div.textContent || div.innerText || "").slice(0, 100) + "..." } break; } sendNotificationRequest(primaryMessage, secondaryMessage); } }); } toggleAcctMenu() { this.setState({ acctMenuOpen: !this.state.acctMenuOpen }); } toggleDrawerOnMobile() { this.setState({ drawerOpenOnMobile: !this.state.drawerOpenOnMobile }) } toggleLogOutDialog() { this.setState({ logOutOpen: !this.state.logOutOpen }); } searchForQuery(what: string) { window.location.href = isDesktopApp()? "hyperspace://hyperspace/app/index.html#/search?query=" + what: "/#/search?query=" + what; window.location.reload; } logOutAndRestart() { let loginData = localStorage.getItem("login"); if (loginData) { let items = ["login", "account", "baseurl", "access_token"]; items.forEach((entry) => { localStorage.removeItem(entry); }) window.location.reload(); } } clearBadge() { if (!getUserDefaultBool('displayAllOnNotificationBadge')) { this.setState({ notificationCount: 0 }); } } titlebar() { const { classes } = this.props; if (isDarwinApp()) { return (
{this.state.brandName? this.state.brandName: "Hyperspace"} {this.state.developerMode? "(beta)": null}
); } else if (this.state.developerMode || process.env.NODE_ENV === "development") { return (
Careful: you're running in developer mode.
); } } appDrawer() { const { classes } = this.props; return (
{/* */} this.toggleLogOutDialog()}>
Timelines { this.state.enableFederation? : }
Account 0? this.state.notificationCount: ""} color="secondary">
More
); } render() { const { classes } = this.props; return (
{this.titlebar()} {this.state.brandName? this.state.brandName: "Hyperspace"}
{ if (event.keyCode === 13) { this.searchForQuery(event.currentTarget.value); } }} />
0? this.state.notificationCount: ""} color="secondary">
Edit profile {/* Switch account */} this.toggleLogOutDialog()}>Log out
this.toggleLogOutDialog()} > Log out of {this.state.brandName? this.state.brandName: "Hyperspace"} You'll need to remove {this.state.brandName? this.state.brandName: "Hyperspace"} from your list of authorized apps and log in again if you want to use {this.state.brandName? this.state.brandName: "Hyperspace"}.
); } } export default withStyles(styles)(withSnackbar(AppLayout));