|
@@ -289,6 +289,7 @@ const resizeSeekerbar = () => {
|
|
(getTimeElapsed() / 1000 / currentSong.value.duration) * 100;
|
|
(getTimeElapsed() / 1000 / currentSong.value.duration) * 100;
|
|
};
|
|
};
|
|
const calculateTimeElapsed = () => {
|
|
const calculateTimeElapsed = () => {
|
|
|
|
+ if (experimentalChangableListenMode.value === "participate") return;
|
|
if (
|
|
if (
|
|
playerReady.value &&
|
|
playerReady.value &&
|
|
!noSong.value &&
|
|
!noSong.value &&
|
|
@@ -407,6 +408,7 @@ const toggleSkipVote = (message?) => {
|
|
});
|
|
});
|
|
};
|
|
};
|
|
const youtubeReady = () => {
|
|
const youtubeReady = () => {
|
|
|
|
+ if (experimentalChangableListenMode.value === "participate") return;
|
|
if (!player.value) {
|
|
if (!player.value) {
|
|
ms.setYTReady(false);
|
|
ms.setYTReady(false);
|
|
player.value = new window.YT.Player("stationPlayer", {
|
|
player.value = new window.YT.Player("stationPlayer", {
|
|
@@ -813,9 +815,11 @@ const resetKeyboardShortcutsHelper = () => {
|
|
const sendActivityWatchVideoData = () => {
|
|
const sendActivityWatchVideoData = () => {
|
|
if (
|
|
if (
|
|
!stationPaused.value &&
|
|
!stationPaused.value &&
|
|
- !localPaused.value &&
|
|
+ (!localPaused.value ||
|
|
|
|
+ experimentalChangableListenMode.value === "participate") &&
|
|
!noSong.value &&
|
|
!noSong.value &&
|
|
- player.value.getPlayerState() === window.YT.PlayerState.PLAYING
|
|
+ (experimentalChangableListenMode.value === "participate" ||
|
|
|
|
+ player.value.getPlayerState() === window.YT.PlayerState.PLAYING)
|
|
) {
|
|
) {
|
|
if (activityWatchVideoLastStatus.value !== "playing") {
|
|
if (activityWatchVideoLastStatus.value !== "playing") {
|
|
activityWatchVideoLastStatus.value = "playing";
|
|
activityWatchVideoLastStatus.value = "playing";
|
|
@@ -849,11 +853,17 @@ const sendActivityWatchVideoData = () => {
|
|
),
|
|
),
|
|
source: `station#${station.value.name}`,
|
|
source: `station#${station.value.name}`,
|
|
hostname: window.location.hostname,
|
|
hostname: window.location.hostname,
|
|
- playerState: Object.keys(window.YT.PlayerState).find(
|
|
+ playerState:
|
|
- key =>
|
|
+ experimentalChangableListenMode.value === "participate"
|
|
- window.YT.PlayerState[key] === player.value.getPlayerState()
|
|
+ ? "none"
|
|
- ),
|
|
+ : Object.keys(window.YT.PlayerState).find(
|
|
- playbackRate: playbackRate.value
|
|
+ key =>
|
|
|
|
+ window.YT.PlayerState[key] ===
|
|
|
|
+ player.value.getPlayerState()
|
|
|
|
+ ),
|
|
|
|
+ playbackRate: playbackRate.value,
|
|
|
|
+ experimentalChangableListenMode:
|
|
|
|
+ experimentalChangableListenMode.value
|
|
};
|
|
};
|
|
|
|
|
|
aw.sendVideoData(videoData);
|
|
aw.sendVideoData(videoData);
|
|
@@ -863,6 +873,12 @@ const sendActivityWatchVideoData = () => {
|
|
};
|
|
};
|
|
|
|
|
|
const experimentalChangableListenModeChange = newMode => {
|
|
const experimentalChangableListenModeChange = newMode => {
|
|
|
|
+ experimentalChangableListenMode.value = newMode;
|
|
|
|
+ localStorage.setItem(
|
|
|
|
+ `experimental_changeable_listen_mode_${station.value._id}`,
|
|
|
|
+ newMode
|
|
|
|
+ );
|
|
|
|
+
|
|
if (newMode === "participate") {
|
|
if (newMode === "participate") {
|
|
// Destroy the YouTube player
|
|
// Destroy the YouTube player
|
|
if (player.value) {
|
|
if (player.value) {
|
|
@@ -873,11 +889,6 @@ const experimentalChangableListenModeChange = newMode => {
|
|
// Recreate the YouTube player
|
|
// Recreate the YouTube player
|
|
youtubeReady();
|
|
youtubeReady();
|
|
}
|
|
}
|
|
- experimentalChangableListenMode.value = newMode;
|
|
|
|
- localStorage.setItem(
|
|
|
|
- `experimental_changeable_listen_mode_${station.value._id}`,
|
|
|
|
- newMode
|
|
|
|
- );
|
|
|
|
};
|
|
};
|
|
|
|
|
|
watch(
|
|
watch(
|
|
@@ -1612,13 +1623,15 @@ onBeforeUnmount(() => {
|
|
<div id="station-right-column" class="column">
|
|
<div id="station-right-column" class="column">
|
|
<div
|
|
<div
|
|
class="experimental-listen-mode-container quadrant"
|
|
class="experimental-listen-mode-container quadrant"
|
|
- v-if="experimentalChangableListenModeEnabled"
|
|
+ v-if="
|
|
|
|
+ experimentalChangableListenModeEnabled &&
|
|
|
|
+ !noSong
|
|
|
|
+ "
|
|
v-show="
|
|
v-show="
|
|
experimentalChangableListenMode ===
|
|
experimentalChangableListenMode ===
|
|
'participate'
|
|
'participate'
|
|
"
|
|
"
|
|
>
|
|
>
|
|
- <h2>Want to listen to music?</h2>
|
|
|
|
<button
|
|
<button
|
|
class="button is-primary"
|
|
class="button is-primary"
|
|
@click="
|
|
@click="
|
|
@@ -1630,8 +1643,152 @@ onBeforeUnmount(() => {
|
|
<i class="material-icons icon-with-button"
|
|
<i class="material-icons icon-with-button"
|
|
>music_note</i
|
|
>music_note</i
|
|
>
|
|
>
|
|
- <span>Listen</span>
|
|
+ <span>Listen to music</span>
|
|
|
|
+ </button>
|
|
|
|
+ <button
|
|
|
|
+ v-if="!skipVotesLoaded"
|
|
|
|
+ class="button is-primary disabled"
|
|
|
|
+ content="Skip votes have not been loaded yet"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i class="material-icons icon-with-button"
|
|
|
|
+ >skip_next</i
|
|
|
|
+ >
|
|
|
|
+ Vote to skip the current song
|
|
</button>
|
|
</button>
|
|
|
|
+ <button
|
|
|
|
+ v-else-if="loggedIn"
|
|
|
|
+ :class="[
|
|
|
|
+ 'button',
|
|
|
|
+ 'is-primary',
|
|
|
|
+ { voted: currentSong.voted }
|
|
|
|
+ ]"
|
|
|
|
+ @click="toggleSkipVote()"
|
|
|
|
+ :content="`${
|
|
|
|
+ currentSong.voted ? 'Remove vote' : 'Vote'
|
|
|
|
+ } to Skip Song`"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i class="material-icons icon-with-button"
|
|
|
|
+ >skip_next</i
|
|
|
|
+ >
|
|
|
|
+ Vote to skip the current song -
|
|
|
|
+ {{ currentSong.skipVotes }} votes
|
|
|
|
+ </button>
|
|
|
|
+ <button
|
|
|
|
+ v-else
|
|
|
|
+ class="button is-primary disabled"
|
|
|
|
+ content="Log in to vote to skip songs"
|
|
|
|
+ v-tippy="{ theme: 'info' }"
|
|
|
|
+ >
|
|
|
|
+ <i class="material-icons icon-with-button"
|
|
|
|
+ >skip_next</i
|
|
|
|
+ >
|
|
|
|
+ Vote to skip the current song -
|
|
|
|
+ {{ currentSong.skipVotes }} votes
|
|
|
|
+ </button>
|
|
|
|
+ <div class="row">
|
|
|
|
+ <!-- Ratings -->
|
|
|
|
+ <div
|
|
|
|
+ class="ratings"
|
|
|
|
+ v-if="ratingsLoaded && ownRatingsLoaded"
|
|
|
|
+ :class="{
|
|
|
|
+ liked: currentSong.liked,
|
|
|
|
+ disliked: currentSong.disliked
|
|
|
|
+ }"
|
|
|
|
+ >
|
|
|
|
+ <!-- Like Song Button -->
|
|
|
|
+ <button
|
|
|
|
+ class="button is-success like-song"
|
|
|
|
+ @click="toggleLike()"
|
|
|
|
+ content="Like Song"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i
|
|
|
|
+ class="material-icons icon-with-button"
|
|
|
|
+ :class="{
|
|
|
|
+ liked: currentSong.liked
|
|
|
|
+ }"
|
|
|
|
+ >thumb_up_alt</i
|
|
|
|
+ >{{ currentSong.likes }}
|
|
|
|
+ </button>
|
|
|
|
+
|
|
|
|
+ <!-- Dislike Song Button -->
|
|
|
|
+ <button
|
|
|
|
+ class="button is-danger dislike-song"
|
|
|
|
+ @click="toggleDislike()"
|
|
|
|
+ content="Dislike Song"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i
|
|
|
|
+ class="material-icons icon-with-button"
|
|
|
|
+ :class="{
|
|
|
|
+ disliked: currentSong.disliked
|
|
|
|
+ }"
|
|
|
|
+ >thumb_down_alt</i
|
|
|
|
+ >{{ currentSong.dislikes }}
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ <div id="ratings" class="disabled" v-else>
|
|
|
|
+ <!-- Like Song Button -->
|
|
|
|
+ <button
|
|
|
|
+ class="button is-success like-song disabled"
|
|
|
|
+ content="Ratings have not been loaded yet"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i
|
|
|
|
+ class="material-icons icon-with-button"
|
|
|
|
+ >thumb_up_alt</i
|
|
|
|
+ >
|
|
|
|
+ </button>
|
|
|
|
+
|
|
|
|
+ <!-- Dislike Song Button -->
|
|
|
|
+ <button
|
|
|
|
+ class="button is-danger dislike-song disabled"
|
|
|
|
+ content="Ratings have not been loaded yet"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <i
|
|
|
|
+ class="material-icons icon-with-button"
|
|
|
|
+ >thumb_down_alt</i
|
|
|
|
+ >
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ <add-to-playlist-dropdown
|
|
|
|
+ :song="currentSong"
|
|
|
|
+ placement="top-end"
|
|
|
|
+ >
|
|
|
|
+ <template #button>
|
|
|
|
+ <div
|
|
|
|
+ id="add-song-to-playlist"
|
|
|
|
+ content="Add Song to Playlist"
|
|
|
|
+ v-tippy
|
|
|
|
+ >
|
|
|
|
+ <div class="control has-addons">
|
|
|
|
+ <button
|
|
|
|
+ class="button is-primary"
|
|
|
|
+ >
|
|
|
|
+ <i class="material-icons">
|
|
|
|
+ playlist_add
|
|
|
|
+ </i>
|
|
|
|
+ </button>
|
|
|
|
+ <button
|
|
|
|
+ class="button"
|
|
|
|
+ id="dropdown-toggle"
|
|
|
|
+ >
|
|
|
|
+ <i class="material-icons">
|
|
|
|
+ {{
|
|
|
|
+ showPlaylistDropdown
|
|
|
|
+ ? "expand_more"
|
|
|
|
+ : "expand_less"
|
|
|
|
+ }}
|
|
|
|
+ </i>
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </template>
|
|
|
|
+ </add-to-playlist-dropdown>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
<div
|
|
class="player-container quadrant"
|
|
class="player-container quadrant"
|
|
@@ -2896,12 +3053,32 @@ onBeforeUnmount(() => {
|
|
display: flex;
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
justify-content: center;
|
|
- row-gap: 8px;
|
|
+ row-gap: 16px;
|
|
padding: 16px 16px;
|
|
padding: 16px 16px;
|
|
|
|
|
|
- h2 {
|
|
+ .row {
|
|
- margin: 0;
|
|
+ display: flex;
|
|
- font-size: 20px;
|
|
+ flex-direction: row;
|
|
|
|
+ column-gap: 16px;
|
|
|
|
+
|
|
|
|
+ .ratings {
|
|
|
|
+ flex: 2;
|
|
|
|
+ display: flex;
|
|
|
|
+ flex-direction: row;
|
|
|
|
+ column-gap: 16px;
|
|
|
|
+
|
|
|
|
+ button {
|
|
|
|
+ flex: 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .addToPlaylistDropdown {
|
|
|
|
+ flex: 1;
|
|
|
|
+
|
|
|
|
+ .button.is-primary {
|
|
|
|
+ flex: 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2920,6 +3097,18 @@ onBeforeUnmount(() => {
|
|
.bg-bubbles li:nth-child(10) {
|
|
.bg-bubbles li:nth-child(10) {
|
|
display: none;
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ .experimental-listen-mode-container {
|
|
|
|
+ row-gap: 8px;
|
|
|
|
+
|
|
|
|
+ .row {
|
|
|
|
+ column-gap: 8px;
|
|
|
|
+
|
|
|
|
+ .ratings {
|
|
|
|
+ column-gap: 8px;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@-webkit-keyframes square {
|
|
@-webkit-keyframes square {
|