Compare commits

..

No commits in common. "44497c442936981a676960769dc36034638eb4fc" and "1986105e716c800bfb06ab4d3a6947bca1ad04db" have entirely different histories.

6 changed files with 192 additions and 194 deletions

View File

@ -1,5 +1,5 @@
{
"backend_dev": "http://localhost:31204",
"backend_de": "https://webplay.rocks",
"backend_de": "http://localhost:31204",
"backend_dev": "https://webplay.rocks",
"backend": "https://webplay.rocks"
}

View File

@ -95,14 +95,6 @@ td.fillCell>* {
color: var(--yellow);
}
.keepPlaying {
z-index: 1;
position: absolute;
cursor: pointer;
right: 0;
}
/*
DIALOGS
*/

View File

@ -1,9 +1,26 @@
<template>
<div id="player" class="flex-column" v-show="selectedTrack._id || selectedRadio._id">
<input type="range" id="slider" min="0" max="100" step="0.1" v-model="selectedTrack.percent" @change="slideChanged" />
<div
id="player"
class="flex-column"
v-show="selectedTrack._id || selectedRadio._id"
>
<input
type="range"
id="slider"
min="0"
max="100"
step="0.1"
v-model="selectedTrack.percent"
@change="slideChanged"
/>
<div id="playerBar" class="flex-row">
<div class="flex-row grow">
<img class="cover pointer" :src="cover" :title="selectedTrack.parent.title" @click="gotoContainer" />
<img
class="cover pointer"
:src="cover"
:title="selectedTrack.parent.title"
@click="gotoContainer"
/>
<div v-if="selectedTrack._id" class="flex-column">
<b>{{ selectedTrack.title }}</b>
from
@ -11,9 +28,21 @@
</div>
</div>
<div id="playerControls" class="flex-row center">
<button @click="switchShuffle" title="Shuffle mode" v-if="selectedTrack._id">
<img src="static/icons/media-shuffle-dark.svg" v-show="$store.getters['player/shuffle']" class="small" />
<img src="static/icons/media-consecutive-dark.svg" v-show="$store.getters['player/shuffle'] == false" class="small" />
<button
@click="switchShuffle"
title="Shuffle mode"
v-if="selectedTrack._id"
>
<img
src="static/icons/media-shuffle-dark.svg"
v-show="$store.getters['player/shuffle']"
class="small"
/>
<img
src="static/icons/media-consecutive-dark.svg"
v-show="$store.getters['player/shuffle'] == false"
class="small"
/>
</button>
<button @click="prevTrack" title="Back" v-if="selectedTrack._id">
<awesome-icon icon="backward" />
@ -25,17 +54,46 @@
<button @click="nextTrack" title="Forward" v-if="selectedTrack._id">
<awesome-icon icon="forward" />
</button>
<button @click="switchRepeatType" title="Repeat mode" v-if="selectedTrack._id">
<img src="static/icons/media-repeat-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'all'" />
<img src="static/icons/media-repeat-song-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'one'" />
<img src="static/icons/media-no-repeat-dark.svg" class="small" v-show="$store.getters['player/repeatType'] == 'none'" />
<button
@click="switchRepeatType"
title="Repeat mode"
v-if="selectedTrack._id"
>
<img
src="static/icons/media-repeat-dark.svg"
class="small"
v-show="$store.getters['player/repeatType'] == 'all'"
/>
<img
src="static/icons/media-repeat-song-dark.svg"
class="small"
v-show="$store.getters['player/repeatType'] == 'one'"
/>
<img
src="static/icons/media-no-repeat-dark.svg"
class="small"
v-show="$store.getters['player/repeatType'] == 'none'"
/>
</button>
</div>
<div class="flex-row ma-right hideOnMobilePortrait grow right" v-show="selectedTrack.title">
<div
class="flex-row ma-right hideOnMobilePortrait grow right"
v-show="selectedTrack.title"
>
{{ formatedP }}&nbsp;|&nbsp;{{ formatedD }}
</div>
</div>
<audio preload="auto" ref="audioControl" type="audio/mpeg" @ended="nextTrack" @canplay="play" @playing="playing" @durationchange="durationChanged" @timeupdate="timeUpdate" src></audio>
<audio
preload="auto"
ref="audioControl"
type="audio/mpeg"
@ended="nextTrack"
@canplay="play"
@playing="playing"
@durationchange="durationChanged"
@timeupdate="timeUpdate"
src
></audio>
</div>
</template>
@ -47,8 +105,7 @@ export default {
audio: {},
duration: 0,
progress: 0,
intervalProgress: 0,
intervalState: 0,
interval: 0,
preConvert: false,
};
},
@ -64,31 +121,21 @@ export default {
play() {
this.audio.play();
},
pause() {
this.audio.pause();
window.clearInterval(this.intervalProgress);
window.clearInterval(this.intervalState);
this.pushState();
if (!this.audio.paused) {
this.audio.pause();
}
},
durationChanged() {
this.duration = this.audio.duration;
},
playing() {
window.clearInterval(this.intervalProgress);
window.clearInterval(this.intervalState);
this.intervalProgress = setInterval(() => {
window.clearInterval(this.interval);
this.interval = setInterval(() => {
this.progress = this.audio.currentTime;
this.selectedTrack.percent = (100 / this.duration) * this.progress;
}, 500);
if (this.currentUser._id) {
this.intervalState = setInterval(() => {
this.pushState();
}, 10000);
}
},
audioReset() {
this.audio.pause();
@ -109,14 +156,6 @@ export default {
this.audio.play();
}
},
skipToSecond(second) {
let was_paused = this.audio.paused;
this.audio.pause();
this.audio.currentTime = second;
if (!was_paused) {
this.audio.play();
}
},
playRadio(radio) {
this.$store.commit("tracks/resetSelectedTrack");
this.audio.pause();
@ -145,13 +184,8 @@ export default {
this.pushHistoryItem();
if (this.currentTrackParent.progress) {
this.skipToSecond(this.currentTrackParent.progress.progress);
this.currentTrackParent.progress = undefined;
} else {
// Try to fix SAFARI
this.audio.play();
}
// Try to fix SAFARI
this.audio.play();
},
pushHistoryItem() {
if (!this.currentUser._id) {
@ -198,20 +232,13 @@ export default {
return;
}
if (!this.audio.paused) {
this.pause();
this.audio.pause();
} else if (this.audio.src != "") {
this.audio.play();
}
},
reset(item) {
let parentId = item.parent._id;
if (item.parent.parent && item.parent.parent.tracks) {
parentId = item.parent.parent._id;
}
this.$store.dispatch("user/resetProgress", parentId);
window.clearInterval(this.intervalProgress);
window.clearInterval(this.intervalState);
reset() {
window.clearInterval(this.interval);
if (!this.audio.paused) {
this.audio.pause();
}
@ -272,19 +299,6 @@ export default {
}
this.$store.dispatch("user/savePlayerSettings");
},
pushState() {
if (!this.currentUser._id) {
return;
}
this.progress = this.audio.currentTime;
let item = {
id: this.selectedTrack._id,
parentId: this.currentTrackParent._id,
type: "track",
progress: Math.round(this.progress)
}
this.$store.dispatch("user/saveProgress", item);
},
timeUpdate(event) {
let percent = (event.target.currentTime / event.target.duration) * 100;
if (percent > 10 && !this.preConvert) {
@ -376,11 +390,11 @@ export default {
this.reset();
}
},
selectedTrack(newVal, oldVal) {
selectedTrack(newVal) {
if (newVal._id) {
this.playTrack(newVal);
} else {
this.reset(oldVal);
this.reset();
}
},
},
@ -395,21 +409,17 @@ export default {
z-index: 1001;
box-shadow: 0 0px 4px var(--shadow);
}
#player .cover {
width: 52px;
margin-right: 4px;
}
#playerBar {
overflow: hidden;
max-height: 52px;
}
#playerBar>div {
#playerBar > div {
align-items: center;
}
#playerControls button {
display: flex;
padding: 4px 12px;

View File

@ -1,13 +1,25 @@
<template>
<DialogBase ref="dialogWindow" :title="album_title" @canceled="closed" :showFooter="false" :disableXscroll="true" :disableYscroll="true">
<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" title="Favourite" />
<awesome-icon icon="play" size="2x" class="keepPlaying ma4 primary-text" @click="playProgress" v-if="selectedAlbum.progress" title="Keep playing" />
<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">
@ -15,7 +27,11 @@
</button>
<template v-slot:dropdown-content>
<div>
<button v-for="(item, i) in $store.state.system.lists.visibility" :key="i" @click="setVisibility(item)">
<button
v-for="(item, i) in $store.state.system.lists.visibility"
:key="i"
@click="setVisibility(item)"
>
<awesome-icon :icon="getVisibilityIcon(item)" />{{
getVisibilityText(item)
}}
@ -24,7 +40,10 @@
<button v-if="!selectedAlbum.share._id" @click="shareEnable">
<awesome-icon icon="share" />Share this album
</button>
<button v-if="selectedAlbum.share._id" @click="addShareUrlToClipboard">
<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">
@ -42,7 +61,8 @@
}}</b>
<br />
<span v-if="album_year">
from year <b>{{ album_year }}</b> </span><br />
from year <b>{{ album_year }}</b> </span
><br />
<b>{{ album_tracks.length }}</b> Tracks with a duration of
<b>{{ album_duration }}</b>
</span>
@ -69,6 +89,7 @@
</DropDown>
</div>
</div>
<ul id="trackList" class="tracks">
<li v-for="track in selectedAlbum.tracks" :key="track._id">
<TrackItem :track="track" :showCover="false" />
@ -135,14 +156,6 @@ export default {
}
}
},
playProgress() {
let track = this.selectedAlbum.tracks.find(
(f) => f._id == this.selectedAlbum.progress.id
);
if (track) {
this.$store.dispatch("tracks/play", track);
}
},
closed() {
if (
(window.history.state.back &&
@ -188,19 +201,19 @@ export default {
return visibility == "global"
? "globe"
: visibility == "instance"
? "server"
: visibility == "hidden"
? "eye-slash"
: "user";
? "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";
? "On this server"
: visibility == "hidden"
? "Hide this Album"
: "Only for me";
},
selectAlbum(album) {
this.$store.dispatch("albums/selectAlbum", album);
@ -215,10 +228,6 @@ export default {
shareDisable() {
this.$store.dispatch("albums/shareDisable", this.selectedAlbum);
},
loadUserProgress() {
if (this.selectedTrack.parent._id != this.selectedAlbum._id)
this.$store.dispatch("user/getProgress", this.selectedAlbum);
}
},
computed: {
...mapGetters({
@ -278,19 +287,19 @@ export default {
return this.selectedAlbum.visibility == "global"
? "globe"
: this.selectedAlbum.visibility == "instance"
? "server"
: this.selectedAlbum.visibility == "hidden"
? "eye-slash"
: "user";
? "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";
? "Visible on this instance"
: this.selectedAlbum.visibility == "hidden"
? "Hidden for all users"
: "Visible only for me";
},
isFavourite() {
return (
@ -309,7 +318,6 @@ export default {
this.$refs.dialogWindow.open();
window.addEventListener("keydown", this.keydownListener);
}
this.loadUserProgress();
this.gotoTrack();
} else {
if (this.$refs.dialogWindow.visible) {
@ -331,17 +339,14 @@ export default {
height: 366px;
width: 640px;
}
#header {
position: relative;
background-color: black;
}
#header img {
align-self: center;
width: 256px;
}
#stats {
z-index: 2;
align-items: center;
@ -352,12 +357,10 @@ export default {
border-top: 1px solid #ffffff20;
border-bottom: 1px solid #00000020;
}
.dropdown-activator button {
width: 32px;
height: 32px;
}
#trackList {
background-color: var(--white);
z-index: 1;
@ -367,19 +370,15 @@ export default {
#header {
width: 100%;
}
#albumViewer {
flex-direction: column;
}
}
@media (max-width: 480px),
(max-height: 480px) {
@media (max-width: 480px), (max-height: 480px) {
#albumViewer {
width: 100%;
height: 100%;
}
#trackList {
height: initial;
flex-grow: 1;

View File

@ -1,10 +1,24 @@
<template>
<DialogBase ref="dialogWindow" id="dialogWindow" :title="selectedArtist.name" @canceled="closed" :showFooter="false" :showFullscreenButton="true" :disableXscroll="true" :disableYscroll="true">
<DialogBase
ref="dialogWindow"
id="dialogWindow"
:title="selectedArtist.name"
@canceled="closed"
:showFooter="false"
:showFullscreenButton="true"
:disableXscroll="true"
:disableYscroll="true"
>
<div id="artistViewer">
<div id="header" class="flex-column">
<div id="background" :style="coverBackground" />
<awesome-icon icon="star" size="2x" class="favourite ma4" :class="{ active: isFavourite }" @click="toggleFavourite" />
<awesome-icon icon="play" size="2x" class="keepPlaying ma4 primary-text" @click="playProgress" v-if="selectedArtist.progress" title="Keep playing" />
<awesome-icon
icon="star"
size="2x"
class="favourite ma4"
:class="{ active: isFavourite }"
@click="toggleFavourite"
/>
<h1 @dblclick="dblclick">
{{ selectedArtist.name }}
</h1>
@ -14,20 +28,41 @@
<b>{{ artist_duration }}</b>
</span>
<div id="albumList" class="flex-row showOnMobilePortrait">
<AlbumItem class="ma" :class="{ playing: playingAlbumId == album._id }" v-for="album in selectedArtist.albums" :key="album._id" :item="album" @click="scrollToAlbum(album)" @dblclick="playAlbum(album)" />
<AlbumItem
class="ma"
:class="{ playing: playingAlbumId == album._id }"
v-for="album in selectedArtist.albums"
:key="album._id"
:item="album"
@click="scrollToAlbum(album)"
@dblclick="playAlbum(album)"
/>
</div>
<div id="navigation" class="flex-row center ma-top">
<div class="flex-row grow"></div>
<div class="flex-row">
<button @click="gotoPrevArtist" class="primary ma4" :title="prevArtist.name" :disabled="!prevArtist._id">
<button
@click="gotoPrevArtist"
class="primary ma4"
:title="prevArtist.name"
:disabled="!prevArtist._id"
>
<awesome-icon icon="angle-left" class="ma4" />
</button>
<button @click="gotoNextArtist" class="primary ma4" :title="nextArtist.name" :disabled="!nextArtist._id">
<button
@click="gotoNextArtist"
class="primary ma4"
:title="nextArtist.name"
:disabled="!nextArtist._id"
>
<awesome-icon icon="angle-right" class="ma4" />
</button>
</div>
<div class="flex-row grow right center">
<DropDown v-if="$store.getters['user/isAdministrator']" class="hideOnMobile">
<DropDown
v-if="$store.getters['user/isAdministrator']"
class="hideOnMobile"
>
<button class="flat pa8-left pa8-right">
<awesome-icon icon="ellipsis-v" />
</button>
@ -51,9 +86,23 @@
</div>
<div class="flex-row overflow-y">
<div id="albumList" class="flex-column hideOnMobilePortrait">
<AlbumItem class="ma-top ma-left ma-right" :class="{ playing: playingAlbumId == album._id }" v-for="album in selectedArtist.albums" :key="album._id" :item="album" :id="album._id" :ref="album._id" @click="scrollToAlbum(album)" @dblclick="playAlbum(album)" />
<AlbumItem
class="ma-top ma-left ma-right"
:class="{ playing: playingAlbumId == album._id }"
v-for="album in selectedArtist.albums"
:key="album._id"
:item="album"
:id="album._id"
:ref="album._id"
@click="scrollToAlbum(album)"
@dblclick="playAlbum(album)"
/>
</div>
<ul id="trackList" class="tracks" :class="{ playing: selectedTrack._id != null }">
<ul
id="trackList"
class="tracks"
:class="{ playing: selectedTrack._id != null }"
>
<li v-for="track in selectedArtist.tracks" :key="track._id">
<TrackItem :track="track" :ref="track._id" />
</li>
@ -94,14 +143,6 @@ export default {
}
}
},
playProgress() {
let track = this.selectedArtist.tracks.find(
(f) => f._id == this.selectedArtist.progress.id
);
if (track) {
this.$store.dispatch("tracks/play", track);
}
},
gotoNextArtist() {
this.$store.dispatch("artists/gotoNextArtist");
},
@ -153,10 +194,6 @@ export default {
uploadNewCover() {
this.$store.dispatch("artists/uploadNewCover", this.selectedArtist);
},
loadUserProgress() {
if (!this.isPlaying || this.selectedTrack.parent.parent._id != this.selectedArtist._id)
this.$store.dispatch("user/getProgress", this.selectedArtist);
}
},
computed: {
...mapGetters({
@ -165,7 +202,6 @@ export default {
selectedArtist: ["artists/selectedArtist"],
selectedTrack: ["tracks/selectedTrack"],
favourites: ["user/favourites"],
isPlaying: ["player/isPlaying"]
}),
cover() {
let covers = this.selectedArtist.covers;
@ -230,7 +266,6 @@ export default {
this.$refs.dialogWindow.open();
window.addEventListener("keydown", this.keydownListener);
}
this.loadUserProgress();
this.gotoTrack();
} else {
if (this.$refs.dialogWindow.visible) {
@ -254,7 +289,6 @@ export default {
flex-direction: column;
overflow: hidden;
}
h1,
#stats {
z-index: 1;
@ -263,40 +297,33 @@ h1,
color: var(--white);
text-shadow: 0 1px 2px black;
}
#artistImage {
width: 512px;
max-height: 256px;
}
#header {
position: relative;
background-color: black;
width: 760px;
max-width: 100%;
}
#albumList {
z-index: 1;
overflow-y: auto;
background-color: var(--white);
}
#albumList::-webkit-scrollbar {
display: none;
}
#albumList .album:last-child {
margin-bottom: 12px;
}
#navigation {
z-index: 2;
background-color: #ffffff40;
border-top: 1px solid #ffffff20;
border-bottom: 1px solid #00000020;
}
#trackList {
z-index: 1;
background-color: var(--white);
@ -311,15 +338,12 @@ h1,
width: initial;
height: initial;
}
.dialog-body button {
color: var(--darkgray);
}
.container {
flex-grow: 0;
}
@media (max-width: 480px) {
#albumList {
background-color: initial;
@ -329,21 +353,19 @@ h1,
}
}
@media (max-width: 480px),
(max-height: 480px) {
@media (max-width: 480px), (max-height: 480px) {
#artistViewer {
height: initial;
}
#trackList {
width: initial;
height: initial;
}
#header {
width: initial;
}
}
@media (max-height: 480px) {}
@media (max-height: 480px) {
}
</style>

View File

@ -80,31 +80,6 @@ export default {
context.commit("setHistory", res.data);
});
},
saveProgress(context, item) {
if (context.state._id == -1) {
return;
}
axios
.post(context.rootGetters.server + "/api/user/progress", item, context.rootGetters.headers);
},
getProgress(context, parent) {
if (context.state._id == -1) {
return;
}
axios
.get(context.rootGetters.server + "/api/user/progress/" + parent._id, context.rootGetters.headers)
.then((res) => {
parent.progress = res.data;
});
},
resetProgress(context, parentId) {
if (context.state._id == -1) {
return;
}
axios
.delete(context.rootGetters.server + "/api/user/progress/" + parentId, context.rootGetters.headers);
},
savePlayerSettings(context) {
let body = {
repeat: context.rootGetters["player/repeatType"],