fix(front): playlist description and header component

This commit is contained in:
ArneBo 2025-04-03 16:21:29 +02:00
parent d7402c29ab
commit 2b3831d4d3
1 changed files with 100 additions and 102 deletions

View File

@ -17,6 +17,7 @@ import HumanDate from '~/components/common/HumanDate.vue'
import TrackTable from '~/components/audio/track/Table.vue' import TrackTable from '~/components/audio/track/Table.vue'
import PlayButton from '~/components/audio/PlayButton.vue' import PlayButton from '~/components/audio/PlayButton.vue'
import Layout from '~/components/ui/Layout.vue' import Layout from '~/components/ui/Layout.vue'
import Header from '~/components/ui/Header.vue'
import Spacer from '~/components/ui/Spacer.vue' import Spacer from '~/components/ui/Spacer.vue'
import Loader from '~/components/ui/Loader.vue' import Loader from '~/components/ui/Loader.vue'
import Button from '~/components/ui/Button.vue' import Button from '~/components/ui/Button.vue'
@ -125,6 +126,7 @@ const deletePlaylist = async () => {
<template> <template>
<Layout <Layout
v-title="playlist?.name"
stack stack
main main
> >
@ -132,116 +134,92 @@ const deletePlaylist = async () => {
v-if="isLoading" v-if="isLoading"
v-title="labels.playlist" v-title="labels.playlist"
/> />
<Layout <Header
v-if="!isLoading && playlist" v-if="!isLoading && playlist"
v-title="playlist.name" :h1="playlist.name"
flex page-heading
> >
<div class="playlist-grid"> <template #image>
<img <div class="playlist-grid">
v-for="(url, idx) in images" <img
:key="idx" v-for="(url, idx) in images"
v-lazy="url" :key="idx"
:alt="playlist.name" v-lazy="url"
:style="{ backgroundColor: randomizedColors[idx % randomizedColors.length] }" :alt="playlist.name"
> :style="{ backgroundColor: randomizedColors[idx % randomizedColors.length] }"
>
</div>
</template>
<div class="meta">
{{ playlist.tracks_count }}
{{ t('views.playlists.Detail.header.tracks') }}
<i class="bi bi-dot" />
<Duration :seconds="playlist.duration" />
</div> </div>
<Layout <Layout
stack flex
style="flex: 1; gap: 8px;" gap-8
> >
<Spacer /> {{ t('views.playlists.Detail.meta.attribution') }}
<h1>{{ playlist.name }}</h1> <ActorLink
<div class="meta"> :actor="playlist.actor"
{{ playlist.tracks_count }} :avatar="false"
{{ t('views.playlists.Detail.header.tracks') }} :discrete="true"
<i class="bi bi-dot" /> />
<Duration :seconds="playlist.duration" /> <i class="bi bi-dot" />
</div> {{ t('views.playlists.Detail.meta.updated') }}
<Layout <HumanDate
flex :date="playlist.modification_date"
gap-8
>
{{ t('views.playlists.Detail.meta.attribution') }}
<ActorLink
:actor="playlist.actor"
:avatar="false"
:discrete="true"
/>
<i class="bi bi-dot" />
{{ t('views.playlists.Detail.meta.updated') }}
<HumanDate
:date="playlist.modification_date"
/>
</Layout>
<RenderedDescription
:description="playlist.description"
:max-length="200"
:show-more="true"
/> />
<Layout
flex
class="header-buttons"
>
<PlayButton
split
:is-playable="playlist.is_playable"
:tracks="tracks"
>
{{ t('views.playlists.Detail.button.playAll') }}
</PlayButton>
<Button
v-if="playlist.tracks_count > 1"
primary
icon="bi-shuffle"
:aria-label="t('components.audio.Player.label.shuffleQueue')"
@click.prevent.stop="shuffle()"
>
{{ t('components.audio.Player.label.shuffleQueue') }}
</Button>
<Button
v-if="store.state.auth.profile && playlist.actor.full_username === store.state.auth.fullUsername"
secondary
icon="bi-pencil"
@click="edit = !edit"
>
<template v-if="edit">
{{ t('views.playlists.Detail.button.stopEdit') }}
</template>
<template v-else>
{{ t('views.playlists.Detail.button.edit') }}
</template>
</Button>
<Spacer
h
grow
/>
<playlist-dropdown
:playlist="playlist"
@import="fetchData"
/>
</Layout>
</Layout> </Layout>
<Modal <RenderedDescription
v-if="playlist.privacy_level === 'everyone' && playlist.is_playable" :content="{ html: playlist.description }"
v-model="showEmbedModal" :truncate-length="200"
title="t('views.playlists.Detail.modal.embed.header')" :show-more="true"
/>
<Layout
flex
class="header-buttons"
> >
<div class="scrolling content"> <PlayButton
<div class="description"> split
<embed-wizard :is-playable="playlist.is_playable"
:id="playlist.id" :tracks="tracks"
type="playlist" >
/> {{ t('views.playlists.Detail.button.playAll') }}
</div> </PlayButton>
</div> <Button
<template #actions> v-if="playlist.tracks_count > 1"
<Button variant="outline"> primary
{{ t('views.playlists.Detail.button.cancel') }} icon="bi-shuffle"
</Button> :aria-label="t('components.audio.Player.label.shuffleQueue')"
</template> @click.prevent.stop="shuffle()"
</Modal> >
</Layout> {{ t('components.audio.Player.label.shuffleQueue') }}
</Button>
<Button
v-if="store.state.auth.profile && playlist.actor.full_username === store.state.auth.fullUsername"
secondary
icon="bi-pencil"
@click="edit = !edit"
>
<template v-if="edit">
{{ t('views.playlists.Detail.button.stopEdit') }}
</template>
<template v-else>
{{ t('views.playlists.Detail.button.edit') }}
</template>
</Button>
<Spacer
h
grow
/>
<playlist-dropdown
:playlist="playlist"
@import="fetchData"
/>
</Layout>
</Header>
<Layout stack> <Layout stack>
<template v-if="edit"> <template v-if="edit">
@ -280,6 +258,26 @@ const deletePlaylist = async () => {
</Button> </Button>
</Alert> </Alert>
</Layout> </Layout>
<Modal
v-if="playlist?.privacy_level === 'everyone' && playlist?.is_playable"
v-model="showEmbedModal"
title="t('views.playlists.Detail.modal.embed.header')"
>
<div class="scrolling content">
<div class="description">
<embed-wizard
:id="playlist.id"
type="playlist"
/>
</div>
</div>
<template #actions>
<Button variant="outline">
{{ t('views.playlists.Detail.button.cancel') }}
</Button>
</template>
</Modal>
</Layout> </Layout>
</template> </template>