geoffrey45 0b24974a63 fix slow folder page
~ stabilize props: move isCurrent check to inside SongItem component
2023-01-13 18:13:49 +03:00

276 lines
5.4 KiB
Vue

<template>
<div
class="songlist-item rounded-sm"
:class="[{ current: isCurrent() }, { contexton: context_menu_showing }]"
@dblclick.prevent="emitUpdate"
@contextmenu.prevent="showMenu"
>
<div class="index t-center ellip" @dblclick.prevent.stop="() => {}">
<span class="text">
{{ index }}
</span>
<HeartSvg />
</div>
<div class="flex">
<div @click.prevent="emitUpdate" class="thumbnail">
<img :src="imguri + track.image" class="album-art image rounded-sm" />
<div
class="now-playing-track-indicator image"
v-if="isCurrent()"
:class="{ last_played: !isCurrentPlaying() }"
></div>
</div>
<div v-tooltip class="song-title">
<div class="with-flag" @click.prevent="emitUpdate">
<span class="title ellip" ref="artisttitle">
{{ track.title }}
</span>
<span v-if="track.bitrate > 1024" class="master-flag"><b>M</b> </span>
</div>
<div class="isSmallArtists" style="display: none">
<ArtistName
:artists="track.artist"
:albumartists="track.albumartist"
/>
</div>
</div>
</div>
<div class="song-artists">
<ArtistName :artists="track.artist" :albumartists="track.albumartist" />
</div>
<router-link
v-if="!hide_album"
class="song-album ellip"
v-tooltip
:to="{
name: 'AlbumView',
params: {
hash: track.albumhash || 'Unknown',
},
}"
>
{{ track.album }}
</router-link>
<div class="song-duration">{{ formatSeconds(track.duration) }}</div>
<div
class="options-icon circular"
@click.stop="showMenu"
@dblclick.stop="() => {}"
>
<OptionSvg />
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { showTrackContextMenu as showContext } from "@/composables/context";
import { paths } from "@/config";
import { Track } from "@/interfaces";
import { formatSeconds } from "@/utils";
import HeartSvg from "@/assets/icons/heart.svg";
import OptionSvg from "@/assets/icons/more.svg";
import ArtistName from "./ArtistName.vue";
import useQueueStore from "@/stores/queue";
const imguri = paths.images.thumb.small;
const context_menu_showing = ref(false);
const queue = useQueueStore();
const artisttitle = ref<HTMLElement | null>(null);
const props = defineProps<{
track: Track;
index: Number | String;
hide_album?: Boolean;
}>();
const emit = defineEmits<{
(e: "playThis"): void;
}>();
function emitUpdate() {
emit("playThis");
}
function showMenu(e: MouseEvent) {
showContext(e, props.track, context_menu_showing);
}
function isCurrent() {
return queue.currenttrackhash == props.track.trackhash;
}
function isCurrentPlaying() {
return isCurrent() && queue.playing;
}
</script>
<style lang="scss">
.songlist-item {
display: grid;
grid-template-columns: 1.5rem 2fr 1fr 1.5fr 2.5rem 2.5rem;
align-items: center;
justify-content: flex-start;
height: $song-item-height;
gap: 1rem;
user-select: none;
padding-left: $small;
.song-title {
.with-flag {
display: flex;
align-items: center;
}
.master-flag {
font-size: 10px;
margin-left: $smaller;
background-color: rgba(184, 108, 21, 0.281);
color: rgb(255, 153, 0);
padding: 2px 5px;
border-radius: 5px;
opacity: 0.75;
}
cursor: pointer;
// outline: solid 1px;
.title {
margin-bottom: 2px;
}
}
&:hover {
background-color: $gray5;
.index {
.text {
transform: translateX($smaller);
opacity: 0;
}
svg {
transform: translateX(0);
opacity: 1;
}
}
}
.song-album {
max-width: max-content;
cursor: pointer !important;
&:hover {
text-decoration: underline;
}
}
.song-artists {
width: fit-content;
max-width: 100%;
}
.index {
opacity: 0.5;
font-size: 0.8rem;
width: 100%;
position: relative;
height: 3rem;
display: flex;
justify-content: center;
.text {
opacity: 1;
display: block;
margin: auto 0;
transition: all 0.25s;
transform: translateX(0);
}
svg {
position: absolute;
left: 0;
transition: all 0.2s;
top: $medium;
opacity: 0;
transform: translateX(-1rem);
cursor: pointer;
}
}
.song-duration {
font-size: small;
text-align: left;
}
.options-icon {
display: flex;
align-items: center;
justify-content: center;
aspect-ratio: 1;
width: 2rem;
svg {
stroke: $white;
}
&:hover {
background-color: $darkestblue;
}
}
.context_menu_showing {
background-color: $gray4;
opacity: 1;
}
.flex {
position: relative;
align-items: center;
.thumbnail {
margin-right: $small;
display: flex;
}
.album-art {
width: 3rem;
height: 3rem;
cursor: pointer;
}
.now-playing-track-indicator {
position: absolute;
left: $small;
top: $small;
}
}
td {
height: 4rem;
padding: $small;
}
td:first-child {
border-radius: $small 0 0 $small;
}
td:nth-child(2) {
border-radius: 0 $small $small 0;
}
}
.songlist-item.current {
background-color: $gray;
}
.songlist-item.contexton {
background-color: $gray;
}
</style>