Commit d93f0d10 authored by Philipp Wolfer's avatar Philipp Wolfer Committed by Georg Krause
Browse files

Allow using dark / light theme as indicated by prefers-color-scheme media feature

parent 742f843c
Allow using default browser dark mode and update UI dynamically on change
\ No newline at end of file
......@@ -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'
})
......
<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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment