mirror of
https://github.com/mmjee/Piped-Material.git
synced 2024-12-06 19:26:36 +01:00
286 lines
7.6 KiB
Vue
286 lines
7.6 KiB
Vue
<template>
|
|
<v-app :style="bgStyles">
|
|
<v-app-bar
|
|
app
|
|
dense
|
|
color="appBarBG"
|
|
v-if="$vuetify.breakpoint.width > 1000 && !$store.getters['prefs/isEmbedded']"
|
|
class="desktop-buttons-container"
|
|
>
|
|
<v-btn icon link to="/" v-if="$store.getters['prefs/getPreferenceBoolean']('homepageButton')">
|
|
<v-icon>
|
|
{{ mdiHome }}
|
|
</v-icon>
|
|
</v-btn>
|
|
<v-btn
|
|
v-for="link in links" :key="link.id"
|
|
link
|
|
text
|
|
:to="link.to"
|
|
>
|
|
{{ $t(link.name) }}
|
|
</v-btn>
|
|
<AuthenticationModal />
|
|
<v-btn icon @click="toggleDarkMode">
|
|
<v-icon>{{ mdiBrightness6 }}</v-icon>
|
|
</v-btn>
|
|
<v-select
|
|
class="mt-6"
|
|
style="max-width: 15vw"
|
|
dense
|
|
:items="languageOptions"
|
|
label="Language"
|
|
:value="$i18n.locale"
|
|
@input="changeLocale"
|
|
outlined
|
|
/>
|
|
<SearchMenu class="search-menu" />
|
|
<!-- ^^^ The above breakpoint is manually determined to be the minimum sustainable width where everything works w/o overlapping -->
|
|
<!-- Might need changing when buttons change -->
|
|
<div class="desktop-buttons-container">
|
|
</div>
|
|
</v-app-bar>
|
|
<div v-else-if="!$store.getters['prefs/isEmbedded']">
|
|
<v-navigation-drawer
|
|
v-model="drawer"
|
|
app
|
|
>
|
|
<v-list nav>
|
|
<v-list-item
|
|
v-for="link in links"
|
|
:key="link.id"
|
|
link
|
|
:to="link.to"
|
|
>
|
|
{{ $t(link.name) }}
|
|
</v-list-item>
|
|
<AuthenticationModal :list-mode="true" />
|
|
</v-list>
|
|
<v-select
|
|
dense
|
|
outlined
|
|
class="mx-2 mt-2"
|
|
:label="$t('preferences.colorScheme')"
|
|
:value="$store.state.prefs.colorScheme"
|
|
@input="$store.commit('prefs/setColorScheme', { colorScheme: $event })"
|
|
:items="colorSchemeOptions"
|
|
/>
|
|
<v-select
|
|
dense
|
|
:items="languageOptions"
|
|
label="Language"
|
|
:value="$i18n.locale"
|
|
@input="changeLocale"
|
|
outlined
|
|
class="mx-2"
|
|
/>
|
|
</v-navigation-drawer>
|
|
|
|
<v-app-bar app dense light color="#efcac3">
|
|
<v-app-bar-nav-icon @click="drawer = !drawer"></v-app-bar-nav-icon>
|
|
|
|
<v-toolbar-title>Piped-Material</v-toolbar-title>
|
|
<v-spacer />
|
|
<v-dialog
|
|
v-model="searchMenuOpened"
|
|
fullscreen hide-overlay
|
|
transition="dialog-bottom-transition"
|
|
>
|
|
<template v-slot:activator="{ on, attrs }">
|
|
<v-btn
|
|
icon
|
|
large
|
|
v-bind="attrs"
|
|
v-on="on"
|
|
aria-label="Open Search Menu"
|
|
>
|
|
<v-icon>
|
|
{{ mdiMagnify }}
|
|
</v-icon>
|
|
</v-btn>
|
|
</template>
|
|
<v-card>
|
|
<v-toolbar
|
|
dark
|
|
color="primary"
|
|
>
|
|
<v-btn
|
|
icon
|
|
dark
|
|
@click="searchMenuOpened = false"
|
|
>
|
|
<v-icon>{{ mdiClose }}</v-icon>
|
|
</v-btn>
|
|
<v-toolbar-title>Search</v-toolbar-title>
|
|
</v-toolbar>
|
|
<v-card-text class="mt-2">
|
|
<SearchMenu @selected="searchMenuOpened = false" />
|
|
</v-card-text>
|
|
</v-card>
|
|
</v-dialog>
|
|
</v-app-bar>
|
|
</div>
|
|
|
|
<v-main>
|
|
<router-view />
|
|
</v-main>
|
|
</v-app>
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
.desktop-buttons-container {
|
|
* {
|
|
margin-right: 4px;
|
|
}
|
|
|
|
:last-child {
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
import { mdiBrightness6, mdiMagnify, mdiClose, mdiHome } from '@mdi/js'
|
|
|
|
import SearchMenu from '@/routes/SearchMenu'
|
|
import { changeLocale, SUPPORTED_LANGUAGES } from '@/plugins/i18n'
|
|
import AuthenticationModal from '@/components/AuthenticationModal'
|
|
import { COLOR_SCHEME_STATES } from '@/store/prefs-store'
|
|
|
|
export default {
|
|
name: 'App',
|
|
components: {
|
|
AuthenticationModal,
|
|
SearchMenu
|
|
},
|
|
metaInfo () {
|
|
return {
|
|
title: this.$t('titles.homepage'),
|
|
// all titles will be injected into this template
|
|
titleTemplate: '%s - Piped'
|
|
}
|
|
},
|
|
|
|
data: () => ({
|
|
drawer: false,
|
|
// Only used on phones
|
|
searchMenuOpened: false,
|
|
|
|
mdiBrightness6,
|
|
mdiMagnify,
|
|
mdiClose,
|
|
mdiHome
|
|
}),
|
|
|
|
computed: {
|
|
bgStyles () {
|
|
return {
|
|
backgroundColor: this.$vuetify.theme.currentTheme.bgOne
|
|
}
|
|
},
|
|
|
|
colorSchemeOptions () {
|
|
return [
|
|
{ text: this.$t('actions.auto'), value: COLOR_SCHEME_STATES.SYSTEM },
|
|
{ text: this.$t('actions.light'), value: COLOR_SCHEME_STATES.LIGHT },
|
|
{ text: this.$t('actions.dark'), value: COLOR_SCHEME_STATES.DARK }
|
|
]
|
|
},
|
|
|
|
links () {
|
|
const links = [
|
|
{
|
|
id: 'trending',
|
|
name: 'titles.trending',
|
|
to: '/trending'
|
|
},
|
|
{
|
|
id: 'prefs',
|
|
name: 'titles.preferences',
|
|
to: '/preferences'
|
|
},
|
|
{
|
|
id: 'watch-history',
|
|
name: 'titles.history',
|
|
to: '/watch-history'
|
|
}
|
|
]
|
|
|
|
if (this.$store.getters['auth/isCurrentlyAuthenticated']) {
|
|
links.splice(0, 0, {
|
|
id: 'feed',
|
|
name: 'titles.feed',
|
|
to: '/feed'
|
|
})
|
|
links.push({
|
|
id: 'playlists',
|
|
name: 'titles.playlists',
|
|
to: '/playlists'
|
|
})
|
|
}
|
|
|
|
return links
|
|
},
|
|
|
|
languageOptions () {
|
|
return SUPPORTED_LANGUAGES.map(code => {
|
|
return {
|
|
text: this.$store.getters['i18n/fmtLanguage'](code),
|
|
value: code
|
|
}
|
|
}).sort((a, b) => this.$store.getters['i18n/compare'](a.text, b.text))
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
changeLocale (lang) {
|
|
return changeLocale(lang)
|
|
},
|
|
|
|
toggleDarkMode () {
|
|
let colorSchemeState
|
|
const newDarkState = !this.$store.state.prefs.colorScheme
|
|
|
|
if (newDarkState) {
|
|
colorSchemeState = COLOR_SCHEME_STATES.DARK
|
|
} else {
|
|
colorSchemeState = COLOR_SCHEME_STATES.LIGHT
|
|
}
|
|
|
|
this.$store.commit('prefs/setColorScheme', {
|
|
colorScheme: colorSchemeState
|
|
})
|
|
},
|
|
|
|
syncDarkMode (newVal) {
|
|
switch (newVal) {
|
|
case COLOR_SCHEME_STATES.SYSTEM:
|
|
this.$vuetify.theme.dark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
break
|
|
case COLOR_SCHEME_STATES.DARK:
|
|
this.$vuetify.theme.dark = true
|
|
break
|
|
case COLOR_SCHEME_STATES.LIGHT:
|
|
this.$vuetify.theme.dark = false
|
|
break
|
|
}
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
'$store.state.prefs.colorScheme': {
|
|
handler (v) {
|
|
return this.syncDarkMode(v)
|
|
},
|
|
immedate: true
|
|
},
|
|
'$store.state.i18n.rtl': {
|
|
handler (newVal) {
|
|
this.$vuetify.rtl = newVal
|
|
},
|
|
immediate: true
|
|
}
|
|
}
|
|
}
|
|
</script>
|