111 lines
3.0 KiB
Vue
111 lines
3.0 KiB
Vue
<script setup lang="ts">
|
||
import { watchEffect, computed, onMounted, nextTick } from 'vue'
|
||
|
||
import { type QueueTrack, useQueue } from '~/composables/audio/queue'
|
||
import { useStore } from '~/store'
|
||
import useLogger from '~/composables/useLogger'
|
||
import { useLocalStorage, useStyleTag, useIntervalFn} from '@vueuse/core'
|
||
import { color } from '~/composables/color';
|
||
|
||
import { generateTrackCreditStringFromQueue } from '~/utils/utils'
|
||
|
||
// TODO: Check if these modals are still needed:
|
||
// import ChannelUploadModal from '~/components/channels/UploadModal.vue'
|
||
// import PlaylistModal from '~/components/playlists/PlaylistModal.vue'
|
||
// import FilterModal from '~/components/moderation/FilterModal.vue'
|
||
// import ReportModal from '~/components/moderation/ReportModal.vue'
|
||
// import ServiceMessages from '~/components/ServiceMessages.vue'
|
||
// TODO: Modernise and add player/queue:
|
||
import AudioPlayer from '~/components/audio/Player.vue'
|
||
// import Queue from '~/components/Queue.vue'
|
||
import Sidebar from '~/ui/components/Sidebar.vue'
|
||
import ShortcutsModal from '~/ui/modals/Shortcuts.vue'
|
||
import LanguagesModal from '~/ui/modals/Languages.vue'
|
||
import UploadModal from '~/ui/modals/Upload.vue';
|
||
|
||
// Fake content
|
||
onMounted(async () => {
|
||
await nextTick()
|
||
document.getElementById('fake-app')?.remove()
|
||
})
|
||
|
||
const logger = useLogger()
|
||
logger.debug('App setup()')
|
||
|
||
const store = useStore()
|
||
|
||
// Tracks
|
||
const { currentTrack } = useQueue()
|
||
const getTrackInformationText = (track: QueueTrack | undefined) => {
|
||
if (!track) {
|
||
return null
|
||
}
|
||
|
||
return `♫ ${track.title} – ${generateTrackCreditStringFromQueue(track)} ♫`
|
||
}
|
||
|
||
// Update title
|
||
const initialTitle = document.title
|
||
watchEffect(() => {
|
||
const parts = [
|
||
getTrackInformationText(currentTrack.value),
|
||
store.state.ui.pageTitle,
|
||
initialTitle || 'Funkwhale'
|
||
]
|
||
|
||
document.title = parts.filter(i => i).join(' – ')
|
||
})
|
||
|
||
// Styles
|
||
useStyleTag(computed(() => store.state.instance.settings.ui.custom_css.value))
|
||
|
||
// Fake content
|
||
onMounted(async () => {
|
||
await nextTick()
|
||
document.getElementById('fake-content')?.classList.add('loaded')
|
||
})
|
||
|
||
// Time ago
|
||
useIntervalFn(() => {
|
||
// used to redraw ago dates every minute
|
||
store.commit('ui/computeLastDate')
|
||
}, 1000 * 60)
|
||
|
||
// Fetch user data on startup
|
||
// NOTE: We're not checking if we're authenticated in the store,
|
||
// because we want to learn if we are authenticated at all
|
||
store.dispatch('auth/fetchUser')
|
||
|
||
</script>
|
||
|
||
<template>
|
||
<div class="funkwhale responsive">
|
||
<Sidebar />
|
||
<RouterView v-bind="color({}, ['default', 'solid'])()" />
|
||
<AudioPlayer />
|
||
<LanguagesModal />
|
||
<ShortcutsModal />
|
||
<UploadModal />
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
.responsive {
|
||
display: grid !important;
|
||
grid-template-columns: 100%;
|
||
grid-template-rows: min-content;
|
||
min-height: 100vh;
|
||
|
||
@media screen and (min-width: 1024px) {
|
||
grid-template-columns: 300px 5fr;
|
||
grid-template-rows: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<style>
|
||
/* Make inert pages (behind modals) unscrollable */
|
||
body:has(#app[inert="true"]) {
|
||
overflow:hidden;
|
||
}
|
||
</style>
|