feat: mark external songs with icon

This commit is contained in:
Phan An 2024-01-04 11:24:40 +01:00
parent ff033139a4
commit f4a0e8d006
5 changed files with 39 additions and 6 deletions

View file

@ -18,6 +18,7 @@ class SongResource extends JsonResource
return [
'type' => 'songs',
'id' => $this->song->id,
'owner_id' => $this->song->owner_id,
'title' => $this->song->title,
'lyrics' => $this->song->lyrics,
'album_id' => $this->song->album->id,
@ -35,7 +36,6 @@ class SongResource extends JsonResource
'genre' => $this->song->genre,
'year' => $this->song->year,
'created_at' => $this->song->created_at,
'owner_id' => $this->song->owner_id,
];
}
}

View file

@ -7,6 +7,7 @@ const generate = (partOfCompilation = false): Song => {
return {
type: 'songs',
owner_id: faker.datatype.number({ min: 1, max: 999 }),
artist_id: artistId,
album_id: faker.datatype.number({ min: 2 }), // avoid Unknown Album by default
artist_name: artistName,

View file

@ -10,7 +10,12 @@
<SongThumbnail :song="song" />
<main>
<div class="details">
<h3>{{ song.title }}</h3>
<h3>
<span class="external-mark" v-if="external">
<Icon :icon="faSquareUpRight" />
</span>
{{ song.title }}
</h3>
<p class="by text-secondary">
<a :href="`#/artist/${song.artist_id}`">{{ song.artist_name }}</a>
- {{ pluralize(song.play_count, 'play') }}
@ -22,11 +27,12 @@
</template>
<script lang="ts" setup>
import { toRefs } from 'vue'
import {faSquareUpRight} from '@fortawesome/free-solid-svg-icons'
import { computed, toRefs } from 'vue'
import { eventBus, pluralize } from '@/utils'
import { queueStore } from '@/stores'
import { playbackService } from '@/services'
import { useDraggable } from '@/composables'
import { useAuthorization, useDraggable } from '@/composables'
import SongThumbnail from '@/components/song/SongThumbnail.vue'
import LikeButton from '@/components/song/SongLikeButton.vue'
@ -34,8 +40,11 @@ import LikeButton from '@/components/song/SongLikeButton.vue'
const props = defineProps<{ song: Song }>()
const { song } = toRefs(props)
const { currentUser } = useAuthorization()
const { startDragging } = useDraggable('songs')
const external = computed(() => song.value.owner_id !== currentUser.value?.id)
const requestContextMenu = (event: MouseEvent) => eventBus.emit('SONG_CONTEXT_MENU_REQUESTED', event, song.value)
const onDragStart = (event: DragEvent) => startDragging(event, [song.value])
@ -136,6 +145,11 @@ article {
flex-direction: column;
gap: 4px;
overflow: hidden;
.external-mark {
margin-right: .2rem;
opacity: .5;
}
}
}

View file

@ -1,6 +1,6 @@
<template>
<div
:class="{ playing, selected: item.selected }"
:class="{ playing, external, selected: item.selected }"
class="song-item"
data-testid="song-item"
tabindex="0"
@ -14,7 +14,12 @@
<SongThumbnail :song="song" />
</span>
<span class="title-artist">
<span class="title text-primary">{{ song.title }}</span>
<span class="title text-primary">
<span class="external-mark" v-if="external">
<Icon :icon="faSquareUpRight" />
</span>
{{ song.title }}
</span>
<span class="artist">
{{ song.artist_name }}
</span>
@ -28,20 +33,25 @@
</template>
<script lang="ts" setup>
import { faSquareUpRight } from '@fortawesome/free-solid-svg-icons'
import { computed, toRefs } from 'vue'
import { playbackService } from '@/services'
import { queueStore } from '@/stores'
import { secondsToHis } from '@/utils'
import { useAuthorization } from '@/composables'
import LikeButton from '@/components/song/SongLikeButton.vue'
import SoundBars from '@/components/ui/SoundBars.vue'
import SongThumbnail from '@/components/song/SongThumbnail.vue'
const { currentUser } = useAuthorization()
const props = defineProps<{ item: SongRow }>()
const { item } = toRefs(props)
const song = computed(() => item.value.song)
const playing = computed(() => ['Playing', 'Paused'].includes(song.value.playback_state!))
const external = computed(() => song.value.owner_id !== currentUser.value?.id)
const fmtLength = secondsToHis(song.value.length)
const play = () => {
@ -64,6 +74,13 @@ const play = () => {
border-radius: 4px;
}
.external-mark {
display: inline-block !important;
vertical-align: bottom;
margin-right: .2rem;
opacity: .5;
}
@media (hover: none) {
.cover {
.control {

View file

@ -127,6 +127,7 @@ interface Album {
interface Song {
type: 'songs'
readonly id: string
readonly owner_id: User['id'],
album_id: Album['id']
album_name: Album['name']
album_cover: Album['cover']