<template> <DialogBase ref="dialogWindow" :title="album_title" @canceled="closed" :showFooter="false" :disableXscroll="true" :disableYscroll="true" > <div id="albumViewer" class="flex-row"> <div id="header" class="flex-column"> <div id="background" :style="coverBackground" /> <div class="grow z1 center flex-column"> <img class="glow ma24" :src="cover" @dblclick="dblclick" /> </div> <awesome-icon icon="star" size="2x" class="favourite ma4" :class="{ active: isFavourite }" @click="toggleFavourite" /> <div id="stats" class="flex-row z1"> <DropDown v-if="$store.getters['user/isAdministrator']"> <button class="flat center" :title="visibility_text"> <awesome-icon :icon="visibility_icon" /> </button> <template v-slot:dropdown-content> <div> <button v-for="(item, i) in $store.state.system.lists.visibility" :key="i" @click="setVisibility(item)" > <awesome-icon :icon="getVisibilityIcon(item)" />{{ getVisibilityText(item) }} </button> </div> </template> </DropDown> <div class="grow flex-column"> <p class="ma4 center"> <span class="grow center"> by <b @click="gotoArtist" class="pointer">{{ selectedAlbum.artist_name }}</b> <br /> <span v-if="album_year"> from year <b>{{ album_year }}</b> </span ><br /> <b>{{ album_tracks.length }}</b> Tracks with a duration of <b>{{ album_duration }}</b> </span> </p> </div> <DropDown v-if="$store.getters['user/isAdministrator']"> <button class="flat center"> <awesome-icon icon="ellipsis-v" /> </button> <template v-slot:dropdown-content> <div> <button @click="uploadNewCover"> <awesome-icon icon="image" />Set new Cover... </button> <button @click="resetCover"> <awesome-icon icon="eraser" />Reset Cover </button> <hr /> <button @click="mergeAlbum"> <awesome-icon icon="compress-alt" />Merge Albums... </button> </div> </template> </DropDown> </div> </div> <ul id="trackList" class="tracks"> <li v-for="track in selectedAlbum.tracks" :key="track._id"> <TrackItem :track="track" :showCover="false" /> </li> </ul> </div> <AlbumMerge ref="mergeDialog" /> </DialogBase> </template> <script> import AlbumMerge from "./AlbumMerge.vue"; import TrackItem from "../Track"; import { mapGetters } from "vuex"; export default { data() { return { move: 152, albums: [], scrollTimer: 0, loadingPrev: false, loadingNext: false, elements: {}, }; }, mounted() { if (window.innerWidth <= 480 || window.innerHeight <= 480) { this.move = 120; } }, methods: { dblclick() { this.$store.commit("tracks/resetSelectedTrack"); this.$store.commit("radios/resetSelectedRadio"); this.$store.dispatch("tracks/playContainer", this.selectedAlbum); }, gotoArtist() { let artist = this.$store.getters["artists/collection"].find( (f) => f._id == this.selectedAlbum.artist_id ); if (artist) { this.$store.dispatch("artists/selectArtist", artist); } else { this.$store .dispatch("artists/loadArtist", this.selectedAlbum.artist_id) .then((artist) => { this.$store.dispatch("artists/selectArtist", artist); }); } }, gotoNextAlbum() { this.$store.dispatch("albums/gotoNextAlbum"); }, gotoPrevAlbum() { this.$store.dispatch("albums/gotoPrevAlbum"); }, gotoTrack() { if (this.$route.query.play) { let track = this.selectedAlbum.tracks.find( (f) => f._id == this.$route.query.play ); if (track) { this.$store.dispatch("tracks/play", track); } } }, closed() { if ( (window.history.state.back && window.history.state.back.indexOf("?") == -1) || window.history.state.back.startsWith("/search") ) { this.$router.back(); } else { this.$store.dispatch("albums/resetSelectedAlbum"); } this.albums = []; }, keydownListener(e) { if (e.key == "ArrowLeft") { e.preventDefault(); this.gotoPrevAlbum(); } if (e.key == "ArrowRight") { e.preventDefault(); this.gotoNextAlbum(); } }, mergeAlbum() { this.$refs.mergeDialog.open(this.selectedAlbum); }, setVisibility(visibility) { this.selectedAlbum.visibility = visibility; this.$store.dispatch("albums/updateAlbum", this.selectedAlbum); }, toggleFavourite() { this.$store.dispatch("user/toggleFavourite", { itemId: this.selectedAlbum._id, type: "album", }); }, uploadNewCover() { this.$store.dispatch("albums/uploadNewCover", this.selectedAlbum); }, resetCover() { this.$store.dispatch("albums/resetCover", this.selectedAlbum); }, getVisibilityIcon(visibility) { return visibility == "global" ? "globe" : visibility == "instance" ? "server" : visibility == "hidden" ? "eye-slash" : "user"; }, getVisibilityText(visibility) { return visibility == "global" ? "Global" : visibility == "instance" ? "On this server" : visibility == "hidden" ? "Hide this Album" : "Only for me"; }, selectAlbum(album) { this.$store.dispatch("albums/selectAlbum", album); }, }, computed: { ...mapGetters({ prevAlbum: ["albums/prevAlbum"], nextAlbum: ["albums/nextAlbum"], selectedAlbum: ["albums/selectedAlbum"], selectedTrack: ["tracks/selectedTrack"], favourites: ["user/favourites"], }), album_title() { return this.selectedAlbum.title; }, album_year() { return this.selectedAlbum.year; }, album_tracks() { return this.selectedAlbum.tracks || []; }, album_duration() { if (!this.selectedAlbum.tracks) { return 0; } let duration = 0; let hours = 0; let minutes = 0; let seconds = 0; this.selectedAlbum.tracks.forEach((track) => { duration += track.duration; }); if (duration >= 3600) { hours = parseInt(duration / 3600); duration -= hours * 3600; } minutes = parseInt(duration / 60); seconds = parseInt(duration - minutes * 60); return ( (hours > 0 ? hours + ":" : "") + (minutes < 10 ? "0" : "") + minutes + ":" + (seconds < 10 ? "0" : "") + seconds ); }, coverBackground() { return "background-image: url('" + this.cover + "')"; }, cover() { return ( this.selectedAlbum.covers.cover256 || "/static/icons/dummy/album.svg" ); }, visibility_icon() { return this.selectedAlbum.visibility == "global" ? "globe" : this.selectedAlbum.visibility == "instance" ? "server" : this.selectedAlbum.visibility == "hidden" ? "eye-slash" : "user"; }, visibility_text() { return this.selectedAlbum.visibility == "global" ? "Visible for the whole world" : this.selectedAlbum.visibility == "instance" ? "Visible on this instance" : this.selectedAlbum.visibility == "hidden" ? "Hidden for all users" : "Visible only for me"; }, isFavourite() { return ( this.favourites.find((f) => f.itemId == this.selectedAlbum._id) != undefined ); }, }, watch: { selectedAlbum(newVal) { if (newVal._id) { if (this.albums.length == 0) { this.albums.push(newVal); } if (!this.$refs.dialogWindow.visible) { this.$refs.dialogWindow.open(); window.addEventListener("keydown", this.keydownListener); } this.gotoTrack(); } else { if (this.$refs.dialogWindow.visible) { this.$refs.dialogWindow.close(); } window.removeEventListener("keydown", this.keydownListener); } }, }, components: { AlbumMerge, TrackItem, }, }; </script> <style scoped> #albumViewer { height: 366px; width: 640px; } #header { position: relative; background-color: black; } #header img { align-self: center; width: 256px; } #stats { z-index: 2; color: var(--white); text-shadow: 0 1px 2px black; line-height: 1.4; background-color: #ffffff40; border-top: 1px solid #ffffff20; border-bottom: 1px solid #00000020; } #stats button { width: 32px; } #trackList { background-color: var(--white); z-index: 1; } @media (max-width: 480px) { #header { width: 100%; } #albumViewer { flex-direction: column; } } @media (max-width: 480px), (max-height: 480px) { #albumViewer { width: 100%; height: 100%; } #trackList { height: initial; flex-grow: 1; } } </style>