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));