client/src/components/dialogs/AlbumViewer.vue

387 lines
10 KiB
Vue
Raw Normal View History

2023-02-08 12:37:55 +01:00
<template>
<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>
<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>
<button
v-for="(item, i) in $store.state.system.lists.visibility"
:key="i"
@click="setVisibility(item)"
>
<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-02-16 23:59:01 +01:00
<button
v-if="selectedAlbum.share._id"
@click="addShareUrlToClipboard"
>
<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">
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>
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>
<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);
}
}
},
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);
},
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-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"
? "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 {
2023-02-12 23:03:19 +01:00
height: 366px;
width: 640px;
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
}
#header img {
align-self: center;
2023-02-12 23:03:19 +01:00
width: 256px;
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-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-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%;
}
#albumViewer {
flex-direction: column;
}
2023-02-08 12:37:55 +01: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
}
#trackList {
height: initial;
2023-02-12 23:03:19 +01:00
flex-grow: 1;
2023-02-08 12:37:55 +01:00
}
}
</style>