ITRadio/client/src/components/player.vue

404 lines
12 KiB
Vue

<template>
<div class="player">
<div class="player__cover">
<q-skeleton v-if="loaderPlay" height="100%" />
<img v-else :src="currentPlay.art" alt="player" />
</div>
<div class="player__content">
<div class="player__top">
<q-skeleton
v-if="loaderPlay"
type="circle"
class="player__btn m--skeleton"
/>
<template v-else>
<button
v-if="currentPlay.isPlay"
@click="handlerPause"
class="button player__btn m--pause"
></button>
<button
v-else
@click="handlerPlay"
class="button player__btn m--play"
></button>
</template>
<div class="player__executor">
<q-skeleton v-if="loaderPlay" class="player__executor m--skeleton" />
<template v-else>
{{ currentPlay.title || '—' }}
</template>
<span>
<q-skeleton v-if="loaderPlay" />
<template v-else>
{{ currentPlay.artist || '—' }}
</template>
</span>
</div>
<template v-if="user?.id">
<q-skeleton v-if="loaderPlay" class="player__favorites m--skeleton" />
<div
v-else
class="player__favorites"
:class="[isFavorites && 'm--active']"
@click="handlerFavorites"
></div>
</template>
<div class="player__tools">
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton" />
<FormKit
v-else
v-model="isUserMusic"
type="toggle"
label="Включить мою музыку"
:disabled="!user?.id || userSongList.length === 0"
/>
<q-skeleton v-if="loaderPlay" class="player__tools m--skeleton" />
<div v-else class="player__volume">
<span @click="changeVolume('set')" />
<input type="range" v-model="songVolume" @change="changeVolume" />
</div>
</div>
</div>
<div class="player__bottom">
<div
class="player__time"
:class="!loaderPlay && !isUserMusic && 'm--ether'"
>
<q-skeleton v-if="loaderPlay" />
<template v-else-if="isUserMusic">
{{ getTime(playerInfo.currentTime) }} /
{{ getTime(playerInfo.duration) }}
</template>
<template v-else> Эфир </template>
</div>
<div class="player__progress">
<q-skeleton v-if="loaderPlay" height="5px" />
<input
v-else
:disabled="!isUserMusic"
type="range"
v-model="playerInfo.progress"
/>
</div>
</div>
</div>
</div>
</template>
<script>
import { app, audio as Player } from '@/services';
export default {
name: 'player',
components: {},
data() {
return {
isFavorites: false,
isPlayRadio: false,
connection: null,
isUserMusic: !this.$store.state.currentPlay.live,
songVolume: this.$store.state.currentPlay.volume,
playerInfo: {
progress: 0,
currentTime: 0,
duration: 0,
},
};
},
computed: {
user() {
return this.$store.state.user;
},
currentPlay() {
return this.$store.state.currentPlay;
},
player() {
return this.$store.state.player;
},
userSongList() {
return this.$store.state.userFavorite?.songs || [];
},
loaderPlay() {
return this.$store.state.currentPlay.isLoader;
},
},
watch: {
currentPlay: {
immediate: false,
handler(to, from) {
if (this.isUserMusic === this.currentPlay.live) {
this.isUserMusic = !this.currentPlay.live;
}
if (this.user?.id && to.id !== from.id) {
this.checkSongIsFavorite();
}
if (!this.currentPlay.live && to.id !== from.id) {
this.getAudio(this.currentPlay.azura_id);
}
},
},
userSongList: {
immediate: false,
handler(to, from) {
if (this.user?.id && to.length !== from.length) {
this.checkSongIsFavorite();
}
},
},
isUserMusic: {
immediate: false,
handler() {
if (this.isUserMusic === this.currentPlay.live) {
this.changeLive();
}
},
},
},
created() {
this.connectionPlayer();
},
mounted() {
console.log(this.currentPlay);
this.$store.dispatch('initPlayer');
if (this.user?.id) {
this.checkSongIsFavorite();
this.getSongList();
}
this.playerInfo.progress = this.currentPlay.live ? 100 : 0;
if (!this.currentPlay.live && this.userSongList?.length > 0) {
this.$store.dispatch('setCurrentPlay', {
...this.userSongList[this.currentPlay.currentIndex || 0],
live: false,
});
this.getAudio(
this.userSongList[this.currentPlay.currentIndex || 0]?.azura_id,
);
if (this.player.target) {
this.player.target.addEventListener('timeupdate', this.updateProgress);
}
}
if (!this.user?.id) {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
currentIndex: null,
});
}
},
methods: {
connectionPlayer() {
if (this.connection) {
this.connection.removePlay();
}
this.connection = new Player();
this.connection.init();
this.connection.onHandler(this.getPlaying);
},
checkSongIsFavorite() {
app
.getCheckFavoriteSong(this.currentPlay.azura_id || this.currentPlay.id)
.then((res) => {
this.isFavorites = res.is_favorite;
})
.catch((err) => {
console.error(err);
});
},
removeFavorites(song) {
app
.removeFavorites(song)
.then(() => {
this.getSongList();
})
.catch((err) => {
this.showLoader = false;
console.error(err);
});
},
getPlaying(e) {
const jsonData = JSON.parse(e.data);
if (jsonData?.pub?.data) {
const data = jsonData?.pub?.data;
if (this.currentPlay.live) {
if (data.np.station.listen_url !== this.player.target.src) {
console.log(
'data.np.station.listen_url',
data.np.station.listen_url,
);
this.$store.dispatch('changePlayer', data.np.station.listen_url);
const params = {
...this.currentPlay,
...data.np.now_playing.song,
azura_id: data.np.now_playing.song.id,
isLoader: false,
live: true,
currentIndex: null,
};
delete params.unique_id;
this.$store.dispatch('setCurrentPlay', params);
}
}
}
},
updateProgress(e) {
this.playerInfo = {
...this.playerInfo,
progress:
(this.player.target.currentTime / this.player.target.duration) * 100,
currentTime: this.player.target.currentTime,
};
if (this.player.target.currentTime === this.player.target.duration) {
let currentIndex = this.currentPlay.currentIndex + 1;
if (
!this.userSongList[currentIndex]?.azura_id ||
currentIndex === null
) {
currentIndex = 0;
}
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
...this.userSongList[currentIndex],
currentIndex,
});
}
},
handlerPlay() {
console.log(this.currentPlay);
console.log(this.player);
this.$store.dispatch('handlerPlayer', { play: true });
},
handlerPause() {
this.$store.dispatch('handlerPlayer', { pause: true });
},
getSongList() {
app
.getFavoriteList()
.then((res) => {
this.$store.dispatch('setUserFavorite', { songs: res });
console.log('res.length', res.length);
if (res.length === 0) {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
});
}
})
.catch((err) => {
console.error(err);
});
},
handlerFavorites() {
if (this.user?.id) {
const params = {
...this.currentPlay,
azura_id: Number(this.currentPlay.id)
? this.currentPlay.azura_id
: this.currentPlay.id,
};
if (!this.isFavorites) {
delete params.id;
app
.createFavoriteForUser(params)
.then(() => {
this.isFavorites = !this.isFavorites;
this.getSongList();
})
.catch((err) => {
console.error(err);
});
} else {
console.log(params);
app
.removeFavorites(params)
.then(() => {
this.getSongList();
})
.catch((err) => {
console.error(err);
});
}
} else {
this.$emit('shopAuthentication', true);
}
},
changeVolume(type) {
let volume = this.songVolume;
if (type === 'set') {
volume = this.songVolume === 0 ? 0.9 : 0.01;
this.songVolume = this.songVolume === 0 ? 100 : 0;
} else {
volume = this.songVolume / 100;
}
if (volume === 0) volume = 0.01;
this.$store.dispatch('handlerPlayer', { volume });
},
getAudio(id) {
app
.getAudio(id)
.then((res) => {
const blob = new Blob([res], { type: 'application/audio' });
const audioUrl = URL.createObjectURL(blob);
this.$store.dispatch('changePlayer', audioUrl);
this.player.target.addEventListener(
'timeupdate',
this.updateProgress,
);
blob.arrayBuffer().then((buffer) => {
var audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
audioContext.decodeAudioData(buffer, (decodedData) => {
this.playerInfo.duration = decodedData.duration;
});
});
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
isLoader: false,
});
})
.catch((err) => {
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
isLoader: false,
});
console.debug(err);
});
},
changeLive() {
if (this.currentPlay.live) {
console.log('избранное');
this.playerInfo.progress = 0;
const params = {
...this.userSongList[this.currentPlay.currentIndex || 0],
live: false,
isLoader: true,
};
if (!this.currentPlay.currentIndex) params.currentIndex = 0;
this.$store.dispatch('setCurrentPlay', params);
} else {
this.playerInfo.progress = 100;
this.$store.dispatch('setCurrentPlay', {
...this.currentPlay,
live: true,
isLoader: true,
});
console.log('поток');
}
},
getTime(value) {
let minutes = Math.floor(value / 60);
let seconds = Math.round(value % 60);
let paddedMinutes = minutes < 10 ? '0' + minutes : minutes;
let paddedSeconds = seconds < 10 ? '0' + seconds : seconds;
if (!paddedMinutes) paddedMinutes = '00';
if (!paddedSeconds) paddedSeconds = '00';
return `${paddedMinutes}:${paddedSeconds}`;
},
},
};
</script>