Allow using dark / light theme as indicated by prefers-color-scheme media feature
This commit is contained in:
parent
742f843c98
commit
d93f0d107d
|
@ -0,0 +1 @@
|
|||
Allow using default browser dark mode and update UI dynamically on change
|
|
@ -129,6 +129,12 @@ export default {
|
|||
return this.$store.state.instance.frontSettings.additionalStylesheets || []
|
||||
}
|
||||
return null
|
||||
},
|
||||
matchDarkColorScheme () {
|
||||
if (window.matchMedia) {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)')
|
||||
}
|
||||
return null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -138,10 +144,21 @@ export default {
|
|||
},
|
||||
'$store.state.ui.theme': {
|
||||
immediate: true,
|
||||
handler (newValue, oldValue) {
|
||||
const oldTheme = oldValue || 'light'
|
||||
document.body.classList.remove(`theme-${oldTheme}`)
|
||||
document.body.classList.add(`theme-${newValue}`)
|
||||
handler (newValue) {
|
||||
const matchesDark = this.matchDarkColorScheme
|
||||
if (matchesDark) {
|
||||
if (newValue === 'system') {
|
||||
newValue = matchesDark.matches ? 'dark' : 'light'
|
||||
matchesDark.addEventListener('change', this.handleThemeChange)
|
||||
} else {
|
||||
matchesDark.removeEventListener('change', this.handleThemeChange)
|
||||
}
|
||||
} else {
|
||||
if (newValue === 'system') {
|
||||
newValue = 'light'
|
||||
}
|
||||
}
|
||||
this.setTheme(newValue)
|
||||
}
|
||||
},
|
||||
'$store.state.auth.authenticated' (newValue) {
|
||||
|
@ -451,6 +468,14 @@ export default {
|
|||
},
|
||||
handleResize () {
|
||||
this.width = window.innerWidth
|
||||
},
|
||||
handleThemeChange (event) {
|
||||
this.setTheme(event.matches ? 'dark' : 'light')
|
||||
},
|
||||
setTheme (theme) {
|
||||
const oldTheme = (theme === 'light') ? 'dark' : 'light'
|
||||
document.body.classList.remove(`theme-${oldTheme}`)
|
||||
document.body.classList.add(`theme-${theme}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,9 +212,11 @@
|
|||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import ThemesMixin from '@/components/mixins/Themes'
|
||||
import _ from '@/lodash'
|
||||
|
||||
export default {
|
||||
mixins: [ThemesMixin],
|
||||
props: { version: { type: String, required: true } },
|
||||
computed: {
|
||||
...mapState({
|
||||
|
@ -229,18 +231,6 @@ export default {
|
|||
const parser = document.createElement('a')
|
||||
parser.href = url
|
||||
return parser.hostname
|
||||
},
|
||||
themes () {
|
||||
return [
|
||||
{
|
||||
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Light'),
|
||||
key: 'light'
|
||||
},
|
||||
{
|
||||
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Dark'),
|
||||
key: 'dark'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -475,6 +475,7 @@ import { mapState, mapActions, mapGetters } from 'vuex'
|
|||
import UserModal from '@/components/common/UserModal'
|
||||
import Logo from '@/components/Logo'
|
||||
import SearchBar from '@/components/audio/SearchBar'
|
||||
import ThemesMixin from '@/components/mixins/Themes'
|
||||
import UserMenu from '@/components/common/UserMenu'
|
||||
import Modal from '@/components/semantic/Modal'
|
||||
|
||||
|
@ -489,6 +490,7 @@ export default {
|
|||
UserModal,
|
||||
Modal
|
||||
},
|
||||
mixins: [ThemesMixin],
|
||||
props: {
|
||||
width: { type: Number, required: true }
|
||||
},
|
||||
|
@ -589,18 +591,6 @@ export default {
|
|||
},
|
||||
production () {
|
||||
return process.env.NODE_ENV === 'production'
|
||||
},
|
||||
themes () {
|
||||
return [
|
||||
{
|
||||
name: this.$pgettext('Sidebar/Settings/Dropdown.Label/Theme name', 'Light'),
|
||||
key: 'light'
|
||||
},
|
||||
{
|
||||
name: this.$pgettext('Sidebar/Settings/Dropdown.Label/Theme name', 'Dark'),
|
||||
key: 'dark'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
|
@ -155,7 +155,10 @@
|
|||
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import ThemesMixin from '@/components/mixins/Themes'
|
||||
|
||||
export default {
|
||||
mixins: [ThemesMixin],
|
||||
computed: {
|
||||
labels () {
|
||||
return {
|
||||
|
@ -176,20 +179,6 @@ export default {
|
|||
notifications: this.$pgettext('*/Notifications/*', 'Notifications')
|
||||
}
|
||||
},
|
||||
themes () {
|
||||
return [
|
||||
{
|
||||
icon: 'sun icon',
|
||||
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Light'),
|
||||
key: 'light'
|
||||
},
|
||||
{
|
||||
icon: 'moon icon',
|
||||
name: this.$pgettext('Footer/Settings/Dropdown.Label/Theme name', 'Dark'),
|
||||
key: 'dark'
|
||||
}
|
||||
]
|
||||
},
|
||||
...mapGetters({
|
||||
additionalNotifications: 'ui/additionalNotifications'
|
||||
})
|
||||
|
|
|
@ -175,12 +175,14 @@
|
|||
|
||||
<script>
|
||||
import Modal from '@/components/semantic/Modal'
|
||||
import ThemesMixin from '@/components/mixins/Themes'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
mixins: [ThemesMixin],
|
||||
props: {
|
||||
show: { type: Boolean, required: true }
|
||||
},
|
||||
|
@ -216,26 +218,6 @@ export default {
|
|||
)
|
||||
}
|
||||
},
|
||||
themes () {
|
||||
return [
|
||||
{
|
||||
icon: 'sun icon',
|
||||
name: this.$pgettext(
|
||||
'Footer/Settings/Dropdown.Label/Theme name',
|
||||
'Light'
|
||||
),
|
||||
key: 'light'
|
||||
},
|
||||
{
|
||||
icon: 'moon icon',
|
||||
name: this.$pgettext(
|
||||
'Footer/Settings/Dropdown.Label/Theme name',
|
||||
'Dark'
|
||||
),
|
||||
key: 'dark'
|
||||
}
|
||||
]
|
||||
},
|
||||
...mapGetters({
|
||||
additionalNotifications: 'ui/additionalNotifications'
|
||||
})
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
themes () {
|
||||
return [
|
||||
{
|
||||
icon: 'palette icon',
|
||||
name: this.$pgettext('*/Settings/Dropdown.Label/Theme name', 'Browser default'),
|
||||
key: 'system'
|
||||
},
|
||||
{
|
||||
icon: 'sun icon',
|
||||
name: this.$pgettext('*/Settings/Dropdown.Label/Theme name', 'Light'),
|
||||
key: 'light'
|
||||
},
|
||||
{
|
||||
icon: 'moon icon',
|
||||
name: this.$pgettext('*/Settings/Dropdown.Label/Theme name', 'Dark'),
|
||||
key: 'dark'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -13,7 +13,7 @@ export default {
|
|||
messageDisplayDuration: 5 * 1000,
|
||||
supportedExtensions: ['flac', 'ogg', 'mp3', 'opus', 'aac', 'm4a', 'aiff', 'aif'],
|
||||
messages: [],
|
||||
theme: 'light',
|
||||
theme: 'system',
|
||||
window: {
|
||||
height: 0,
|
||||
width: 0
|
||||
|
|
Loading…
Reference in New Issue