* Auto theme preference added * Fix lint * Add and use AUTO from consts * Add shared custom hook to get current theme * Moved up 'Auto' choice * AUTO -> AUTO_THEME_ID & extract useCurrentTheme to file * Liberalise theme setting * Add tests
This commit is contained in:
@@ -15,11 +15,11 @@ import {
|
||||
setVolume,
|
||||
clearQueue,
|
||||
} from '../actions'
|
||||
import themes from '../themes'
|
||||
import config from '../config'
|
||||
import PlayerToolbar from './PlayerToolbar'
|
||||
import { sendNotification, baseUrl } from '../utils'
|
||||
import { keyMap } from '../hotkeys'
|
||||
import useCurrentTheme from '../themes/useCurrentTheme'
|
||||
|
||||
const useStyle = makeStyles((theme) => ({
|
||||
audioTitle: {
|
||||
@@ -58,8 +58,7 @@ const AudioTitle = React.memo(({ audioInfo, isMobile, className }) => {
|
||||
|
||||
const Player = () => {
|
||||
const translate = useTranslate()
|
||||
const currentTheme = useSelector((state) => state.theme)
|
||||
const theme = themes[currentTheme] || themes.DarkTheme
|
||||
const theme = useCurrentTheme()
|
||||
const playerTheme = (theme.player && theme.player.theme) || 'dark'
|
||||
const dataProvider = useDataProvider()
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export const REST_URL = '/app/api'
|
||||
|
||||
export const M3U_MIME_TYPE = 'audio/x-mpegurl'
|
||||
|
||||
export const AUTO_THEME_ID = 'AUTO_THEME_ID'
|
||||
|
||||
@@ -6,14 +6,14 @@ import { HotKeys } from 'react-hotkeys'
|
||||
import Menu from './Menu'
|
||||
import AppBar from './AppBar'
|
||||
import Notification from './Notification'
|
||||
import themes from '../themes'
|
||||
import useCurrentTheme from '../themes/useCurrentTheme'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: { paddingBottom: (props) => (props.addPadding ? '80px' : 0) },
|
||||
})
|
||||
|
||||
export default (props) => {
|
||||
const theme = useSelector((state) => themes[state.theme] || themes.DarkTheme)
|
||||
const theme = useCurrentTheme()
|
||||
const queue = useSelector((state) => state.queue)
|
||||
const classes = useStyles({ addPadding: queue.queue.length > 0 })
|
||||
const dispatch = useDispatch()
|
||||
|
||||
@@ -23,6 +23,7 @@ import themes from '../themes'
|
||||
import { docsUrl } from '../utils'
|
||||
import { useGetLanguageChoices } from '../i18n'
|
||||
import albumLists, { defaultAlbumList } from '../album/albumLists'
|
||||
import { AUTO_THEME_ID } from '../consts'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: { marginTop: '1em' },
|
||||
@@ -77,9 +78,17 @@ const SelectTheme = (props) => {
|
||||
const translate = useTranslate()
|
||||
const dispatch = useDispatch()
|
||||
const currentTheme = useSelector((state) => state.theme)
|
||||
const themeChoices = Object.keys(themes).map((key) => {
|
||||
return { id: key, name: themes[key].themeName }
|
||||
})
|
||||
const themeChoices = [
|
||||
{
|
||||
id: AUTO_THEME_ID,
|
||||
name: 'Auto',
|
||||
},
|
||||
]
|
||||
themeChoices.push(
|
||||
...Object.keys(themes).map((key) => {
|
||||
return { id: key, name: themes[key].themeName }
|
||||
})
|
||||
)
|
||||
themeChoices.push({
|
||||
id: helpKey,
|
||||
name: <HelpMsg caption={'Create your own'} />,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { useSelector } from 'react-redux'
|
||||
import useMediaQuery from '@material-ui/core/useMediaQuery'
|
||||
import themes from './index'
|
||||
import { AUTO_THEME_ID } from '../consts'
|
||||
|
||||
export default () => {
|
||||
const prefersLightMode = useMediaQuery('(prefers-color-scheme: light)')
|
||||
return useSelector((state) => {
|
||||
if (state.theme === AUTO_THEME_ID) {
|
||||
return prefersLightMode ? themes.LightTheme : themes.DarkTheme
|
||||
}
|
||||
return themes[state.theme] || themes.DarkTheme
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import React from 'react'
|
||||
import { Provider } from 'react-redux'
|
||||
import { createStore } from 'redux'
|
||||
import mediaQuery from 'css-mediaquery'
|
||||
import { renderHook } from '@testing-library/react-hooks'
|
||||
import useCurrentTheme from './useCurrentTheme'
|
||||
import { themeReducer } from '../reducers/themeReducer'
|
||||
import { AUTO_THEME_ID } from '../consts'
|
||||
|
||||
function createMatchMedia(theme) {
|
||||
return (query) => ({
|
||||
matches: mediaQuery.match(query, { 'prefers-color-scheme': theme }),
|
||||
addListener: () => {},
|
||||
removeListener: () => {},
|
||||
})
|
||||
}
|
||||
|
||||
describe('useCurrentTheme', () => {
|
||||
describe('with user preference theme as light', () => {
|
||||
beforeAll(() => {
|
||||
window.matchMedia = createMatchMedia('light')
|
||||
})
|
||||
it('sets theme as light in auto mode', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: AUTO_THEME_ID })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
expect(result.current.themeName).toMatch('Light')
|
||||
})
|
||||
it('sets theme as dark', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: 'DarkTheme' })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Dark')
|
||||
})
|
||||
it('sets theme as light', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: 'LightTheme' })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Light')
|
||||
})
|
||||
it('sets theme as spotify-ish', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider
|
||||
store={createStore(themeReducer, { theme: 'SpotifyTheme' })}
|
||||
>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Spotify-ish')
|
||||
})
|
||||
})
|
||||
describe('with user preference theme as dark', () => {
|
||||
beforeAll(() => {
|
||||
window.matchMedia = createMatchMedia('dark')
|
||||
})
|
||||
it('sets theme as dark in auto mode', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: AUTO_THEME_ID })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Dark')
|
||||
})
|
||||
it('sets theme as dark', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: 'DarkTheme' })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Dark')
|
||||
})
|
||||
it('sets theme as light', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider store={createStore(themeReducer, { theme: 'LightTheme' })}>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Light')
|
||||
})
|
||||
it('sets theme as spotify-ish', () => {
|
||||
const { result } = renderHook(() => useCurrentTheme(), {
|
||||
wrapper: ({ children }) => (
|
||||
<Provider
|
||||
store={createStore(themeReducer, { theme: 'SpotifyTheme' })}
|
||||
>
|
||||
{children}
|
||||
</Provider>
|
||||
),
|
||||
})
|
||||
|
||||
expect(result.current.themeName).toMatch('Spotify-ish')
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user