From f041503a854814fddd85ed19305fa2df723dce37 Mon Sep 17 00:00:00 2001 From: Deluan Date: Tue, 31 Mar 2020 09:35:44 -0400 Subject: [PATCH] feat: simple theme selector. only works with hardcoded `light` and `dark` for now --- ui/src/App.js | 11 +++---- ui/src/configuration/Configuration.js | 46 +++++++++++++++++++++++++++ ui/src/configuration/actions.js | 6 ++++ ui/src/configuration/themeReducer.js | 8 +++++ ui/src/i18n/en.js | 10 +++++- ui/src/layout/AppBar.js | 24 ++++++++++++-- ui/src/layout/Layout.js | 10 +++++- ui/src/routes.js | 7 ++++ 8 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 ui/src/configuration/Configuration.js create mode 100644 ui/src/configuration/actions.js create mode 100644 ui/src/configuration/themeReducer.js create mode 100644 ui/src/routes.js diff --git a/ui/src/App.js b/ui/src/App.js index 6a8a466a0..ec968190a 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -5,18 +5,16 @@ import authProvider from './authProvider' import polyglotI18nProvider from 'ra-i18n-polyglot' import messages from './i18n' import { Layout, Login } from './layout' -import { DarkTheme } from './themes' import transcoding from './transcoding' import player from './player' import user from './user' import song from './song' import album from './album' import artist from './artist' -import { createMuiTheme } from '@material-ui/core/styles' import { Player, playQueueReducer } from './audioplayer' import { albumViewReducer } from './album/albumState' - -const theme = createMuiTheme(DarkTheme) +import customRoutes from './routes' +import themeReducer from './configuration/themeReducer' const i18nProvider = polyglotI18nProvider( (locale) => (messages[locale] ? messages[locale] : messages.en), @@ -35,14 +33,15 @@ const App = () => { return ( diff --git a/ui/src/configuration/Configuration.js b/ui/src/configuration/Configuration.js new file mode 100644 index 000000000..dd5979eed --- /dev/null +++ b/ui/src/configuration/Configuration.js @@ -0,0 +1,46 @@ +import React from 'react' +import { useSelector, useDispatch } from 'react-redux' +import Card from '@material-ui/core/Card' +import CardContent from '@material-ui/core/CardContent' +import Button from '@material-ui/core/Button' +import { useTranslate, Title } from 'react-admin' +import { makeStyles } from '@material-ui/core/styles' +import { changeTheme } from './actions' + +const useStyles = makeStyles({ + label: { width: '10em', display: 'inline-block' }, + button: { margin: '1em' } +}) + +const Configuration = () => { + const translate = useTranslate() + const classes = useStyles() + const theme = useSelector((state) => state.theme) + const dispatch = useDispatch() + return ( + + + <CardContent> + <div className={classes.label}>{translate('menu.theme.name')}</div> + <Button + variant="contained" + className={classes.button} + color={theme === 'light' ? 'primary' : 'default'} + onClick={() => dispatch(changeTheme('light'))} + > + {translate('theme.light')} + </Button> + <Button + variant="contained" + className={classes.button} + color={theme === 'dark' ? 'primary' : 'default'} + onClick={() => dispatch(changeTheme('dark'))} + > + {translate('theme.dark')} + </Button> + </CardContent> + </Card> + ) +} + +export default Configuration diff --git a/ui/src/configuration/actions.js b/ui/src/configuration/actions.js new file mode 100644 index 000000000..bbfbbf995 --- /dev/null +++ b/ui/src/configuration/actions.js @@ -0,0 +1,6 @@ +export const CHANGE_THEME = 'CHANGE_THEME' + +export const changeTheme = (theme) => ({ + type: CHANGE_THEME, + payload: theme +}) diff --git a/ui/src/configuration/themeReducer.js b/ui/src/configuration/themeReducer.js new file mode 100644 index 000000000..71141b90d --- /dev/null +++ b/ui/src/configuration/themeReducer.js @@ -0,0 +1,8 @@ +import { CHANGE_THEME } from './actions' + +export default (previousState = 'dark', { type, payload }) => { + if (type === CHANGE_THEME) { + return payload + } + return previousState +} diff --git a/ui/src/i18n/en.js b/ui/src/i18n/en.js index 9e3654f9a..c75c3369c 100644 --- a/ui/src/i18n/en.js +++ b/ui/src/i18n/en.js @@ -44,7 +44,15 @@ export default deepmerge(englishMessages, { }, menu: { library: 'Library', - settings: 'Settings' + settings: 'Settings', + configuration: 'Configuration', + theme: { + name: 'Theme' + } + }, + theme: { + dark: 'Dark', + light: 'Light' }, player: { panelTitle: 'Play Queue', diff --git a/ui/src/layout/AppBar.js b/ui/src/layout/AppBar.js index 130db4e1b..793b27257 100644 --- a/ui/src/layout/AppBar.js +++ b/ui/src/layout/AppBar.js @@ -1,8 +1,27 @@ import React, { forwardRef } from 'react' -import { AppBar as RAAppBar, UserMenu, MenuItemLink } from 'react-admin' +import { + AppBar as RAAppBar, + UserMenu, + MenuItemLink, + useTranslate +} from 'react-admin' import InfoIcon from '@material-ui/icons/Info' +import TuneIcon from '@material-ui/icons/Tune' -const ConfigurationMenu = forwardRef(({ onClick }, ref) => ( +const ConfigurationMenu = forwardRef(({ onClick }, ref) => { + const translate = useTranslate() + return ( + <MenuItemLink + ref={ref} + to="/configuration" + primaryText={translate('menu.configuration')} + leftIcon={<TuneIcon />} + onClick={onClick} + /> + ) +}) + +const VersionMenu = forwardRef(({ onClick }, ref) => ( <MenuItemLink ref={ref} to="" @@ -15,6 +34,7 @@ const ConfigurationMenu = forwardRef(({ onClick }, ref) => ( const CustomUserMenu = (props) => ( <UserMenu {...props}> <ConfigurationMenu /> + <VersionMenu /> </UserMenu> ) diff --git a/ui/src/layout/Layout.js b/ui/src/layout/Layout.js index f82225b12..056c8f0c1 100644 --- a/ui/src/layout/Layout.js +++ b/ui/src/layout/Layout.js @@ -1,6 +1,14 @@ import React from 'react' +import { useSelector } from 'react-redux' import { Layout } from 'react-admin' import Menu from './Menu' import AppBar from './AppBar' +import { DarkTheme, LightTheme } from '../themes' -export default (props) => <Layout {...props} menu={Menu} appBar={AppBar} /> +export default (props) => { + const theme = useSelector((state) => + state.theme === 'dark' ? DarkTheme : LightTheme + ) + + return <Layout {...props} menu={Menu} appBar={AppBar} theme={theme} /> +} diff --git a/ui/src/routes.js b/ui/src/routes.js new file mode 100644 index 000000000..77322dc00 --- /dev/null +++ b/ui/src/routes.js @@ -0,0 +1,7 @@ +import React from 'react' +import { Route } from 'react-router-dom' +import Configuration from './configuration/Configuration' + +export default [ + <Route exact path="/configuration" render={() => <Configuration />} /> +]