From 32f9940ea2ef88bdb06ce722aab939da2d6ac372 Mon Sep 17 00:00:00 2001 From: Marquis Kurt Date: Sat, 21 Sep 2019 22:13:25 -0400 Subject: [PATCH] Set up basic UI for server blocking Signed-off-by: Marquis Kurt --- .prettierrc | 4 + package-lock.json | 8 +- package.json | 1 + src/App.styles.tsx | 27 +- src/App.tsx | 176 +-- src/components/AppLayout/AppLayout.styles.tsx | 129 +- src/components/AppLayout/AppLayout.tsx | 833 ++++++----- src/components/AppLayout/index.tsx | 10 +- .../Attachment/Attachment.styles.tsx | 19 +- src/components/Attachment/Attachment.tsx | 212 +-- src/components/Attachment/index.tsx | 8 +- .../ComposeMediaAttachment.styles.tsx | 21 +- .../ComposeMediaAttachment.tsx | 147 +- .../ComposeMediaAttachment/index.tsx | 8 +- src/components/EmojiPicker/index.tsx | 50 +- src/components/Post/Post.styles.tsx | 47 +- src/components/Post/Post.tsx | 1273 ++++++++++------- src/components/Post/PostShareMenu.tsx | 21 +- src/components/Post/index.tsx | 10 +- src/components/ThemePreview/ThemePreview.tsx | 119 +- src/components/ThemePreview/index.tsx | 4 +- src/index.tsx | 54 +- src/interfaces/overrides.tsx | 106 +- src/pages/About.tsx | 775 ++++++---- src/pages/Blocked.tsx | 47 + src/pages/Compose.styles.tsx | 49 +- src/pages/Compose.tsx | 1079 +++++++------- src/pages/Conversation.tsx | 233 +-- src/pages/Home.tsx | 372 ++--- src/pages/Local.tsx | 373 ++--- src/pages/Messages.tsx | 207 +-- src/pages/Missingno.tsx | 45 +- src/pages/Notifications.tsx | 644 +++++---- src/pages/PageLayout.styles.tsx | 189 +-- src/pages/ProfilePage.tsx | 808 ++++++----- src/pages/Public.tsx | 371 ++--- src/pages/Recommendations.tsx | 523 ++++--- src/pages/Search.tsx | 549 +++---- src/pages/Settings.tsx | 434 ++++-- src/pages/Welcome.tsx | 1099 ++++++++------ src/pages/WelcomePage.styles.tsx | 111 +- src/pages/You.tsx | 443 +++--- src/types/Account.tsx | 54 +- src/types/Attachment.tsx | 18 +- src/types/Card.tsx | 26 +- src/types/Config.tsx | 52 +- src/types/Context.tsx | 8 +- src/types/Emojis.tsx | 14 +- src/types/Field.tsx | 8 +- src/types/HyperspaceTheme.tsx | 231 +-- src/types/Instance.tsx | 22 +- src/types/Mention.tsx | 10 +- src/types/Notification.tsx | 12 +- src/types/Poll.tsx | 34 +- src/types/Relationship.tsx | 22 +- src/types/Search.tsx | 8 +- src/types/SessionData.tsx | 10 +- src/types/Status.tsx | 70 +- src/types/Tag.tsx | 6 +- src/types/Visibility.tsx | 2 +- src/utilities/accounts.tsx | 37 +- src/utilities/appbar.tsx | 4 +- src/utilities/desktop.tsx | 16 +- src/utilities/emojis.tsx | 75 +- src/utilities/login.tsx | 69 +- src/utilities/notifications.tsx | 54 +- src/utilities/settings.tsx | 159 +- src/utilities/themes.tsx | 109 +- 68 files changed, 7334 insertions(+), 5434 deletions(-) create mode 100644 .prettierrc create mode 100644 src/pages/Blocked.tsx diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b0987a6 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "bracketSpacing": true, + "tabWidth": 4 +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2676737..bd7af84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "hyperspace", - "version": "1.0.0-beta6", + "version": "1.0.0-beta7", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -17778,6 +17778,12 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "prettier": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", + "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "dev": true + }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", diff --git a/package.json b/package.json index 72ea036..3ba1682 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "megalodon": "^0.6.4", "moment": "^2.24.0", "notistack": "^0.5.1", + "prettier": "^1.18.2", "query-string": "^6.8.2", "react": "^16.8.6", "react-dom": "^16.8.6", diff --git a/src/App.styles.tsx b/src/App.styles.tsx index c379a4f..53c33d5 100644 --- a/src/App.styles.tsx +++ b/src/App.styles.tsx @@ -1,21 +1,24 @@ import { Theme, createStyles } from "@material-ui/core"; -import { isDarwinApp } from './utilities/desktop'; +import { isDarwinApp } from "./utilities/desktop"; -export const styles = (theme: Theme) => createStyles({ +export const styles = (theme: Theme) => + createStyles({ root: { - width: '100%', - display: 'flex', - height: '100%', - minHeight: '100vh', - backgroundColor: isDarwinApp()? "transparent": theme.palette.background.default, + width: "100%", + display: "flex", + height: "100%", + minHeight: "100vh", + backgroundColor: isDarwinApp() + ? "transparent" + : theme.palette.background.default }, content: { marginTop: 72, flexGrow: 1, padding: theme.spacing.unit * 3, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up("md")]: { marginLeft: 250, - marginTop: 88, - }, - }, - }); \ No newline at end of file + marginTop: 88 + } + } + }); diff --git a/src/App.tsx b/src/App.tsx index c1991d9..0155cef 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,94 +1,110 @@ -import React, { Component } from 'react'; -import {MuiThemeProvider, CssBaseline, withStyles } from '@material-ui/core'; -import { setHyperspaceTheme, darkMode } from './utilities/themes'; -import AppLayout from './components/AppLayout'; -import {styles} from './App.styles'; -import {Route} from 'react-router-dom'; -import AboutPage from './pages/About'; -import Settings from './pages/Settings'; -import { getUserDefaultBool, getUserDefaultTheme } from './utilities/settings'; -import ProfilePage from './pages/ProfilePage'; -import HomePage from './pages/Home'; -import LocalPage from './pages/Local'; -import PublicPage from './pages/Public'; -import Conversation from './pages/Conversation'; -import NotificationsPage from './pages/Notifications'; -import SearchPage from './pages/Search'; -import Composer from './pages/Compose'; -import WelcomePage from './pages/Welcome'; -import MessagesPage from './pages/Messages'; -import RecommendationsPage from './pages/Recommendations'; -import Missingno from './pages/Missingno'; -import You from './pages/You'; -import {withSnackbar} from 'notistack'; -import {PrivateRoute} from './interfaces/overrides'; -import { userLoggedIn } from './utilities/accounts'; -import { isDarwinApp } from './utilities/desktop'; +import React, { Component } from "react"; +import { MuiThemeProvider, CssBaseline, withStyles } from "@material-ui/core"; +import { setHyperspaceTheme, darkMode } from "./utilities/themes"; +import AppLayout from "./components/AppLayout"; +import { styles } from "./App.styles"; +import { Route } from "react-router-dom"; +import AboutPage from "./pages/About"; +import Settings from "./pages/Settings"; +import { getUserDefaultBool, getUserDefaultTheme } from "./utilities/settings"; +import ProfilePage from "./pages/ProfilePage"; +import HomePage from "./pages/Home"; +import LocalPage from "./pages/Local"; +import PublicPage from "./pages/Public"; +import Conversation from "./pages/Conversation"; +import NotificationsPage from "./pages/Notifications"; +import SearchPage from "./pages/Search"; +import Composer from "./pages/Compose"; +import WelcomePage from "./pages/Welcome"; +import MessagesPage from "./pages/Messages"; +import RecommendationsPage from "./pages/Recommendations"; +import Missingno from "./pages/Missingno"; +import You from "./pages/You"; +import Blocked from "./pages/Blocked"; +import { withSnackbar } from "notistack"; +import { PrivateRoute } from "./interfaces/overrides"; +import { userLoggedIn } from "./utilities/accounts"; +import { isDarwinApp } from "./utilities/desktop"; let theme = setHyperspaceTheme(getUserDefaultTheme()); class App extends Component { + offline: any; - offline: any; + constructor(props: any) { + super(props); - constructor(props: any) { - super(props); - - this.state = { - theme: theme + this.state = { + theme: theme + }; } - } - componentWillMount() { - let newTheme = darkMode(this.state.theme, getUserDefaultBool('darkModeEnabled')); - this.setState({ theme: newTheme }); - } - - componentDidMount() { - this.removeBodyBackground() - } - - componentDidUpdate() { - this.removeBodyBackground() - } - - removeBodyBackground() { - if (isDarwinApp()) { - document.body.style.backgroundColor = "transparent"; - console.log("Changed!") - console.log(`New color: ${document.body.style.backgroundColor}`) + componentWillMount() { + let newTheme = darkMode( + this.state.theme, + getUserDefaultBool("darkModeEnabled") + ); + this.setState({ theme: newTheme }); } - } - render() { - const { classes } = this.props; + componentDidMount() { + this.removeBodyBackground(); + } - this.removeBodyBackground() - - return ( - - - -
- { userLoggedIn()? : null} - - - - - - - - - - - - - - -
+ componentDidUpdate() { + this.removeBodyBackground(); + } -
- ); - } + removeBodyBackground() { + if (isDarwinApp()) { + document.body.style.backgroundColor = "transparent"; + console.log("Changed!"); + console.log(`New color: ${document.body.style.backgroundColor}`); + } + } + + render() { + const { classes } = this.props; + + this.removeBodyBackground(); + + return ( + + + +
+ {userLoggedIn() ? : null} + + + + + + + + + + + + + + + + +
+
+ ); + } } export default withStyles(styles)(withSnackbar(App)); diff --git a/src/components/AppLayout/AppLayout.styles.tsx b/src/components/AppLayout/AppLayout.styles.tsx index 7c4d125..56c56df 100644 --- a/src/components/AppLayout/AppLayout.styles.tsx +++ b/src/components/AppLayout/AppLayout.styles.tsx @@ -1,32 +1,35 @@ import { Theme, createStyles } from "@material-ui/core"; import { darken } from "@material-ui/core/styles/colorManipulator"; -import { isDarwinApp } from '../../utilities/desktop'; +import { isDarwinApp } from "../../utilities/desktop"; import { fade } from "@material-ui/core/styles/colorManipulator"; -export const styles = (theme: Theme) => createStyles({ +export const styles = (theme: Theme) => + createStyles({ root: { - width: '100%', - display: 'flex', + width: "100%", + display: "flex" }, stickyArea: { - position: 'fixed', - width: '100%', + position: "fixed", + width: "100%", top: 0, left: 0, - zIndex: 1000, + zIndex: 1000 }, titleBarRoot: { top: 0, left: 0, height: 24, - width: '100%', - backgroundColor: isDarwinApp()? theme.palette.primary.main: theme.palette.primary.dark, - textAlign: 'center', + width: "100%", + backgroundColor: isDarwinApp() + ? theme.palette.primary.main + : theme.palette.primary.dark, + textAlign: "center", zIndex: 1000, - verticalAlign: 'middle', - WebkitUserSelect: 'none', - WebkitAppRegion: "drag", + verticalAlign: "middle", + WebkitUserSelect: "none", + WebkitAppRegion: "drag" }, titleBarText: { color: theme.palette.common.white, @@ -36,83 +39,83 @@ export const styles = (theme: Theme) => createStyles({ }, appBar: { zIndex: 1000, - backgroundImage: isDarwinApp()? `linear-gradient(${theme.palette.primary.main}, ${theme.palette.primary.dark})`: undefined, + backgroundImage: isDarwinApp() + ? `linear-gradient(${theme.palette.primary.main}, ${theme.palette.primary.dark})` + : undefined, backgroundColor: theme.palette.primary.main, borderBottomColor: darken(theme.palette.primary.dark, 0.2), borderBottomWidth: 1, - borderBottomStyle: isDarwinApp()? "solid": "none", - boxShadow: isDarwinApp()? "none": "inherit" + borderBottomStyle: isDarwinApp() ? "solid" : "none", + boxShadow: isDarwinApp() ? "none" : "inherit" }, appBarMenuButton: { marginLeft: -12, marginRight: 20, - [theme.breakpoints.up('md')]: { - display: 'none' + [theme.breakpoints.up("md")]: { + display: "none" } }, appBarTitle: { - display: 'none', - [theme.breakpoints.up('md')]: { - display: 'block', + display: "none", + [theme.breakpoints.up("md")]: { + display: "block" } }, appBarSearch: { - position: 'relative', + position: "relative", borderRadius: theme.shape.borderRadius, backgroundColor: fade(theme.palette.common.white, 0.15), - '&:hover': { + "&:hover": { backgroundColor: fade(theme.palette.common.white, 0.25) }, - width: '100%', + width: "100%", marginLeft: 0, marginRight: theme.spacing.unit, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up("md")]: { marginLeft: theme.spacing.unit * 6, - width: '50%' + width: "50%" } }, appBarSearchIcon: { width: theme.spacing.unit * 9, - height: '100%', - position: 'absolute', - pointerEvents: 'none', - display: 'flex', - alignItems: 'center', - justifyContent: 'center' + height: "100%", + position: "absolute", + pointerEvents: "none", + display: "flex", + alignItems: "center", + justifyContent: "center" }, appBarSearchInputRoot: { - color: 'inherit', - width: '100%' + color: "inherit", + width: "100%" }, appBarSearchInputInput: { paddingTop: theme.spacing.unit, paddingBottom: theme.spacing.unit, paddingLeft: theme.spacing.unit * 10, paddingRight: theme.spacing.unit, - transition: theme.transitions.create('width'), - width: '100%', + transition: theme.transitions.create("width"), + width: "100%" }, appBarFlexGrow: { flexGrow: 1 }, appBarActionButtons: { - display: 'none', - [theme.breakpoints.up('sm')]: { - display: 'flex', - }, + display: "none", + [theme.breakpoints.up("sm")]: { + display: "flex" + } }, appBarAcctMenuIcon: { backgroundColor: theme.palette.primary.dark }, - acctMenu: { - - }, + acctMenu: {}, drawer: { - [theme.breakpoints.up('sm')]: { + [theme.breakpoints.up("sm")]: { width: 250, flexShrink: 0 }, - zIndex: 1, + zIndex: 1 }, drawerPaper: { width: 250, @@ -122,43 +125,47 @@ export const styles = (theme: Theme) => createStyles({ width: 250, zIndex: -1, marginTop: 64, - backgroundColor: isDarwinApp()? "transparent": theme.palette.background.paper + backgroundColor: isDarwinApp() + ? "transparent" + : theme.palette.background.paper }, drawerPaperWithTitleAndAppBar: { width: 250, zIndex: -1, marginTop: 88, - backgroundColor: isDarwinApp()? "transparent": theme.palette.background.paper + backgroundColor: isDarwinApp() + ? "transparent" + : theme.palette.background.paper }, drawerDisplayMobile: { - [theme.breakpoints.up('md')]: { - display: 'none' + [theme.breakpoints.up("md")]: { + display: "none" } }, toolbar: theme.mixins.toolbar, sectionDesktop: { - display: 'none', - [theme.breakpoints.up('md')]: { - display: 'flex', - }, + display: "none", + [theme.breakpoints.up("md")]: { + display: "flex" + } }, sectionMobile: { - display: 'flex', - [theme.breakpoints.up('md')]: { - display: 'none', - }, + display: "flex", + [theme.breakpoints.up("md")]: { + display: "none" + } }, content: { padding: theme.spacing.unit * 3, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up("md")]: { marginLeft: 250 }, - overflowY: 'auto', + overflowY: "auto" }, composeButton: { position: "fixed", bottom: theme.spacing.unit * 2, right: theme.spacing.unit * 2, zIndex: 50 - }, - }); \ No newline at end of file + } + }); diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx index 8835d92..fc24655 100644 --- a/src/components/AppLayout/AppLayout.tsx +++ b/src/components/AppLayout/AppLayout.tsx @@ -1,297 +1,416 @@ -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 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'; +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; + 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; + client: Mastodon; + streamListener: any; - constructor(props: any) { - super(props); + 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); - } + this.client = new Mastodon( + localStorage.getItem("access_token") as string, + (localStorage.getItem("baseurl") as string) + "/api/v1" + ); - 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); - }) - } + this.state = { + drawerOpenOnMobile: false, + acctMenuOpen: false, + notificationCount: 0, + logOutOpen: false + }; - 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.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); + }); + } - 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); - } + 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 }); } + }); - toggleAcctMenu() { - this.setState({ acctMenuOpen: !this.state.acctMenuOpen }); - } + this.streamNotifications(); + } - toggleDrawerOnMobile() { - this.setState({ - drawerOpenOnMobile: !this.state.drawerOpenOnMobile - }) - } + streamNotifications() { + this.streamListener = this.client.stream("/streaming/user"); - toggleLogOutDialog() { - this.setState({ logOutOpen: !this.state.logOutOpen }); - } + if (getUserDefaultBool("displayAllOnNotificationBadge")) { + this.client.get("/notifications").then((resp: any) => { + let notifArray = resp.data; + this.setState({ notificationCount: notifArray.length }); + }); + } - searchForQuery(what: string) { - window.location.href = isDesktopApp()? "hyperspace://hyperspace/app/index.html#/search?query=" + what: "/#/search?query=" + what; - window.location.reload; - } + this.streamListener.on("notification", (notif: Notification) => { + const notificationCount = this.state.notificationCount + 1; + this.setState({ notificationCount }); + if (!document.hasFocus()) { + let primaryMessage = ""; + let secondaryMessage = ""; - logOutAndRestart() { - let loginData = localStorage.getItem("login"); - if (loginData) { - let items = ["login", "account", "baseurl", "access_token"]; - items.forEach((entry) => { - localStorage.removeItem(entry); - }) - window.location.reload(); + 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; } - } - clearBadge() { - if (!getUserDefaultBool('displayAllOnNotificationBadge')) { - this.setState({ notificationCount: 0 }); - } + sendNotificationRequest(primaryMessage, secondaryMessage); } + }); + } - 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. -
- ); - } - } + toggleAcctMenu() { + this.setState({ acctMenuOpen: !this.state.acctMenuOpen }); + } - appDrawer() { - const { classes } = this.props; - return ( -
- -
- - - - - - - {/* + 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 - - - - - - - - - - - - -
+ 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"} + + {this.state.brandName ? this.state.brandName : "Hyperspace"} -
+
- +
{ root: classes.appBarSearchInputRoot, input: classes.appBarSearchInputInput }} - onKeyUp={(event) => { + onKeyUp={event => { if (event.keyCode === 13) { this.searchForQuery(event.currentTarget.value); } }} />
-
+
- - - 0? this.state.notificationCount: ""} color="secondary"> - - - - - - - - - - - - - - - - + - -
- - - - - - - - {/* Switch account */} - this.toggleLogOutDialog()}>Log out -
-
-
+ 0 + ? this.state.notificationCount + : "" + } + color="secondary" + > + + + + + + + + + + + + + + + + + +
+ + + + + + + + {/* Switch account */} + this.toggleLogOutDialog()}> + Log out + +
+
+
this.toggleLogOutDialog()} - > - Log out of {this.state.brandName? this.state.brandName: "Hyperspace"} + > + + 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"}. - + + 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"}. + - - + + - - + + -
+
); } } diff --git a/src/components/AppLayout/index.tsx b/src/components/AppLayout/index.tsx index eea680e..865b52a 100644 --- a/src/components/AppLayout/index.tsx +++ b/src/components/AppLayout/index.tsx @@ -1,6 +1,6 @@ -import { AppLayout } from './AppLayout'; -import { withStyles } from '@material-ui/core'; -import { styles } from './AppLayout.styles'; -import {withSnackbar} from 'notistack'; +import { AppLayout } from "./AppLayout"; +import { withStyles } from "@material-ui/core"; +import { styles } from "./AppLayout.styles"; +import { withSnackbar } from "notistack"; -export default withStyles(styles)(withSnackbar(AppLayout)); \ No newline at end of file +export default withStyles(styles)(withSnackbar(AppLayout)); diff --git a/src/components/Attachment/Attachment.styles.tsx b/src/components/Attachment/Attachment.styles.tsx index ad83d5b..9bdcd91 100644 --- a/src/components/Attachment/Attachment.styles.tsx +++ b/src/components/Attachment/Attachment.styles.tsx @@ -1,16 +1,17 @@ -import { Theme, createStyles } from '@material-ui/core'; +import { Theme, createStyles } from "@material-ui/core"; -export const styles = (theme: Theme) => createStyles({ +export const styles = (theme: Theme) => + createStyles({ mediaContainer: { - padding: theme.spacing.unit * 2, + padding: theme.spacing.unit * 2 }, mediaObject: { - width: '100%', - height: '100%' + width: "100%", + height: "100%" }, mediaSlide: { - backgroundColor: theme.palette.primary.light, - width: '100%', - height: 'auto' + backgroundColor: theme.palette.primary.light, + width: "100%", + height: "auto" } -}); \ No newline at end of file + }); diff --git a/src/components/Attachment/Attachment.tsx b/src/components/Attachment/Attachment.tsx index a5d830e..0956a7f 100644 --- a/src/components/Attachment/Attachment.tsx +++ b/src/components/Attachment/Attachment.tsx @@ -1,105 +1,141 @@ -import React, { Component } from 'react'; -import {withStyles, Typography, MobileStepper, Button} from '@material-ui/core'; -import { styles } from './Attachment.styles'; -import { Attachment } from '../../types/Attachment'; -import SwipeableViews from 'react-swipeable-views'; +import React, { Component } from "react"; +import { + withStyles, + Typography, + MobileStepper, + Button +} from "@material-ui/core"; +import { styles } from "./Attachment.styles"; +import { Attachment } from "../../types/Attachment"; +import SwipeableViews from "react-swipeable-views"; interface IAttachmentProps { - media: [Attachment]; - classes?: any; + media: [Attachment]; + classes?: any; } interface IAttachmentState { - totalSteps: number; - currentStep: number; - attachments: [Attachment]; + totalSteps: number; + currentStep: number; + attachments: [Attachment]; } -class AttachmentComponent extends Component { - constructor(props: IAttachmentProps) { - super(props); +class AttachmentComponent extends Component< + IAttachmentProps, + IAttachmentState +> { + constructor(props: IAttachmentProps) { + super(props); - this.state = { - attachments: this.props.media, - totalSteps: this.props.media.length, - currentStep: 0 - } + this.state = { + attachments: this.props.media, + totalSteps: this.props.media.length, + currentStep: 0 + }; + } + + moveBack() { + let nextStep = this.state.currentStep - 1; + if (nextStep < 0) { + nextStep = 0; } + this.setState({ currentStep: nextStep }); + } - moveBack() { - let nextStep = this.state.currentStep - 1; - if (nextStep < 0) { - nextStep = 0; - } - this.setState({ currentStep: nextStep }); + moveForward() { + let nextStep = this.state.currentStep + 1; + if (nextStep > this.state.totalSteps) { + nextStep = this.state.totalSteps; } + this.setState({ currentStep: nextStep }); + } - moveForward() { - let nextStep = this.state.currentStep + 1; - if (nextStep > this.state.totalSteps) { - nextStep = this.state.totalSteps; - } - this.setState({ currentStep: nextStep }); + handleStepChange(currentStep: number) { + this.setState({ + currentStep + }); + } - } - - handleStepChange(currentStep: number) { - this.setState({ - currentStep - }) - } - - getSlide(slide: Attachment) { - const {classes} = this.props; - switch (slide.type) { - case 'image': - return {slide.description? - case 'video': - return