Add setting for system-determined dark mode
This commit is contained in:
parent
bd926d31c4
commit
f2e384ad97
|
@ -28,10 +28,11 @@ import {canSendNotifications, browserSupportsNotificationRequests} from '../util
|
||||||
import {themes, defaultTheme} from '../types/HyperspaceTheme';
|
import {themes, defaultTheme} from '../types/HyperspaceTheme';
|
||||||
import ThemePreview from '../components/ThemePreview';
|
import ThemePreview from '../components/ThemePreview';
|
||||||
import {setHyperspaceTheme, getHyperspaceTheme} from '../utilities/themes';
|
import {setHyperspaceTheme, getHyperspaceTheme} from '../utilities/themes';
|
||||||
import { Visibility, toVisibility } from '../types/Visibility';
|
import { Visibility } from '../types/Visibility';
|
||||||
|
|
||||||
interface ISettingsState {
|
interface ISettingsState {
|
||||||
darkModeEnabled: boolean;
|
darkModeEnabled: boolean;
|
||||||
|
systemDecidesDarkMode: boolean;
|
||||||
pushNotificationsEnabled: boolean;
|
pushNotificationsEnabled: boolean;
|
||||||
badgeDisplaysAllNotifs: boolean;
|
badgeDisplaysAllNotifs: boolean;
|
||||||
selectThemeName: string;
|
selectThemeName: string;
|
||||||
|
@ -50,6 +51,7 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
darkModeEnabled: getUserDefaultBool('darkModeEnabled'),
|
darkModeEnabled: getUserDefaultBool('darkModeEnabled'),
|
||||||
|
systemDecidesDarkMode: getUserDefaultBool('systemDecidesDarkMode'),
|
||||||
pushNotificationsEnabled: canSendNotifications(),
|
pushNotificationsEnabled: canSendNotifications(),
|
||||||
badgeDisplaysAllNotifs: getUserDefaultBool('displayAllOnNotificationBadge'),
|
badgeDisplaysAllNotifs: getUserDefaultBool('displayAllOnNotificationBadge'),
|
||||||
selectThemeName: getUserDefaultTheme().key,
|
selectThemeName: getUserDefaultTheme().key,
|
||||||
|
@ -62,6 +64,7 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.toggleDarkMode = this.toggleDarkMode.bind(this);
|
this.toggleDarkMode = this.toggleDarkMode.bind(this);
|
||||||
|
this.toggleSystemDarkMode = this.toggleSystemDarkMode.bind(this);
|
||||||
this.togglePushNotifications = this.togglePushNotifications.bind(this);
|
this.togglePushNotifications = this.togglePushNotifications.bind(this);
|
||||||
this.toggleBadgeCount = this.toggleBadgeCount.bind(this);
|
this.toggleBadgeCount = this.toggleBadgeCount.bind(this);
|
||||||
this.toggleThemeDialog = this.toggleThemeDialog.bind(this);
|
this.toggleThemeDialog = this.toggleThemeDialog.bind(this);
|
||||||
|
@ -77,6 +80,12 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleSystemDarkMode() {
|
||||||
|
this.setState({ systemDecidesDarkMode: !this.state.systemDecidesDarkMode });
|
||||||
|
setUserDefaultBool('systemDecidesDarkMode', !this.state.systemDecidesDarkMode);
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
togglePushNotifications() {
|
togglePushNotifications() {
|
||||||
this.setState({ pushNotificationsEnabled: !this.state.pushNotificationsEnabled });
|
this.setState({ pushNotificationsEnabled: !this.state.pushNotificationsEnabled });
|
||||||
setUserDefaultBool('enablePushNotifications', !this.state.pushNotificationsEnabled);
|
setUserDefaultBool('enablePushNotifications', !this.state.pushNotificationsEnabled);
|
||||||
|
@ -269,10 +278,23 @@ class SettingsPage extends Component<any, ISettingsState> {
|
||||||
<ListSubheader>Appearance</ListSubheader>
|
<ListSubheader>Appearance</ListSubheader>
|
||||||
<Paper className={classes.pageListConstraints}>
|
<Paper className={classes.pageListConstraints}>
|
||||||
<List>
|
<List>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemText primary="Match system appearance" secondary="Obey light/dark mode from your system"/>
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Switch
|
||||||
|
checked={this.state.systemDecidesDarkMode}
|
||||||
|
onChange={this.toggleSystemDarkMode}
|
||||||
|
/>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary="Dark mode"/>
|
<ListItemText primary="Dark mode"/>
|
||||||
<ListItemSecondaryAction>
|
<ListItemSecondaryAction>
|
||||||
<Switch checked={this.state.darkModeEnabled} onChange={this.toggleDarkMode}/>
|
<Switch
|
||||||
|
disabled={this.state.systemDecidesDarkMode}
|
||||||
|
checked={this.state.darkModeEnabled}
|
||||||
|
onChange={this.toggleDarkMode}
|
||||||
|
/>
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Color} from '@material-ui/core';
|
import {Color} from '@material-ui/core';
|
||||||
import { deepPurple, red, lightGreen, yellow, purple, deepOrange, indigo, lightBlue, orange, blue, amber, pink, brown } from '@material-ui/core/colors';
|
import { deepPurple, red, lightGreen, yellow, purple, deepOrange, indigo, lightBlue, orange, blue, amber, pink, brown, blueGrey } from '@material-ui/core/colors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic theme colors for Hyperspace.
|
* Basic theme colors for Hyperspace.
|
||||||
|
@ -8,8 +8,12 @@ export type HyperspaceTheme = {
|
||||||
key: string;
|
key: string;
|
||||||
name: string;
|
name: string;
|
||||||
palette: {
|
palette: {
|
||||||
primary: Color;
|
primary: {
|
||||||
secondary: Color;
|
main: string;
|
||||||
|
} | Color;
|
||||||
|
secondary: {
|
||||||
|
main: string;
|
||||||
|
} | Color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,9 +120,24 @@ export const blissTheme: HyperspaceTheme = {
|
||||||
key: "blissTheme",
|
key: "blissTheme",
|
||||||
name: "Bliss",
|
name: "Bliss",
|
||||||
palette: {
|
palette: {
|
||||||
primary: brown,
|
primary: {
|
||||||
|
main: "#3e2723"
|
||||||
|
},
|
||||||
secondary: lightBlue
|
secondary: lightBlue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const themes = [defaultTheme, gardenerTheme, teacherTheme, jokerTheme, brotherTheme, guardTheme, scientistTheme, entertainerTheme, kingTheme, dragonTheme, memoriumTheme, blissTheme]
|
export const attractTheme: HyperspaceTheme = {
|
||||||
|
key: "attractTheme",
|
||||||
|
name: "Attract",
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: '#f5f5f5',
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#1a237e",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const themes = [defaultTheme, gardenerTheme, teacherTheme, jokerTheme, brotherTheme, guardTheme, scientistTheme, entertainerTheme, kingTheme, dragonTheme, memoriumTheme, blissTheme, attractTheme]
|
|
@ -7,9 +7,11 @@ import { Visibility } from "../types/Visibility";
|
||||||
type SettingsTemplate = {
|
type SettingsTemplate = {
|
||||||
[key:string]: any;
|
[key:string]: any;
|
||||||
darkModeEnabled: boolean;
|
darkModeEnabled: boolean;
|
||||||
|
systemDecidesDarkMode: boolean;
|
||||||
enablePushNotifications: boolean;
|
enablePushNotifications: boolean;
|
||||||
clearNotificationsOnRead: boolean;
|
clearNotificationsOnRead: boolean;
|
||||||
displayAllOnNotificationBadge: boolean;
|
displayAllOnNotificationBadge: boolean;
|
||||||
|
defaultVisibility: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,13 +91,14 @@ export function setUserDefaultTheme(themeName: string) {
|
||||||
export function createUserDefaults() {
|
export function createUserDefaults() {
|
||||||
let defaults: SettingsTemplate = {
|
let defaults: SettingsTemplate = {
|
||||||
darkModeEnabled: false,
|
darkModeEnabled: false,
|
||||||
|
systemDecidesDarkMode: true,
|
||||||
enablePushNotifications: true,
|
enablePushNotifications: true,
|
||||||
clearNotificationsOnRead: false,
|
clearNotificationsOnRead: false,
|
||||||
displayAllOnNotificationBadge: false,
|
displayAllOnNotificationBadge: false,
|
||||||
defaultVisibility: "public"
|
defaultVisibility: "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
let settings = ["darkModeEnabled", "clearNotificationsOnRead", "displayAllOnNotificationBadge", "defaultVisibility"];
|
let settings = ["darkModeEnabled", "systemDecidesDarkMode", "clearNotificationsOnRead", "displayAllOnNotificationBadge", "defaultVisibility"];
|
||||||
settings.forEach((setting: string) => {
|
settings.forEach((setting: string) => {
|
||||||
if (localStorage.getItem(setting) === null) {
|
if (localStorage.getItem(setting) === null) {
|
||||||
if (typeof defaults[setting] === "boolean") {
|
if (typeof defaults[setting] === "boolean") {
|
||||||
|
|
|
@ -42,11 +42,24 @@ export function setHyperspaceTheme(theme: HyperspaceTheme): Theme {
|
||||||
palette: {
|
palette: {
|
||||||
primary: theme.palette.primary,
|
primary: theme.palette.primary,
|
||||||
secondary: theme.palette.secondary,
|
secondary: theme.palette.secondary,
|
||||||
type: getUserDefaultBool('darkModeEnabled')? "dark": "light"
|
type: getUserDefaultBool('darkModeEnabled')? "dark":
|
||||||
|
getDarkModeFromSystem() === "dark"? "dark": "light"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getDarkModeFromSystem(): string {
|
||||||
|
if (getUserDefaultBool('systemDecidesDarkMode')) {
|
||||||
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||||
|
return "dark";
|
||||||
|
} else {
|
||||||
|
return "light";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "light";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the app's palette type (aka. turns on an off dark mode)
|
* Sets the app's palette type (aka. turns on an off dark mode)
|
||||||
* @param theme The Material-UI theme to toggle the dark mode on
|
* @param theme The Material-UI theme to toggle the dark mode on
|
||||||
|
|
Loading…
Reference in New Issue