refactor(front): [WIP] implement new layout for Album base page

This commit is contained in:
ArneBo 2025-01-17 13:01:59 +01:00
parent 4b167437c0
commit be492901dc
1 changed files with 81 additions and 230 deletions

View File

@ -7,10 +7,12 @@ import { useI18n } from 'vue-i18n'
import { useRouter, useRoute } from 'vue-router'
import { sum } from 'lodash-es'
import { useStore } from '~/store'
import { useQueue } from '~/composables/audio/queue'
import axios from 'axios'
import ArtistCreditLabel from '~/components/audio/ArtistCreditLabel.vue'
import TrackFavoriteIcon from '~/components/favorites/TrackFavoriteIcon.vue'
import PlayButton from '~/components/audio/PlayButton.vue'
import TagsList from '~/components/tags/List.vue'
import AlbumDropdown from './AlbumDropdown.vue'
@ -18,6 +20,7 @@ import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Loader from '~/components/ui/Loader.vue'
import Section from '~/components/ui/Section.vue'
import Button from '~/components/ui/Button.vue'
import useErrorHandler from '~/composables/useErrorHandler'
import useLogger from '~/composables/useLogger'
@ -58,10 +61,17 @@ const publicLibraries = computed(() => libraries.value?.filter(library => librar
const logger = useLogger()
const { t } = useI18n()
const labels = computed(() => ({
title: t('components.library.AlbumBase.title')
title: t('components.library.AlbumBase.title'),
shuffle: t('components.audio.Player.label.shuffleQueue')
}))
const {
isShuffled,
shuffle,
} = useQueue()
const isLoading = ref(false)
const fetchData = async () => {
isLoading.value = true
@ -146,7 +156,6 @@ const remove = async () => {
v-title="labels.title"
/>
<template v-if="object">
<!-- Image -->
<Layout flex>
<img
v-if="object.cover && object.cover.urls.original"
@ -176,19 +185,65 @@ const remove = async () => {
/>
<!-- Metadata: -->
<div>
<!-- EP -->
 · 
<!-- 2022 -->
 · 
<!-- 7 tracks -->
<template v-if="object.release_date">
{{ momentFormat(new Date(object.release_date ?? '1970-01-01'), 'Y') }}
<i class="bi bi-dot" />
</template>
<template v-if="totalTracks > 0">
<span v-if="isSerie">
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
</span>
<span v-else>
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
</span>
</template>
<i v-if="totalDuration > 0" class="bi bi-dot" />
<human-duration
v-if="totalDuration > 0"
:duration="totalDuration"
/>
<i v-if="object.tags && object.tags.length > 0" class="bi bi-dot" />
<!--TODO: License -->
<TagsList
v-if="object.tags && object.tags.length > 0"
:tags="object.tags"
/>
</div>
<Layout flex>
<!-- Pause -->
<!-- Shuffle -->
<Spacer h grow />
<!-- Herzchen -->
<rendered-description
v-if="object.description"
:content="object.description"
:can-update="false"
/>
</Layout>
<Layout flex>
<PlayButton
class="vibrant"
:tracks="object.tracks"
:is-playable="object.is_playable"
/>
<Button
primary
icon="bi-shuffle"
:disabled="object.tracks.length < 2"
:aria-label="labels.shuffle"
@click.prevent.stop="shuffle()"
>
{{ labels.shuffle }}
</Button>
<Spacer h grow />
<TrackFavoriteIcon v-if="store.state.auth.authenticated" :album="object" />
<!-- Button mit Pfeilchen -->
<!-- OptionsButton / -->
<album-dropdown
:object="object"
:public-libraries="publicLibraries"
:is-loading="isLoading"
:is-album="isAlbum"
:is-serie="isSerie"
:is-channel="isChannel"
:artist-credit="artistCredit"
@remove="remove"
/>
</Layout>
</Layout>
</Section>
@ -202,224 +257,20 @@ const remove = async () => {
<!-- 1 selected -->
</Layout>
<!-- hier die einzelnen Tracks -->
<!-- Reference: -->
<section class="segment channel-serie">
<Layout flex gap-64 style="align-content: stretch;">
<div style="flex: 2;">
<div
v-if="isSerie"
class="padded basic segment"
>
<div
v-if="isSerie"
class="ui two column grid"
>
<div class="column">
<div class="large two-images">
<img
v-if="object.cover && object.cover.urls.original"
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
alt=""
class="channel-image"
>
<img
v-else
alt=""
class="channel-image"
src="../../assets/audio/default-cover.png"
>
<img
v-if="object.cover && object.cover.urls.original"
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
alt=""
class="channel-image"
>
<img
v-else
alt=""
class="channel-image"
src="../../assets/audio/default-cover.png"
>
</div>
</div>
<div class="ui column right aligned">
<TagsList
v-if="object.tags && object.tags.length > 0"
:tags="object.tags"
/>
<div class="ui small hidden divider" />
<human-duration
v-if="totalDuration > 0"
:duration="totalDuration"
/>
<template v-if="totalTracks > 0">
<div class="ui hidden very small divider" />
<span v-if="isSerie">
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
</span>
<span v-else>
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
</span>
</template>
<PlayButton
class="vibrant"
:tracks="object.tracks"
:is-playable="object.is_playable"
/>
<div class="ui hidden horizontal divider" />
<album-dropdown
:object="object"
:public-libraries="publicLibraries"
:is-loading="isLoading"
:is-album="isAlbum"
:is-serie="isSerie"
:is-channel="isChannel"
:artist-credit="artistCredit"
@remove="remove"
/>
</div>
</div>
<header>
<h2
class="ui header"
:title="object.title"
>
{{ object.title }}
</h2>
<artist-credit-label
v-if="artistCredit"
:artist-credit="artistCredit"
/>
</header>
</div>
<div
v-else
class="ui center aligned text padded basic segment"
>
<img
v-if="object.cover && object.cover.urls.original"
v-lazy="store.getters['instance/absoluteUrl'](object.cover.urls.medium_square_crop)"
alt=""
class="channel-image"
>
<img
v-else
alt=""
class="channel-image"
src="../../assets/audio/default-cover.png"
>
<div class="ui hidden divider" />
<header>
<h2
class="ui header"
:title="object.title"
>
{{ object.title }}
</h2>
<artist-credit-label
v-if="artistCredit"
:artist-credit="artistCredit"
/>
</header>
<Spacer :size="16"/>
<div
v-if="object.release_date || (totalTracks > 0)"
class="ui small hidden divider"
/>
<template v-if="object.release_date">
{{ momentFormat(new Date(object.release_date ?? '1970-01-01'), 'Y') }}
<span class="middle middledot symbol" />
</template>
<template v-if="totalTracks > 0">
<span v-if="isSerie">
{{ t('components.library.AlbumBase.meta.episodes', totalTracks) }}
</span>
<span v-else>
{{ t('components.library.AlbumBase.meta.tracks', totalTracks) }}
</span>
<span class="middle middledot symbol" />
</template>
<human-duration
v-if="totalDuration > 0"
:duration="totalDuration"
/>
<div class="ui small hidden divider" />
<play-button
class="vibrant"
:album="object"
:is-playable="object.is_playable"
/>
<div class="ui horizontal hidden divider" />
<album-dropdown
:object="object"
:public-libraries="publicLibraries"
:is-loading="isLoading"
:is-album="isAlbum"
:is-serie="isSerie"
:is-channel="isChannel"
:artist-credit="artistCredit"
@remove="remove"
/>
<div v-if="(object.tags && object.tags.length > 0) || object.description || store.state.auth.authenticated && object.is_local">
<div class="ui small hidden divider" />
<div class="ui divider" />
<div class="ui small hidden divider" />
<template v-if="object.tags && object.tags.length > 0">
<TagsList :tags="object.tags" />
<div class="ui small hidden divider" />
</template>
<rendered-description
v-if="object.description"
:content="object.description"
:can-update="false"
/>
<router-link
v-else-if="store.state.auth.authenticated && object.is_local"
:to="{name: 'library.albums.edit', params: {id: object.id }}"
>
<i class="pencil icon" />
{{ t('components.library.AlbumBase.link.addDescription') }}
</router-link>
</div>
</div>
<template v-if="isSerie">
<div class="ui hidden divider" />
<rendered-description
v-if="object.description"
:content="object.description"
:can-update="false"
/>
<router-link
v-else-if="store.state.auth.authenticated && object.is_local"
:to="{name: 'library.albums.edit', params: {id: object.id }}"
>
<i class="pencil icon" />
{{ t('components.library.AlbumBase.link.addDescription') }}
</router-link>
</template>
</div>
<div style="flex 1;">
<router-view
v-if="object"
:key="route.fullPath"
:paginate-by="paginateBy"
:total-tracks="totalTracks"
:is-serie="isSerie"
:artist-credit="artistCredit"
:object="object"
:is-loading-tracks="isLoadingTracks"
object-type="album"
@libraries-loaded="libraries = $event"
/>
</div>
</Layout>
</section>
<div style="flex 1;">
<router-view
v-if="object"
:key="route.fullPath"
:paginate-by="paginateBy"
:total-tracks="totalTracks"
:is-serie="isSerie"
:artist-credit="artistCredit"
:object="object"
:is-loading-tracks="isLoadingTracks"
object-type="album"
@libraries-loaded="libraries = $event"
/>
</div>
</template>
</Layout>
</template>