2019-09-18 19:52:39 +02:00
|
|
|
import React, { Component } from "react";
|
2019-03-27 22:39:25 +01:00
|
|
|
import {
|
2019-09-18 19:52:39 +02:00
|
|
|
List,
|
2019-04-28 18:46:26 +02:00
|
|
|
ListItem,
|
|
|
|
ListItemAvatar,
|
2019-09-18 19:52:39 +02:00
|
|
|
ListItemText,
|
|
|
|
ListSubheader,
|
|
|
|
ListItemSecondaryAction,
|
|
|
|
Paper,
|
|
|
|
IconButton,
|
|
|
|
withStyles,
|
2019-03-27 22:39:25 +01:00
|
|
|
Button,
|
|
|
|
Switch,
|
|
|
|
Dialog,
|
|
|
|
DialogTitle,
|
|
|
|
DialogContent,
|
|
|
|
RadioGroup,
|
|
|
|
FormControlLabel,
|
|
|
|
Radio,
|
2019-04-08 20:31:20 +02:00
|
|
|
DialogActions,
|
2019-04-20 22:35:38 +02:00
|
|
|
DialogContentText,
|
|
|
|
Grid,
|
2019-04-21 21:32:12 +02:00
|
|
|
Theme,
|
2019-10-01 00:18:38 +02:00
|
|
|
Typography,
|
|
|
|
Avatar,
|
|
|
|
Toolbar,
|
|
|
|
Tooltip
|
2019-09-18 19:52:39 +02:00
|
|
|
} from "@material-ui/core";
|
|
|
|
import { styles } from "./PageLayout.styles";
|
|
|
|
import {
|
|
|
|
setUserDefaultBool,
|
|
|
|
getUserDefaultBool,
|
|
|
|
getUserDefaultTheme,
|
|
|
|
setUserDefaultTheme,
|
|
|
|
getUserDefaultVisibility,
|
|
|
|
setUserDefaultVisibility,
|
|
|
|
getConfig
|
|
|
|
} from "../utilities/settings";
|
|
|
|
import {
|
|
|
|
canSendNotifications,
|
|
|
|
browserSupportsNotificationRequests
|
|
|
|
} from "../utilities/notifications";
|
|
|
|
import { themes, defaultTheme } from "../types/HyperspaceTheme";
|
|
|
|
import ThemePreview from "../components/ThemePreview";
|
|
|
|
import {
|
|
|
|
setHyperspaceTheme,
|
|
|
|
getHyperspaceTheme,
|
|
|
|
getDarkModeFromSystem
|
|
|
|
} from "../utilities/themes";
|
|
|
|
import { Visibility } from "../types/Visibility";
|
2019-10-01 00:18:38 +02:00
|
|
|
import { LinkableButton, LinkableIconButton } from "../interfaces/overrides";
|
2019-03-27 22:39:25 +01:00
|
|
|
|
2019-09-18 19:52:39 +02:00
|
|
|
import OpenInNewIcon from "@material-ui/icons/OpenInNew";
|
|
|
|
import DevicesIcon from "@material-ui/icons/Devices";
|
|
|
|
import Brightness3Icon from "@material-ui/icons/Brightness3";
|
|
|
|
import PaletteIcon from "@material-ui/icons/Palette";
|
|
|
|
import AccountEditIcon from "mdi-material-ui/AccountEdit";
|
|
|
|
import MastodonIcon from "mdi-material-ui/Mastodon";
|
|
|
|
import VisibilityIcon from "@material-ui/icons/Visibility";
|
|
|
|
import NotificationsIcon from "@material-ui/icons/Notifications";
|
|
|
|
import BellAlertIcon from "mdi-material-ui/BellAlert";
|
|
|
|
import RefreshIcon from "@material-ui/icons/Refresh";
|
|
|
|
import UndoIcon from "@material-ui/icons/Undo";
|
2019-09-23 20:00:11 +02:00
|
|
|
import DomainDisabledIcon from "@material-ui/icons/DomainDisabled";
|
2019-11-01 22:51:30 +01:00
|
|
|
import AccountSettingsIcon from "mdi-material-ui/AccountSettings";
|
2019-11-17 19:55:53 +01:00
|
|
|
import AlphabeticalVariantOffIcon from "mdi-material-ui/AlphabeticalVariantOff";
|
2019-11-01 22:51:30 +01:00
|
|
|
|
2019-09-18 19:52:39 +02:00
|
|
|
import { Config } from "../types/Config";
|
2019-10-01 00:18:38 +02:00
|
|
|
import { Account } from "../types/Account";
|
|
|
|
import Mastodon from "megalodon";
|
|
|
|
import { isDarwinApp } from "../utilities/desktop";
|
2019-04-28 18:46:26 +02:00
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
interface ISettingsState {
|
|
|
|
darkModeEnabled: boolean;
|
2019-04-21 18:39:22 +02:00
|
|
|
systemDecidesDarkMode: boolean;
|
2019-03-27 22:39:25 +01:00
|
|
|
pushNotificationsEnabled: boolean;
|
2019-04-19 20:57:35 +02:00
|
|
|
badgeDisplaysAllNotifs: boolean;
|
2019-03-27 22:39:25 +01:00
|
|
|
selectThemeName: string;
|
|
|
|
themeDialogOpen: boolean;
|
2019-04-20 23:14:47 +02:00
|
|
|
visibilityDialogOpen: boolean;
|
2019-04-08 20:31:20 +02:00
|
|
|
resetHyperspaceDialog: boolean;
|
2019-04-12 19:39:24 +02:00
|
|
|
resetSettingsDialog: boolean;
|
2019-04-20 22:35:38 +02:00
|
|
|
previewTheme: Theme;
|
2019-04-20 23:14:47 +02:00
|
|
|
defaultVisibility: Visibility;
|
2019-04-28 21:38:44 +02:00
|
|
|
brandName: string;
|
2019-04-27 19:21:24 +02:00
|
|
|
federated: boolean;
|
2019-10-01 00:18:38 +02:00
|
|
|
currentUser?: Account;
|
2019-11-17 19:55:53 +01:00
|
|
|
imposeCharacterLimit: boolean;
|
2019-03-27 22:39:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class SettingsPage extends Component<any, ISettingsState> {
|
2019-10-01 00:18:38 +02:00
|
|
|
client: Mastodon;
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
constructor(props: any) {
|
|
|
|
super(props);
|
|
|
|
|
2019-10-01 00:18:38 +02:00
|
|
|
this.client = new Mastodon(
|
|
|
|
localStorage.getItem("access_token") as string,
|
|
|
|
(localStorage.getItem("baseurl") as string) + "/api/v1"
|
|
|
|
);
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
this.state = {
|
2019-09-18 19:52:39 +02:00
|
|
|
darkModeEnabled: getUserDefaultBool("darkModeEnabled"),
|
|
|
|
systemDecidesDarkMode: getUserDefaultBool("systemDecidesDarkMode"),
|
2019-03-28 14:24:38 +01:00
|
|
|
pushNotificationsEnabled: canSendNotifications(),
|
2019-09-18 19:52:39 +02:00
|
|
|
badgeDisplaysAllNotifs: getUserDefaultBool(
|
|
|
|
"displayAllOnNotificationBadge"
|
|
|
|
),
|
2019-03-27 22:39:25 +01:00
|
|
|
selectThemeName: getUserDefaultTheme().key,
|
2019-04-08 20:31:20 +02:00
|
|
|
themeDialogOpen: false,
|
2019-04-20 23:14:47 +02:00
|
|
|
visibilityDialogOpen: false,
|
2019-04-12 19:39:24 +02:00
|
|
|
resetHyperspaceDialog: false,
|
2019-04-20 22:35:38 +02:00
|
|
|
resetSettingsDialog: false,
|
2019-09-18 19:52:39 +02:00
|
|
|
previewTheme:
|
|
|
|
setHyperspaceTheme(getUserDefaultTheme()) ||
|
|
|
|
setHyperspaceTheme(defaultTheme),
|
2019-04-27 19:21:24 +02:00
|
|
|
defaultVisibility: getUserDefaultVisibility() || "public",
|
2019-04-28 21:52:08 +02:00
|
|
|
brandName: "Hyperspace",
|
2019-11-17 19:55:53 +01:00
|
|
|
federated: true,
|
|
|
|
imposeCharacterLimit: getUserDefaultBool("imposeCharacterLimit")
|
2019-09-18 19:52:39 +02:00
|
|
|
};
|
2019-03-27 22:39:25 +01:00
|
|
|
|
|
|
|
this.toggleDarkMode = this.toggleDarkMode.bind(this);
|
2019-04-21 18:39:22 +02:00
|
|
|
this.toggleSystemDarkMode = this.toggleSystemDarkMode.bind(this);
|
2019-03-27 22:39:25 +01:00
|
|
|
this.togglePushNotifications = this.togglePushNotifications.bind(this);
|
2019-04-19 20:57:35 +02:00
|
|
|
this.toggleBadgeCount = this.toggleBadgeCount.bind(this);
|
2019-03-27 22:39:25 +01:00
|
|
|
this.toggleThemeDialog = this.toggleThemeDialog.bind(this);
|
2019-04-20 23:14:47 +02:00
|
|
|
this.toggleVisibilityDialog = this.toggleVisibilityDialog.bind(this);
|
2019-03-27 22:39:25 +01:00
|
|
|
this.changeThemeName = this.changeThemeName.bind(this);
|
|
|
|
this.changeTheme = this.changeTheme.bind(this);
|
2019-04-20 23:14:47 +02:00
|
|
|
this.setVisibility = this.setVisibility.bind(this);
|
2019-03-27 22:39:25 +01:00
|
|
|
}
|
|
|
|
|
2019-04-27 19:21:24 +02:00
|
|
|
componentDidMount() {
|
2019-09-18 19:52:39 +02:00
|
|
|
getConfig()
|
|
|
|
.then((config: any) => {
|
|
|
|
this.setState({
|
|
|
|
brandName: config.branding.name
|
|
|
|
});
|
2019-04-28 21:38:44 +02:00
|
|
|
})
|
2019-09-18 19:52:39 +02:00
|
|
|
.catch((err: Error) => {
|
|
|
|
console.error(err.message);
|
|
|
|
});
|
2019-04-27 19:21:24 +02:00
|
|
|
this.getFederatedStatus();
|
2019-10-01 00:18:38 +02:00
|
|
|
|
2019-10-03 21:28:49 +02:00
|
|
|
this.client
|
|
|
|
.get("/accounts/verify_credentials")
|
|
|
|
.then((resp: any) => {
|
|
|
|
let data: Account = resp.data;
|
|
|
|
this.setState({ currentUser: data });
|
|
|
|
})
|
|
|
|
.catch((err: Error) => {
|
2019-10-04 19:41:49 +02:00
|
|
|
let acct = localStorage.getItem("account");
|
|
|
|
if (acct) {
|
|
|
|
this.setState({ currentUser: JSON.parse(acct) });
|
|
|
|
} else {
|
|
|
|
this.props.enqueueSnackbar(
|
|
|
|
"Couldn't find profile info: " + err.name
|
|
|
|
);
|
|
|
|
console.error(err.message);
|
|
|
|
}
|
2019-10-03 21:28:49 +02:00
|
|
|
});
|
2019-04-27 19:21:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
getFederatedStatus() {
|
2019-05-08 21:24:36 +02:00
|
|
|
getConfig().then((result: any) => {
|
|
|
|
if (result !== undefined) {
|
|
|
|
let config: Config = result;
|
2019-10-01 00:18:38 +02:00
|
|
|
console.log(!config.federation.allowPublicPosts);
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
federated: config.federation.allowPublicPosts
|
|
|
|
});
|
2019-05-08 21:24:36 +02:00
|
|
|
}
|
2019-09-18 19:52:39 +02:00
|
|
|
});
|
2019-04-27 19:21:24 +02:00
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
toggleDarkMode() {
|
|
|
|
this.setState({ darkModeEnabled: !this.state.darkModeEnabled });
|
2019-09-18 19:52:39 +02:00
|
|
|
setUserDefaultBool("darkModeEnabled", !this.state.darkModeEnabled);
|
2019-03-27 22:39:25 +01:00
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
|
2019-04-21 18:39:22 +02:00
|
|
|
toggleSystemDarkMode() {
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
systemDecidesDarkMode: !this.state.systemDecidesDarkMode
|
|
|
|
});
|
|
|
|
setUserDefaultBool(
|
|
|
|
"systemDecidesDarkMode",
|
|
|
|
!this.state.systemDecidesDarkMode
|
|
|
|
);
|
2019-04-21 18:39:22 +02:00
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
togglePushNotifications() {
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
pushNotificationsEnabled: !this.state.pushNotificationsEnabled
|
|
|
|
});
|
|
|
|
setUserDefaultBool(
|
|
|
|
"enablePushNotifications",
|
|
|
|
!this.state.pushNotificationsEnabled
|
|
|
|
);
|
2019-03-27 22:39:25 +01:00
|
|
|
}
|
|
|
|
|
2019-04-19 20:57:35 +02:00
|
|
|
toggleBadgeCount() {
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
badgeDisplaysAllNotifs: !this.state.badgeDisplaysAllNotifs
|
|
|
|
});
|
|
|
|
setUserDefaultBool(
|
|
|
|
"displayAllOnNotificationBadge",
|
|
|
|
!this.state.badgeDisplaysAllNotifs
|
|
|
|
);
|
2019-04-19 20:57:35 +02:00
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
toggleThemeDialog() {
|
|
|
|
this.setState({ themeDialogOpen: !this.state.themeDialogOpen });
|
|
|
|
}
|
|
|
|
|
2019-04-20 23:14:47 +02:00
|
|
|
toggleVisibilityDialog() {
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
visibilityDialogOpen: !this.state.visibilityDialogOpen
|
|
|
|
});
|
2019-04-20 23:14:47 +02:00
|
|
|
}
|
|
|
|
|
2019-11-17 19:55:53 +01:00
|
|
|
toggleCharacterLimit() {
|
|
|
|
this.setState({
|
|
|
|
imposeCharacterLimit: !this.state.imposeCharacterLimit
|
|
|
|
});
|
|
|
|
setUserDefaultBool(
|
|
|
|
"imposeCharacterLimit",
|
|
|
|
!this.state.imposeCharacterLimit
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-08 20:31:20 +02:00
|
|
|
toggleResetDialog() {
|
2019-09-18 19:52:39 +02:00
|
|
|
this.setState({
|
|
|
|
resetHyperspaceDialog: !this.state.resetHyperspaceDialog
|
|
|
|
});
|
2019-04-08 20:31:20 +02:00
|
|
|
}
|
|
|
|
|
2019-04-12 19:39:24 +02:00
|
|
|
toggleResetSettingsDialog() {
|
|
|
|
this.setState({ resetSettingsDialog: !this.state.resetSettingsDialog });
|
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
changeTheme() {
|
|
|
|
setUserDefaultTheme(this.state.selectThemeName);
|
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
changeThemeName(theme: string) {
|
2019-04-20 22:35:38 +02:00
|
|
|
let previewTheme = setHyperspaceTheme(getHyperspaceTheme(theme));
|
|
|
|
this.setState({ selectThemeName: theme, previewTheme });
|
2019-03-27 22:39:25 +01:00
|
|
|
}
|
|
|
|
|
2019-04-20 23:14:47 +02:00
|
|
|
changeVisibility(to: Visibility) {
|
|
|
|
this.setState({ defaultVisibility: to });
|
|
|
|
}
|
|
|
|
|
|
|
|
setVisibility() {
|
2019-04-20 23:23:08 +02:00
|
|
|
setUserDefaultVisibility(this.state.defaultVisibility);
|
2019-04-20 23:14:47 +02:00
|
|
|
this.toggleVisibilityDialog();
|
|
|
|
}
|
|
|
|
|
2019-04-08 20:31:20 +02:00
|
|
|
reset() {
|
|
|
|
localStorage.clear();
|
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
|
2019-04-12 19:39:24 +02:00
|
|
|
refresh() {
|
2019-09-18 19:52:39 +02:00
|
|
|
let settings = [
|
|
|
|
"darkModeEnabled",
|
|
|
|
"enablePushNotifications",
|
|
|
|
"clearNotificationsOnRead",
|
|
|
|
"theme",
|
|
|
|
"displayAllOnNotificationBadge",
|
|
|
|
"defaultVisibility"
|
|
|
|
];
|
2019-04-12 19:39:24 +02:00
|
|
|
settings.forEach(setting => {
|
|
|
|
localStorage.removeItem(setting);
|
2019-09-18 19:52:39 +02:00
|
|
|
});
|
2019-04-12 19:39:24 +02:00
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
showThemeDialog() {
|
2019-09-18 19:52:39 +02:00
|
|
|
const { classes } = this.props;
|
2019-03-27 22:39:25 +01:00
|
|
|
return (
|
|
|
|
<Dialog
|
|
|
|
open={this.state.themeDialogOpen}
|
|
|
|
disableBackdropClick
|
|
|
|
disableEscapeKeyDown
|
2019-04-20 22:35:38 +02:00
|
|
|
maxWidth="md"
|
2019-03-27 22:39:25 +01:00
|
|
|
fullWidth={true}
|
|
|
|
aria-labelledby="confirmation-dialog-title"
|
|
|
|
>
|
2019-09-18 19:52:39 +02:00
|
|
|
<DialogTitle id="confirmation-dialog-title">
|
|
|
|
Choose a theme
|
|
|
|
</DialogTitle>
|
2019-03-27 22:39:25 +01:00
|
|
|
<DialogContent>
|
2019-04-20 22:35:38 +02:00
|
|
|
<Grid container spacing={16}>
|
|
|
|
<Grid item xs={12} md={6}>
|
|
|
|
<RadioGroup
|
2019-04-20 22:39:35 +02:00
|
|
|
aria-label="Theme"
|
2019-04-20 22:35:38 +02:00
|
|
|
name="colorScheme"
|
|
|
|
value={this.state.selectThemeName}
|
2019-09-18 19:52:39 +02:00
|
|
|
onChange={(e, value) =>
|
|
|
|
this.changeThemeName(value)
|
|
|
|
}
|
2019-04-20 22:35:38 +02:00
|
|
|
>
|
|
|
|
{themes.map(theme => (
|
2019-09-18 19:52:39 +02:00
|
|
|
<FormControlLabel
|
|
|
|
value={theme.key}
|
|
|
|
key={theme.key}
|
|
|
|
control={<Radio />}
|
|
|
|
label={theme.name}
|
|
|
|
/>
|
2019-04-20 22:35:38 +02:00
|
|
|
))}
|
|
|
|
))}
|
|
|
|
</RadioGroup>
|
|
|
|
</Grid>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Grid
|
|
|
|
item
|
|
|
|
xs={12}
|
|
|
|
md={6}
|
|
|
|
className={classes.desktopOnly}
|
|
|
|
>
|
|
|
|
<Typography variant="h6" component="p">
|
|
|
|
Theme preview
|
|
|
|
</Typography>
|
|
|
|
<ThemePreview theme={this.state.previewTheme} />
|
2019-04-20 22:35:38 +02:00
|
|
|
</Grid>
|
|
|
|
</Grid>
|
2019-03-27 22:39:25 +01:00
|
|
|
</DialogContent>
|
|
|
|
<DialogActions>
|
2019-03-28 00:24:52 +01:00
|
|
|
<Button onClick={this.toggleThemeDialog} color="default">
|
2019-03-27 22:39:25 +01:00
|
|
|
Cancel
|
|
|
|
</Button>
|
2019-03-28 00:24:52 +01:00
|
|
|
<Button onClick={this.changeTheme} color="secondary">
|
2019-04-20 22:35:38 +02:00
|
|
|
Set theme
|
2019-03-27 22:39:25 +01:00
|
|
|
</Button>
|
|
|
|
</DialogActions>
|
|
|
|
</Dialog>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-20 23:14:47 +02:00
|
|
|
showVisibilityDialog() {
|
|
|
|
return (
|
|
|
|
<Dialog
|
|
|
|
open={this.state.visibilityDialogOpen}
|
|
|
|
disableBackdropClick
|
|
|
|
disableEscapeKeyDown
|
|
|
|
maxWidth="xs"
|
|
|
|
fullWidth={true}
|
|
|
|
aria-labelledby="confirmation-dialog-title"
|
|
|
|
>
|
2019-09-18 19:52:39 +02:00
|
|
|
<DialogTitle id="confirmation-dialog-title">
|
|
|
|
Set your default visibility
|
|
|
|
</DialogTitle>
|
2019-04-20 23:14:47 +02:00
|
|
|
<DialogContent>
|
|
|
|
<RadioGroup
|
|
|
|
aria-label="Visibility"
|
|
|
|
name="visibility"
|
|
|
|
value={this.state.defaultVisibility}
|
2019-09-18 19:52:39 +02:00
|
|
|
onChange={(e, value) =>
|
|
|
|
this.changeVisibility(value as Visibility)
|
|
|
|
}
|
2019-04-20 23:14:47 +02:00
|
|
|
>
|
2019-09-18 19:52:39 +02:00
|
|
|
<FormControlLabel
|
|
|
|
value={"public"}
|
|
|
|
key={"public"}
|
|
|
|
control={<Radio />}
|
|
|
|
label={`Public ${
|
|
|
|
this.state.federated
|
|
|
|
? ""
|
|
|
|
: "(disabled by provider)"
|
2019-12-18 03:00:58 +01:00
|
|
|
}`}
|
2019-09-18 19:52:39 +02:00
|
|
|
disabled={!this.state.federated}
|
|
|
|
/>
|
|
|
|
<FormControlLabel
|
|
|
|
value={"unlisted"}
|
|
|
|
key={"unlisted"}
|
|
|
|
control={<Radio />}
|
|
|
|
label={"Unlisted"}
|
|
|
|
/>
|
|
|
|
<FormControlLabel
|
|
|
|
value={"private"}
|
|
|
|
key={"private"}
|
|
|
|
control={<Radio />}
|
|
|
|
label={"Private (followers only)"}
|
|
|
|
/>
|
|
|
|
<FormControlLabel
|
|
|
|
value={"direct"}
|
|
|
|
key={"direct"}
|
|
|
|
control={<Radio />}
|
|
|
|
label={"Direct"}
|
|
|
|
/>
|
2019-04-20 23:14:47 +02:00
|
|
|
</RadioGroup>
|
|
|
|
</DialogContent>
|
|
|
|
<DialogActions>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Button
|
|
|
|
onClick={this.toggleVisibilityDialog}
|
|
|
|
color="default"
|
|
|
|
>
|
2019-04-20 23:14:47 +02:00
|
|
|
Cancel
|
|
|
|
</Button>
|
|
|
|
<Button onClick={this.setVisibility} color="secondary">
|
|
|
|
Set default
|
|
|
|
</Button>
|
|
|
|
</DialogActions>
|
|
|
|
</Dialog>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-12 19:39:24 +02:00
|
|
|
showResetSettingsDialog() {
|
|
|
|
return (
|
|
|
|
<Dialog
|
|
|
|
open={this.state.resetSettingsDialog}
|
|
|
|
onClose={() => this.toggleResetSettingsDialog()}
|
2019-09-18 19:52:39 +02:00
|
|
|
>
|
|
|
|
<DialogTitle id="alert-dialog-title">
|
|
|
|
Are you sure you want to refresh settings?
|
|
|
|
</DialogTitle>
|
2019-04-12 19:39:24 +02:00
|
|
|
<DialogActions>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Button
|
|
|
|
onClick={() => this.toggleResetSettingsDialog()}
|
|
|
|
color="primary"
|
|
|
|
autoFocus
|
|
|
|
>
|
|
|
|
Cancel
|
2019-04-12 19:39:24 +02:00
|
|
|
</Button>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Button
|
|
|
|
onClick={() => {
|
|
|
|
this.refresh();
|
|
|
|
}}
|
|
|
|
color="primary"
|
|
|
|
>
|
|
|
|
Refresh
|
2019-04-12 19:39:24 +02:00
|
|
|
</Button>
|
|
|
|
</DialogActions>
|
2019-09-18 19:52:39 +02:00
|
|
|
</Dialog>
|
2019-04-12 19:39:24 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-08 20:31:20 +02:00
|
|
|
showResetDialog() {
|
|
|
|
return (
|
|
|
|
<Dialog
|
|
|
|
open={this.state.resetHyperspaceDialog}
|
|
|
|
onClose={() => this.toggleResetDialog()}
|
2019-09-18 19:52:39 +02:00
|
|
|
>
|
|
|
|
<DialogTitle id="alert-dialog-title">
|
|
|
|
Reset {this.state.brandName}?
|
|
|
|
</DialogTitle>
|
2019-04-08 20:31:20 +02:00
|
|
|
<DialogContent>
|
|
|
|
<DialogContentText id="alert-dialog-description">
|
2019-09-18 19:52:39 +02:00
|
|
|
Are you sure you want to reset {this.state.brandName}?
|
|
|
|
You'll need to re-authorize {this.state.brandName}{" "}
|
|
|
|
access again.
|
2019-04-08 20:31:20 +02:00
|
|
|
</DialogContentText>
|
|
|
|
</DialogContent>
|
|
|
|
<DialogActions>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Button
|
|
|
|
onClick={() => this.toggleResetDialog()}
|
|
|
|
color="primary"
|
|
|
|
autoFocus
|
|
|
|
>
|
|
|
|
Cancel
|
2019-04-08 20:31:20 +02:00
|
|
|
</Button>
|
2019-09-18 19:52:39 +02:00
|
|
|
<Button
|
|
|
|
onClick={() => {
|
|
|
|
this.reset();
|
|
|
|
}}
|
|
|
|
color="primary"
|
|
|
|
>
|
|
|
|
Reset
|
2019-04-08 20:31:20 +02:00
|
|
|
</Button>
|
|
|
|
</DialogActions>
|
2019-09-18 19:52:39 +02:00
|
|
|
</Dialog>
|
2019-04-08 20:31:20 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-03-27 22:39:25 +01:00
|
|
|
render() {
|
|
|
|
const { classes } = this.props;
|
|
|
|
return (
|
2019-10-01 00:18:38 +02:00
|
|
|
<div>
|
|
|
|
<div className={classes.pageLayoutMinimalConstraints}>
|
|
|
|
{this.state.currentUser ? (
|
|
|
|
<div className={classes.pageHeroBackground}>
|
|
|
|
<div
|
|
|
|
className={classes.pageHeroBackgroundImage}
|
|
|
|
style={{
|
|
|
|
backgroundImage: `url("${this.state.currentUser.header_static}")`
|
|
|
|
}}
|
2019-09-18 19:52:39 +02:00
|
|
|
/>
|
2019-10-01 00:18:38 +02:00
|
|
|
<div className={classes.profileContent}>
|
|
|
|
<br />
|
|
|
|
<Avatar
|
2019-10-05 19:21:59 +02:00
|
|
|
className={classes.settingsAvatar}
|
2019-10-01 00:18:38 +02:00
|
|
|
src={this.state.currentUser.avatar_static}
|
2019-04-21 18:39:22 +02:00
|
|
|
/>
|
2019-10-01 00:18:38 +02:00
|
|
|
<div
|
|
|
|
className={classes.profileUserBox}
|
|
|
|
style={{ margin: "auto" }}
|
2019-09-18 19:52:39 +02:00
|
|
|
>
|
2019-10-01 00:18:38 +02:00
|
|
|
<Typography
|
2019-10-05 19:21:59 +02:00
|
|
|
className={classes.settingsHeaderText}
|
2019-10-01 00:18:38 +02:00
|
|
|
color="inherit"
|
|
|
|
component="h1"
|
|
|
|
>
|
|
|
|
{this.state.currentUser.display_name ||
|
|
|
|
this.state.currentUser.username}
|
|
|
|
</Typography>
|
|
|
|
<Typography
|
|
|
|
color="inherit"
|
2019-10-05 19:21:59 +02:00
|
|
|
className={classes.settingsDetailText}
|
2019-10-01 00:18:38 +02:00
|
|
|
component="p"
|
|
|
|
>
|
|
|
|
@{this.state.currentUser.acct}
|
|
|
|
</Typography>
|
|
|
|
</div>
|
|
|
|
<div className={classes.pageGrow} />
|
|
|
|
<Toolbar>
|
2019-11-01 22:51:30 +01:00
|
|
|
<Tooltip title="Edit profile">
|
2019-10-01 00:18:38 +02:00
|
|
|
<LinkableIconButton
|
|
|
|
to={"/you"}
|
|
|
|
color="inherit"
|
|
|
|
>
|
|
|
|
<AccountEditIcon />
|
|
|
|
</LinkableIconButton>
|
|
|
|
</Tooltip>
|
|
|
|
<Tooltip title="Manage blocked servers">
|
|
|
|
<LinkableIconButton
|
|
|
|
to={"/blocked"}
|
|
|
|
color="inherit"
|
|
|
|
>
|
|
|
|
<DomainDisabledIcon />
|
|
|
|
</LinkableIconButton>
|
|
|
|
</Tooltip>
|
2019-11-01 22:51:30 +01:00
|
|
|
<Tooltip title="Manage follow requests">
|
|
|
|
<LinkableIconButton
|
|
|
|
to={"/requests"}
|
|
|
|
color="inherit"
|
|
|
|
>
|
|
|
|
<AccountSettingsIcon />
|
|
|
|
</LinkableIconButton>
|
|
|
|
</Tooltip>
|
2019-10-01 00:18:38 +02:00
|
|
|
<Tooltip title="Configure on Mastodon">
|
|
|
|
<IconButton
|
|
|
|
href={
|
|
|
|
(localStorage.getItem(
|
|
|
|
"baseurl"
|
|
|
|
) as string) +
|
|
|
|
"/settings/preferences"
|
|
|
|
}
|
|
|
|
target="_blank"
|
|
|
|
rel="noreferrer"
|
|
|
|
color="inherit"
|
|
|
|
>
|
|
|
|
<MastodonIcon />
|
|
|
|
</IconButton>
|
|
|
|
</Tooltip>
|
|
|
|
</Toolbar>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-12-18 03:04:16 +01:00
|
|
|
) : (
|
|
|
|
<div className={classes.pageHeroBackground}>
|
|
|
|
<div className={classes.pageHeroBackgroundImage} />
|
|
|
|
<div className={classes.profileContent}>
|
|
|
|
<br />
|
|
|
|
<Avatar
|
|
|
|
className={classes.settingsAvatar}
|
|
|
|
/>
|
|
|
|
<div
|
|
|
|
className={classes.profileUserBox}
|
|
|
|
style={{ margin: "auto" }}
|
|
|
|
>
|
|
|
|
<Typography
|
|
|
|
className={classes.settingsHeaderText}
|
|
|
|
color="inherit"
|
|
|
|
component="h1"
|
|
|
|
>
|
|
|
|
{'Loading...'}
|
|
|
|
</Typography>
|
|
|
|
<Typography
|
|
|
|
color="inherit"
|
|
|
|
className={classes.settingsDetailText}
|
|
|
|
component="p"
|
|
|
|
>
|
|
|
|
@{'...'}
|
|
|
|
</Typography>
|
|
|
|
</div>
|
|
|
|
<div className={classes.pageGrow} />
|
|
|
|
<Toolbar />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
2019-10-01 00:18:38 +02:00
|
|
|
<div className={classes.pageContentLayoutConstraints}>
|
|
|
|
<ListSubheader>Appearance</ListSubheader>
|
|
|
|
<Paper className={classes.pageListConstraints}>
|
|
|
|
<List>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<DevicesIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Match system appearance"
|
2019-10-05 19:26:00 +02:00
|
|
|
secondary="Follows your device's preferences to toggle dark mode"
|
2019-10-01 00:18:38 +02:00
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Switch
|
|
|
|
checked={
|
|
|
|
this.state.systemDecidesDarkMode
|
|
|
|
}
|
|
|
|
onChange={this.toggleSystemDarkMode}
|
|
|
|
/>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
2019-10-05 19:26:00 +02:00
|
|
|
{!this.state.systemDecidesDarkMode ? (
|
2019-10-01 00:18:38 +02:00
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<Brightness3Icon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Dark mode"
|
|
|
|
secondary="Toggles light or dark theme"
|
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Switch
|
|
|
|
disabled={
|
|
|
|
this.state
|
|
|
|
.systemDecidesDarkMode
|
|
|
|
}
|
|
|
|
checked={
|
|
|
|
this.state.darkModeEnabled
|
|
|
|
}
|
|
|
|
onChange={this.toggleDarkMode}
|
|
|
|
/>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<PaletteIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Interface theme"
|
2019-10-05 19:26:00 +02:00
|
|
|
secondary="Defines the color palette used for the interface"
|
2019-10-01 00:18:38 +02:00
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Button
|
|
|
|
onClick={this.toggleThemeDialog}
|
|
|
|
>
|
|
|
|
Set theme
|
|
|
|
</Button>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
</List>
|
|
|
|
</Paper>
|
|
|
|
<br />
|
|
|
|
<ListSubheader>Composer</ListSubheader>
|
|
|
|
<Paper className={classes.pageListConstraints}>
|
|
|
|
<List>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<VisibilityIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
2019-10-05 19:26:00 +02:00
|
|
|
primary="Default post visibility"
|
|
|
|
secondary="Creating posts in the composer will use this visiblity"
|
2019-10-01 00:18:38 +02:00
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Button
|
|
|
|
onClick={
|
|
|
|
this.toggleVisibilityDialog
|
|
|
|
}
|
|
|
|
>
|
|
|
|
Change
|
|
|
|
</Button>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
2019-11-17 19:55:53 +01:00
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<AlphabeticalVariantOffIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Impose character limit"
|
|
|
|
secondary="Impose a character limit when creating posts"
|
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Switch
|
|
|
|
checked={
|
|
|
|
this.state.imposeCharacterLimit
|
|
|
|
}
|
2019-11-17 20:15:59 +01:00
|
|
|
onChange={() =>
|
|
|
|
this.toggleCharacterLimit()
|
|
|
|
}
|
2019-11-17 19:55:53 +01:00
|
|
|
/>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
2019-10-01 00:18:38 +02:00
|
|
|
</List>
|
|
|
|
</Paper>
|
|
|
|
<br />
|
|
|
|
<ListSubheader>Notifications</ListSubheader>
|
|
|
|
<Paper className={classes.pageListConstraints}>
|
|
|
|
<List>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<NotificationsIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Enable push notifications"
|
|
|
|
secondary={
|
|
|
|
getUserDefaultBool(
|
|
|
|
"userDeniedNotification"
|
|
|
|
)
|
|
|
|
? "Check your browser's notification permissions."
|
|
|
|
: browserSupportsNotificationRequests()
|
2019-12-18 03:00:58 +01:00
|
|
|
? "Sends a push notification when not focused."
|
|
|
|
: "Notifications aren't supported."
|
2019-10-01 00:18:38 +02:00
|
|
|
}
|
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Switch
|
|
|
|
checked={
|
|
|
|
this.state
|
|
|
|
.pushNotificationsEnabled
|
|
|
|
}
|
|
|
|
onChange={
|
|
|
|
this.togglePushNotifications
|
|
|
|
}
|
|
|
|
disabled={
|
|
|
|
!browserSupportsNotificationRequests() ||
|
|
|
|
getUserDefaultBool(
|
|
|
|
"userDeniedNotification"
|
|
|
|
)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<BellAlertIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Notification badge counts all notifications"
|
|
|
|
secondary={
|
|
|
|
"Counts all notifications, read or unread."
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Switch
|
|
|
|
checked={
|
|
|
|
this.state
|
|
|
|
.badgeDisplaysAllNotifs
|
|
|
|
}
|
|
|
|
onChange={this.toggleBadgeCount}
|
|
|
|
/>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
</List>
|
|
|
|
</Paper>
|
|
|
|
<br />
|
|
|
|
<ListSubheader>Advanced</ListSubheader>
|
|
|
|
<Paper className={classes.pageListConstraints}>
|
|
|
|
<List>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<RefreshIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary="Refresh settings"
|
2019-10-05 19:26:00 +02:00
|
|
|
secondary="Resets the settings to defaults."
|
2019-10-01 00:18:38 +02:00
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Button
|
|
|
|
onClick={() =>
|
|
|
|
this.toggleResetSettingsDialog()
|
|
|
|
}
|
|
|
|
>
|
|
|
|
Refresh
|
|
|
|
</Button>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemAvatar>
|
|
|
|
<UndoIcon color="action" />
|
|
|
|
</ListItemAvatar>
|
|
|
|
<ListItemText
|
|
|
|
primary={`Reset ${this.state.brandName}`}
|
|
|
|
secondary="Deletes all data and resets the app"
|
|
|
|
/>
|
|
|
|
<ListItemSecondaryAction>
|
|
|
|
<Button
|
|
|
|
onClick={() =>
|
|
|
|
this.toggleResetDialog()
|
|
|
|
}
|
|
|
|
>
|
|
|
|
Reset
|
|
|
|
</Button>
|
|
|
|
</ListItemSecondaryAction>
|
|
|
|
</ListItem>
|
|
|
|
</List>
|
|
|
|
</Paper>
|
|
|
|
{this.showThemeDialog()}
|
|
|
|
{this.showVisibilityDialog()}
|
|
|
|
{this.showResetDialog()}
|
|
|
|
{this.showResetSettingsDialog()}
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-03-27 22:39:25 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-18 19:52:39 +02:00
|
|
|
export default withStyles(styles)(SettingsPage);
|