345 lines
10 KiB
Vue
345 lines
10 KiB
Vue
<template>
|
|
<DialogBase ref="dialogWindow" :title="selectedBox.title" @canceled="closed" :showFooter="false" :closeOnEscape="selectedVideo._id == null" :disableXscroll="true" :disableYscroll="true" :flatDialogHeader="true">
|
|
<div id="boxViewer" class="flex-row">
|
|
<div id="header" class="flex-column grow">
|
|
<div id="background" :style="coverBackground" />
|
|
<div id="title" class="grow z1 pa flex-column">
|
|
<img class="glow ma" :src="cover" />
|
|
<span id="stats" class="center">
|
|
<b>{{ selectedBox.title }}</b>
|
|
<br />
|
|
<b>{{ box_videos.length }}</b> Videos
|
|
</span>
|
|
|
|
<div class="grow"> </div>
|
|
<div class="flex-row ma-top grow">
|
|
<button class="flat ma-right" title="Favourite" @click="toggleFavourite">
|
|
<awesome-icon :icon="['fas', 'star']" size="2x" class="white-text favourite active" v-if="isFavourite" />
|
|
<awesome-icon :icon="['far', 'star']" size="2x" class="white-text favourite" v-else />
|
|
</button>
|
|
<button class="flat ma-right" title="Keep playing" @click="playProgress" v-if="selectedBox.progress">
|
|
<awesome-icon icon="play" size="2x" class="primary-text" />
|
|
</button>
|
|
<button class="flat ma-right" title="Play" @dblclick="dblclick" v-else>
|
|
<awesome-icon icon="play" size="2x" class="white-text" />
|
|
</button>
|
|
<button @click="gotoPrevBox" class="flat ma-left ma-right" :title="prevBox.name" :disabled="!prevBox._id">
|
|
<awesome-icon icon="angle-left" class="ma4 white-text" />
|
|
</button>
|
|
<button @click="gotoNextBox" class="flat" :title="nextBox.name" :disabled="!nextBox._id">
|
|
<awesome-icon icon="angle-right" class="ma4 white-text" />
|
|
</button>
|
|
<div class="grow"></div>
|
|
<DropDown v-if="$store.getters['user/isAdministrator']">
|
|
<button class="flat center" :title="visibility_text">
|
|
<awesome-icon :icon="visibility_icon" class="white-text" />
|
|
</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>
|
|
<hr />
|
|
<button v-if="!selectedBox.share._id" @click="shareEnable">
|
|
<awesome-icon icon="share" />Share this box
|
|
</button>
|
|
<button v-if="selectedBox.share._id" @click="addShareUrlToClipboard">
|
|
<awesome-icon icon="clipboard" />Copy url into clipboard
|
|
</button>
|
|
<button v-if="selectedBox.share._id" @click="shareDisable">
|
|
<awesome-icon icon="share" />Remove share
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</DropDown>
|
|
<DropDown v-if="$store.getters['user/isAdministrator']">
|
|
<button class="flat center">
|
|
<awesome-icon icon="ellipsis-v" class="white-text" />
|
|
</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="mergeBox">
|
|
<awesome-icon icon="compress-alt" />Merge Boxes...
|
|
</button>
|
|
</div>
|
|
</template>
|
|
</DropDown>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<ul id="videoList" class="videos">
|
|
<li v-for="item in selectedBox.videos" :key="item._id">
|
|
<VideoItem :video="item" />
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<BoxMerge ref="mergeDialog" />
|
|
</DialogBase>
|
|
</template>
|
|
|
|
<script>
|
|
import BoxMerge from "./BoxMerge";
|
|
import VideoItem from "../Video";
|
|
import { mapGetters } from "vuex";
|
|
|
|
export default {
|
|
methods: {
|
|
addShareUrlToClipboard() {
|
|
let url =
|
|
window.location.origin + "/#/share?id=" + this.selectedBox.share._id;
|
|
navigator.clipboard.writeText(url);
|
|
},
|
|
dblclick() {
|
|
this.$store.commit("tracks/resetSelectedTrack");
|
|
this.$store.commit("radios/resetSelectedRadio");
|
|
this.$store.dispatch("videos/playContainer", this.selectedBox);
|
|
},
|
|
gotoVideo() {
|
|
if (this.$route.query.play) {
|
|
let video = this.selectedBox.videos.find(
|
|
(f) => f._id == this.$route.query.play
|
|
);
|
|
if (video) {
|
|
this.$store.dispatch("videos/play", video);
|
|
}
|
|
}
|
|
},
|
|
playProgress() {
|
|
let video = this.selectedBox.videos.find(
|
|
(f) => f._id == this.selectedBox.progress.id
|
|
);
|
|
if (video) {
|
|
this.$store.dispatch("videos/play", video);
|
|
}
|
|
},
|
|
gotoNextBox() {
|
|
this.$store.dispatch("boxes/gotoNextBox");
|
|
},
|
|
gotoPrevBox() {
|
|
this.$store.dispatch("boxes/gotoPrevBox");
|
|
},
|
|
closed() {
|
|
if (
|
|
window.history.state.back.indexOf("?") == -1 ||
|
|
window.history.state.back.startsWith("/search")
|
|
) {
|
|
this.$router.back();
|
|
} else {
|
|
this.$store.dispatch("boxes/resetSelectedBox");
|
|
}
|
|
},
|
|
keydownListener(e) {
|
|
if (e.key == "ArrowLeft") {
|
|
e.preventDefault();
|
|
this.gotoPrevBox();
|
|
}
|
|
if (e.key == "ArrowRight") {
|
|
e.preventDefault();
|
|
this.gotoNextBox();
|
|
}
|
|
},
|
|
mergeBox() {
|
|
this.$refs.mergeDialog.open(this.selectedBox);
|
|
},
|
|
toggleFavourite() {
|
|
this.$store.dispatch("user/toggleFavourite", {
|
|
itemId: this.selectedBox._id,
|
|
type: "box",
|
|
});
|
|
},
|
|
setVisibility(visibility) {
|
|
this.selectedBox.visibility = visibility;
|
|
this.$store.dispatch("boxes/updateBox", this.selectedBox);
|
|
},
|
|
uploadNewCover() {
|
|
this.$store.dispatch("boxes/uploadNewCover", this.selectedBox);
|
|
},
|
|
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 Box"
|
|
: "Only for me";
|
|
},
|
|
resetCover() {
|
|
this.$store.dispatch("boxes/resetCover", this.selectedBox);
|
|
},
|
|
shareEnable() {
|
|
this.$store.dispatch("boxes/shareEnable", this.selectedBox).then(() => {
|
|
this.addShareUrlToClipboard();
|
|
});
|
|
},
|
|
shareDisable() {
|
|
this.$store.dispatch("boxes/shareDisable", this.selectedBox);
|
|
},
|
|
loadUserProgress() {
|
|
if (this.selectedVideo.parent._id != this.selectedBox._id) {
|
|
this.$store
|
|
.dispatch("user/getProgress", this.selectedBox)
|
|
.then(() => {
|
|
this.gotoVideo();
|
|
});
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
prevBox: ["boxes/prevBox"],
|
|
nextBox: ["boxes/nextBox"],
|
|
selectedBox: ["boxes/selectedBox"],
|
|
selectedVideo: ["videos/selectedVideo"],
|
|
favourites: ["user/favourites"],
|
|
}),
|
|
box_videos() {
|
|
return this.selectedBox.videos || [];
|
|
},
|
|
box_year() {
|
|
return this.selectedBox.year;
|
|
},
|
|
coverBackground() {
|
|
return "background-image: url('" + this.cover + "')";
|
|
},
|
|
cover() {
|
|
let cover = "/static/icons/dummy/box.svg";
|
|
if (this.selectedBox.covers && this.selectedBox.covers.cover256) {
|
|
cover = this.selectedBox.covers.cover256;
|
|
}
|
|
return cover;
|
|
},
|
|
isFavourite() {
|
|
return (
|
|
this.favourites.find((f) => f.itemId == this.selectedBox._id) !=
|
|
undefined
|
|
);
|
|
},
|
|
visibility_icon() {
|
|
return this.selectedBox.visibility == "global"
|
|
? "globe"
|
|
: this.selectedBox.visibility == "instance"
|
|
? "server"
|
|
: this.selectedBox.visibility == "hidden"
|
|
? "eye-slash"
|
|
: "user";
|
|
},
|
|
visibility_text() {
|
|
return this.selectedBox.visibility == "global"
|
|
? "Visible for the whole world"
|
|
: this.selectedBox.visibility == "instance"
|
|
? "Visible on this instance"
|
|
: this.selectedBox.visibility == "hidden"
|
|
? "Hidden for all users"
|
|
: "Visible only for me";
|
|
},
|
|
},
|
|
watch: {
|
|
selectedBox(newVal) {
|
|
if (newVal._id) {
|
|
if (!this.$refs.dialogWindow.visible) {
|
|
this.$refs.dialogWindow.open();
|
|
window.addEventListener("keydown", this.keydownListener);
|
|
}
|
|
this.loadUserProgress();
|
|
} else {
|
|
if (this.$refs.dialogWindow.visible) {
|
|
this.$refs.dialogWindow.close();
|
|
}
|
|
window.removeEventListener("keydown", this.keydownListener);
|
|
}
|
|
},
|
|
},
|
|
components: {
|
|
BoxMerge,
|
|
VideoItem,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
#boxViewer {
|
|
height: 486px;
|
|
}
|
|
|
|
#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;
|
|
}
|
|
|
|
.dropdown-activator button {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
|
|
#videoList {
|
|
background-color: var(--white);
|
|
z-index: 1;
|
|
overflow: overlay;
|
|
}
|
|
|
|
.video {
|
|
width: 220px;
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
#boxViewer {
|
|
flex-direction: column;
|
|
}
|
|
|
|
#stats p {
|
|
max-width: initial;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px),
|
|
(max-height: 480px) {
|
|
#boxViewer {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
#header img {
|
|
width: 192px;
|
|
}
|
|
|
|
#videoList {
|
|
height: initial;
|
|
flex-grow: 1;
|
|
}
|
|
|
|
.video {
|
|
width: initial;
|
|
}
|
|
}
|
|
|
|
@media (max-height: 480px) {}
|
|
</style> |