game on #27
@@ -83,15 +83,24 @@ class SessionConsumer(WebsocketConsumer):
|
|||||||
for track in tracks:
|
for track in tracks:
|
||||||
if next:
|
if next:
|
||||||
session.current_track = track
|
session.current_track = track
|
||||||
|
next = False
|
||||||
break
|
break
|
||||||
if session.current_track == track:
|
if session.current_track == track:
|
||||||
next = True
|
next = True
|
||||||
|
if next:
|
||||||
|
# We didnt get a next track, so it must have been the last one
|
||||||
|
session.current_track = None
|
||||||
else:
|
else:
|
||||||
session.current_track = tracks.first()
|
session.current_track = tracks.first()
|
||||||
session.save()
|
session.save()
|
||||||
async_to_sync(self.channel_layer.group_send)(
|
if session.current_track is None:
|
||||||
self.session_name, {"type": "announce.track"}
|
async_to_sync(self.channel_layer.group_send)(
|
||||||
)
|
self.session_name, {"type": "announce.done"}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
async_to_sync(self.channel_layer.group_send)(
|
||||||
|
self.session_name, {"type": "announce.track"}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def announce(self, event):
|
def announce(self, event):
|
||||||
@@ -100,6 +109,8 @@ class SessionConsumer(WebsocketConsumer):
|
|||||||
|
|
||||||
def announce_track(self, event):
|
def announce_track(self, event):
|
||||||
self.send(text_data=json.dumps({"track": {}}))
|
self.send(text_data=json.dumps({"track": {}}))
|
||||||
|
def announce_done(self, event):
|
||||||
|
self.send(text_data=json.dumps({"done": {}}))
|
||||||
|
|
||||||
def voted(self, event):
|
def voted(self, event):
|
||||||
user = event["user"]
|
user = event["user"]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Markazi_Text, Nunito } from "next/font/google";
|
import { Markazi_Text, Nunito } from "next/font/google";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useAuth } from "react-oidc-context";
|
import { useAuth } from "react-oidc-context";
|
||||||
@@ -28,8 +29,12 @@ export default function Lobby() {
|
|||||||
const [spotifyId, setSpotifyId] = useState<string | null>(null);
|
const [spotifyId, setSpotifyId] = useState<string | null>(null);
|
||||||
const auth = useAuth();
|
const auth = useAuth();
|
||||||
const user = getUser();
|
const user = getUser();
|
||||||
|
const router = useRouter();
|
||||||
const controller = useSpotifyIframe();
|
const controller = useSpotifyIframe();
|
||||||
const [revealed, setRevealed] = useState(false);
|
const [revealed, setRevealed] = useState(false);
|
||||||
|
const [playingPercentage, setPlayingPercentage] = useState(0);
|
||||||
|
const [secondsLeft, setSecondsLeft] = useState(30);
|
||||||
|
const [state, setState] = useState("lobby"); // lobby, playing, waiting, loading
|
||||||
|
|
||||||
// Main message handler and dispatcher
|
// Main message handler and dispatcher
|
||||||
function onMessage(e) {
|
function onMessage(e) {
|
||||||
@@ -42,6 +47,8 @@ export default function Lobby() {
|
|||||||
getTrack();
|
getTrack();
|
||||||
} else if (key == "voted") {
|
} else if (key == "voted") {
|
||||||
voteUser(data[key]);
|
voteUser(data[key]);
|
||||||
|
} else if (key == "done") {
|
||||||
|
router.push("/post-game");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(data);
|
console.log(data);
|
||||||
@@ -78,6 +85,7 @@ export default function Lobby() {
|
|||||||
|
|
||||||
function startSession() {
|
function startSession() {
|
||||||
setSessionState("voting");
|
setSessionState("voting");
|
||||||
|
setState("loading");
|
||||||
getTrack();
|
getTrack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +160,7 @@ export default function Lobby() {
|
|||||||
|
|
||||||
async function getTrack() {
|
async function getTrack() {
|
||||||
setSongLoading(true);
|
setSongLoading(true);
|
||||||
|
setState("loading");
|
||||||
setUserList((prevUserList) => {
|
setUserList((prevUserList) => {
|
||||||
return prevUserList.map((user) => {
|
return prevUserList.map((user) => {
|
||||||
return { ...user, hidden: false };
|
return { ...user, hidden: false };
|
||||||
@@ -174,6 +183,9 @@ export default function Lobby() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function nextTrack() {
|
async function nextTrack() {
|
||||||
|
console.log("nextTrack");
|
||||||
|
setState("loading");
|
||||||
|
setRevealed(false);
|
||||||
setSongLoading(true);
|
setSongLoading(true);
|
||||||
sessionSocket.send(
|
sessionSocket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@@ -183,19 +195,64 @@ export default function Lobby() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function endPlay() {
|
||||||
|
controller?.seek(100);
|
||||||
|
}
|
||||||
|
|
||||||
// Spotify Player stuff
|
// Spotify Player stuff
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (controller) {
|
if (controller) {
|
||||||
console.log("Loaded track:", spotifyId);
|
console.log("Loaded track:", spotifyId);
|
||||||
controller.loadUri(`spotify:track:${spotifyId}`);
|
controller.loadUri(`spotify:track:${spotifyId}`);
|
||||||
controller.play();
|
controller.play();
|
||||||
|
// Note: do not set playing state here, but later when its actually playing.
|
||||||
|
console.log(controller._listeners);
|
||||||
|
if (controller._listeners["playback_update"].length === 0) {
|
||||||
|
controller.addListener("playback_update", (e) => {
|
||||||
|
updatePlayback(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Spotify player not initialized");
|
console.log("Spotify player not initialized");
|
||||||
}
|
}
|
||||||
}, [controller, spotifyId]);
|
}, [controller, spotifyId]);
|
||||||
|
function updatePlayback(e) {
|
||||||
|
let duration = e.data.duration;
|
||||||
|
let playingPosition = e.data.position;
|
||||||
|
const playingSeconds = Math.floor((duration - playingPosition) / 1000);
|
||||||
|
setPlayingPercentage((playingPosition / duration) * 100);
|
||||||
|
setSecondsLeft((s) => {
|
||||||
|
setState((state) => {
|
||||||
|
if (playingSeconds >= 1) {
|
||||||
|
return "playing";
|
||||||
|
}
|
||||||
|
if (state == "playing" && s <= 0) {
|
||||||
|
console.log("track ended");
|
||||||
|
return "waiting";
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
});
|
||||||
|
return playingSeconds;
|
||||||
|
});
|
||||||
|
}
|
||||||
async function playTrack() {
|
async function playTrack() {
|
||||||
controller.play();
|
controller.play();
|
||||||
}
|
}
|
||||||
|
async function pauseTrack() {
|
||||||
|
controller.togglePlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("useEffect state:", state);
|
||||||
|
if (state == "waiting") {
|
||||||
|
setRevealed(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setState("next");
|
||||||
|
}, 5000);
|
||||||
|
} else if (state == "next") {
|
||||||
|
nextTrack();
|
||||||
|
}
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
if (sessionState == "lobby") {
|
if (sessionState == "lobby") {
|
||||||
return (
|
return (
|
||||||
@@ -218,7 +275,8 @@ export default function Lobby() {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={startSession}
|
onClick={startSession}
|
||||||
className="rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400"
|
className="rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400 disabled:bg-yellow-900 disabled:text-gray-400"
|
||||||
|
disabled={sessionId === null}
|
||||||
>
|
>
|
||||||
START
|
START
|
||||||
</button>
|
</button>
|
||||||
@@ -265,21 +323,17 @@ export default function Lobby() {
|
|||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col items-center justify-between gap-4 p-24">
|
<main className="flex min-h-screen flex-col items-center justify-between gap-4 p-24">
|
||||||
<div className="flex w-full items-start justify-between text-center">
|
<div className="flex w-full items-start justify-between text-center">
|
||||||
<div className="flex-1">
|
<div className="flex-1"></div>
|
||||||
{" "}
|
|
||||||
<button
|
|
||||||
onClick={() => setRevealed(!revealed)}
|
|
||||||
className="rounded bg-blue-600 px-4 py-2 text-white"
|
|
||||||
>
|
|
||||||
{revealed ? "Gordijntje dicht" : "Gordijntje open"}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-1 items-center justify-center">
|
<div className="flex flex-1 items-center justify-center">
|
||||||
<div className="flex h-[170px] w-[170px] items-center justify-center rounded-full border-2 bg-orange-400">
|
{(state == "playing" || state == "waiting") && (
|
||||||
<div className="text-5xl text-white drop-shadow-sm drop-shadow-black">
|
<div
|
||||||
<button onClick={getTrack}>30</button>
|
className={`flex h-[170px] w-[170px] items-center justify-center rounded-full border-2 ${state == "playing" ? "bg-orange-400" : ""} ${state == "waiting" ? "bg-green-400" : ""}`}
|
||||||
|
>
|
||||||
|
<div className="text-5xl text-white drop-shadow-sm drop-shadow-black">
|
||||||
|
{secondsLeft}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-1 flex-row items-center justify-end gap-4">
|
<div className="flex flex-1 flex-row items-center justify-end gap-4">
|
||||||
@@ -289,15 +343,15 @@ export default function Lobby() {
|
|||||||
>
|
>
|
||||||
PLAY
|
PLAY
|
||||||
</button>
|
</button>
|
||||||
<Link
|
<button
|
||||||
href="/pause"
|
onClick={pauseTrack}
|
||||||
className="w-30 rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400"
|
className="w-30 rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400"
|
||||||
>
|
>
|
||||||
PAUSE
|
PAUSE
|
||||||
</Link>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="w-30 rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400"
|
className="w-30 rounded-lg border-2 border-black bg-yellow-500 p-4 text-2xl font-extrabold text-blue-600 hover:bg-yellow-400"
|
||||||
onClick={nextTrack}
|
onClick={endPlay}
|
||||||
>
|
>
|
||||||
NEXT
|
NEXT
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user