2023-02-08 12:37:55 +01:00
|
|
|
<template>
|
2023-09-19 01:56:09 +02:00
|
|
|
<DialogBase ref="dialogWindow" :title="album_title" @canceled="closed" :showFooter="false" :disableXscroll="true" :disableYscroll="true">
|
2023-02-12 23:03:19 +01:00
|
|
|
<div id="albumViewer" class="flex-row">
|
2023-02-08 12:37:55 +01:00
|
|
|
<div id="header" class="flex-column">
|
|
|
|
<div id="background" :style="coverBackground" />
|
2023-02-12 23:03:19 +01:00
|
|
|
<div class="grow z1 center flex-column">
|
|
|
|
<img class="glow ma24" :src="cover" @dblclick="dblclick" />
|
2023-02-08 12:37:55 +01:00
|
|
|
</div>
|
2023-09-19 01:56:09 +02:00
|
|
|
<awesome-icon icon="star" size="2x" class="favourite ma4" :class="{ active: isFavourite }" @click="toggleFavourite" />
|
2023-02-12 23:03:19 +01:00
|
|
|
<div id="stats" class="flex-row z1">
|
2023-02-08 12:37:55 +01:00
|
|
|
<DropDown v-if="$store.getters['user/isAdministrator']">
|
2023-02-12 23:03:19 +01:00
|
|
|
<button class="flat center" :title="visibility_text">
|
2023-02-08 12:37:55 +01:00
|
|
|
<awesome-icon :icon="visibility_icon" />
|
|
|
|
</button>
|
|
|
|
<template v-slot:dropdown-content>
|
|
|
|
<div>
|
2023-09-19 01:56:09 +02:00
|
|
|
<button v-for="(item, i) in $store.state.system.lists.visibility" :key="i" @click="setVisibility(item)">
|
2023-02-08 12:37:55 +01:00
|
|
|
<awesome-icon :icon="getVisibilityIcon(item)" />{{
|
|
|
|
getVisibilityText(item)
|
|
|
|
}}
|
|
|
|
</button>
|
2023-02-15 11:13:06 +01:00
|
|
|
<hr />
|
2023-02-15 23:36:37 +01:00
|
|
|
<button v-if="!selectedAlbum.share._id" @click="shareEnable">
|
2023-02-15 11:13:06 +01:00
|
|
|
<awesome-icon icon="share" />Share this album
|
|
|
|
</button>
|
2023-09-19 01:56:09 +02:00
|
|
|
<button v-if="selectedAlbum.share._id" @click="addShareUrlToClipboard">
|
2023-02-16 23:59:01 +01:00
|
|
|
<awesome-icon icon="clipboard" />Copy url into clipboard
|
|
|
|
</button>
|
|
|
|
<button v-if="selectedAlbum.share._id" @click="shareDisable">
|
2023-02-15 23:36:37 +01:00
|
|
|
<awesome-icon icon="share" />Remove share
|
|
|
|
</button>
|
2023-02-08 12:37:55 +01:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</DropDown>
|
2023-02-12 23:03:19 +01:00
|
|
|
<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">
|
2023-09-19 01:56:09 +02:00
|
|
|
from year <b>{{ album_year }}</b> </span><br />
|
2023-02-12 23:03:19 +01:00
|
|
|
<b>{{ album_tracks.length }}</b> Tracks with a duration of
|
|
|
|
<b>{{ album_duration }}</b>
|
|
|
|
</span>
|
|
|
|
</p>
|
|
|
|
</div>
|
2023-02-08 12:37:55 +01:00
|
|
|
<DropDown v-if="$store.getters['user/isAdministrator']">
|
2023-02-12 23:03:19 +01:00
|
|
|
<button class="flat center">
|
2023-02-08 12:37:55 +01:00
|
|
|
<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>
|
2023-09-19 01:56:09 +02:00
|
|
|
<p v-if="selectedAlbum.progress" @click="playProgress">Progress</p>
|
2023-02-08 12:37:55 +01:00
|
|
|
|
|
|
|
<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 {
|
|
|
|
albums: [],
|
|
|
|
scrollTimer: 0,
|
|
|
|
loadingPrev: false,
|
|
|
|
loadingNext: false,
|
|
|
|
elements: {},
|
|
|
|
};
|
|
|
|
},
|
|
|
|
methods: {
|
2023-02-16 23:59:01 +01:00
|
|
|
addShareUrlToClipboard() {
|
|
|
|
let url =
|
|
|
|
window.location.origin + "/#/share?id=" + this.selectedAlbum.share._id;
|
|
|
|
navigator.clipboard.writeText(url);
|
|
|
|
},
|
2023-02-08 12:37:55 +01:00
|
|
|
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() {
|
2023-02-12 23:03:19 +01:00
|
|
|
this.$store.dispatch("albums/gotoNextAlbum");
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
gotoPrevAlbum() {
|
2023-02-12 23:03:19 +01:00
|
|
|
this.$store.dispatch("albums/gotoPrevAlbum");
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2023-09-19 01:56:09 +02:00
|
|
|
playProgress() {
|
|
|
|
let track = this.selectedAlbum.tracks.find(
|
|
|
|
(f) => f._id == this.selectedAlbum.progress.id
|
|
|
|
);
|
|
|
|
if (track) {
|
|
|
|
this.$store.dispatch("tracks/play", track);
|
|
|
|
}
|
|
|
|
},
|
2023-02-08 12:37:55 +01:00
|
|
|
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"
|
2023-09-19 01:56:09 +02:00
|
|
|
? "server"
|
|
|
|
: visibility == "hidden"
|
|
|
|
? "eye-slash"
|
|
|
|
: "user";
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
getVisibilityText(visibility) {
|
|
|
|
return visibility == "global"
|
|
|
|
? "Global"
|
|
|
|
: visibility == "instance"
|
2023-09-19 01:56:09 +02:00
|
|
|
? "On this server"
|
|
|
|
: visibility == "hidden"
|
|
|
|
? "Hide this Album"
|
|
|
|
: "Only for me";
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
selectAlbum(album) {
|
|
|
|
this.$store.dispatch("albums/selectAlbum", album);
|
|
|
|
},
|
2023-02-15 23:36:37 +01:00
|
|
|
shareEnable() {
|
2023-02-16 23:59:01 +01:00
|
|
|
this.$store
|
|
|
|
.dispatch("albums/shareEnable", this.selectedAlbum)
|
|
|
|
.then(() => {
|
|
|
|
this.addShareUrlToClipboard();
|
|
|
|
});
|
2023-02-15 23:36:37 +01:00
|
|
|
},
|
|
|
|
shareDisable() {
|
|
|
|
this.$store.dispatch("albums/shareDisable", this.selectedAlbum);
|
2023-02-15 12:57:13 +01:00
|
|
|
},
|
2023-09-19 01:56:09 +02:00
|
|
|
loadUserProgress() {
|
|
|
|
this.$store.dispatch("user/getProgress", this.selectedAlbum);
|
|
|
|
}
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
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"
|
2023-09-19 01:56:09 +02:00
|
|
|
? "server"
|
|
|
|
: this.selectedAlbum.visibility == "hidden"
|
|
|
|
? "eye-slash"
|
|
|
|
: "user";
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
visibility_text() {
|
|
|
|
return this.selectedAlbum.visibility == "global"
|
|
|
|
? "Visible for the whole world"
|
|
|
|
: this.selectedAlbum.visibility == "instance"
|
2023-09-19 01:56:09 +02:00
|
|
|
? "Visible on this instance"
|
|
|
|
: this.selectedAlbum.visibility == "hidden"
|
|
|
|
? "Hidden for all users"
|
|
|
|
: "Visible only for me";
|
2023-02-08 12:37:55 +01:00
|
|
|
},
|
|
|
|
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);
|
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
this.loadUserProgress();
|
2023-02-08 12:37:55 +01:00
|
|
|
this.gotoTrack();
|
|
|
|
} else {
|
|
|
|
if (this.$refs.dialogWindow.visible) {
|
|
|
|
this.$refs.dialogWindow.close();
|
|
|
|
}
|
|
|
|
window.removeEventListener("keydown", this.keydownListener);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
components: {
|
|
|
|
AlbumMerge,
|
|
|
|
TrackItem,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
#albumViewer {
|
2023-02-12 23:03:19 +01:00
|
|
|
height: 366px;
|
|
|
|
width: 640px;
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-08 12:37:55 +01:00
|
|
|
#header {
|
|
|
|
position: relative;
|
2023-02-12 23:03:19 +01:00
|
|
|
background-color: black;
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-08 12:37:55 +01:00
|
|
|
#header img {
|
|
|
|
align-self: center;
|
2023-02-12 23:03:19 +01:00
|
|
|
width: 256px;
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-08 12:37:55 +01:00
|
|
|
#stats {
|
|
|
|
z-index: 2;
|
2023-02-15 11:13:06 +01:00
|
|
|
align-items: center;
|
2023-02-08 12:37:55 +01:00
|
|
|
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;
|
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-16 23:59:01 +01:00
|
|
|
.dropdown-activator button {
|
2023-02-12 23:03:19 +01:00
|
|
|
width: 32px;
|
2023-02-15 11:13:06 +01:00
|
|
|
height: 32px;
|
2023-02-12 23:03:19 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-08 12:37:55 +01:00
|
|
|
#trackList {
|
|
|
|
background-color: var(--white);
|
|
|
|
z-index: 1;
|
|
|
|
}
|
2023-02-15 12:57:13 +01:00
|
|
|
|
2023-02-12 23:03:19 +01:00
|
|
|
@media (max-width: 480px) {
|
|
|
|
#header {
|
|
|
|
width: 100%;
|
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-12 23:03:19 +01:00
|
|
|
#albumViewer {
|
|
|
|
flex-direction: column;
|
|
|
|
}
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
|
|
|
@media (max-width: 480px),
|
|
|
|
(max-height: 480px) {
|
2023-02-12 23:03:19 +01:00
|
|
|
#albumViewer {
|
2023-02-08 12:37:55 +01:00
|
|
|
width: 100%;
|
2023-02-12 23:03:19 +01:00
|
|
|
height: 100%;
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
2023-09-19 01:56:09 +02:00
|
|
|
|
2023-02-08 12:37:55 +01:00
|
|
|
#trackList {
|
|
|
|
height: initial;
|
2023-02-12 23:03:19 +01:00
|
|
|
flex-grow: 1;
|
2023-02-08 12:37:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|