funkwhale/front/src/components/library/AlbumDetail.vue

139 lines
4.0 KiB
Vue

<script setup lang="ts">
import type { ArtistCredit, Album, Library, Track } from '~/types'
import LibraryWidget from '~/components/federation/LibraryWidget.vue'
import ChannelEntries from '~/components/audio/ChannelEntries.vue'
import TrackTable from '~/components/audio/track/Table.vue'
import PlayButton from '~/components/audio/PlayButton.vue'
import Pagination from '~/components/vui/Pagination.vue'
import { computed, ref } from 'vue'
interface Events {
(e: 'libraries-loaded', libraries: Library[]): void
}
interface Props {
object: Album
isLoadingTracks: boolean
isSerie: boolean
artistCredit: ArtistCredit[]
paginateBy: number
totalTracks: number
}
const emit = defineEmits<Events>()
const props = defineProps<Props>()
const getDiscKey = (disc: Track[]) => disc?.map(track => track.id).join('|') ?? ''
const page = ref(1)
const discCount = computed(() => props.object.tracks.reduce((acc, track) => {
acc.add(track.disc_number)
return acc
}, new Set()).size)
const discs = computed(() => props.object.tracks
.reduce((acc: Track[][], track: Track) => {
const discNumber = track.disc_number - (props.object.tracks[0]?.disc_number ?? 1)
acc[discNumber].push(track)
return acc
}, Array(discCount.value).fill(undefined).map(() => []))
)
const paginatedDiscs = computed(() => props.object.tracks.slice(props.paginateBy * (page.value - 1), props.paginateBy * page.value)
.reduce((acc: Track[][], track: Track) => {
const discNumber = track.disc_number - (props.object.tracks[0]?.disc_number ?? 1)
acc[discNumber].push(track)
return acc
}, Array(discCount.value).fill(undefined).map(() => []))
)
</script>
<template>
<div
v-if="!isLoadingTracks"
class="ui vertical segment"
>
<h2 class="ui header">
<span v-if="isSerie">
{{ $t('components.library.AlbumDetail.header.episodes') }}
</span>
<span v-else>
{{ $t('components.library.AlbumDetail.header.tracks') }}
</span>
</h2>
<channel-entries
v-if="artistCredit && artistCredit[0].artist.channel && isSerie"
:is-podcast="isSerie"
:limit="50"
:filters="{channel: artistCredit[0].artist.channel.uuid, album: object.id, ordering: '-creation_date'}"
/>
<template v-else>
<template v-if="discCount > 1">
<div
v-for="tracks, index in paginatedDiscs"
:key="index + getDiscKey(tracks)"
>
<template v-if="tracks.length > 0">
<div class="ui hidden divider" />
<play-button
class="right floated mini inverted vibrant"
:tracks="discs[index]"
/>
<h3>
{{ $t('components.library.AlbumDetail.meta.volume', {number: tracks[0].disc_number}) }}
</h3>
<track-table
:is-album="true"
:tracks="tracks"
:show-position="true"
:show-art="false"
:show-album="false"
:show-artist="false"
:paginate-results="false"
/>
</template>
</div>
</template>
<template v-else>
<track-table
:is-album="true"
:tracks="object.tracks"
:show-position="true"
:show-art="false"
:show-album="false"
:show-artist="false"
:paginate-results="false"
/>
</template>
<div
v-if="totalTracks > paginateBy"
class="ui center aligned basic segment"
>
<pagination
v-model:current="page"
:paginate-by="paginateBy"
:total="totalTracks"
/>
</div>
</template>
<template v-if="artistCredit && !artistCredit[0]?.artist.channel && !isSerie">
<h2>
{{ $t('components.library.AlbumDetail.header.libraries') }}
</h2>
<library-widget
:url="'albums/' + object.id + '/libraries/'"
@loaded="emit('libraries-loaded', $event)"
>
{{ $t('components.library.AlbumDetail.description.libraries') }}
</library-widget>
</template>
</div>
</template>