This commit is contained in:
2025-08-20 21:51:51 +02:00
parent 2a23f1dedc
commit c23cb63817
2 changed files with 86 additions and 21 deletions
+11
View File
@@ -83,12 +83,21 @@ class SessionConsumer(WebsocketConsumer):
for track in tracks:
if next:
session.current_track = track
next = False
break
if session.current_track == track:
next = True
if next:
# We didnt get a next track, so it must have been the last one
session.current_track = None
else:
session.current_track = tracks.first()
session.save()
if session.current_track is None:
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"}
)
@@ -100,6 +109,8 @@ class SessionConsumer(WebsocketConsumer):
def announce_track(self, event):
self.send(text_data=json.dumps({"track": {}}))
def announce_done(self, event):
self.send(text_data=json.dumps({"done": {}}))
def voted(self, event):
user = event["user"]
+70 -16
View File
@@ -1,6 +1,7 @@
"use client";
import { useState, useEffect } from "react";
import { Markazi_Text, Nunito } from "next/font/google";
import { useRouter } from "next/navigation";
import Image from "next/image";
import Link from "next/link";
import { useAuth } from "react-oidc-context";
@@ -28,8 +29,12 @@ export default function Lobby() {
const [spotifyId, setSpotifyId] = useState<string | null>(null);
const auth = useAuth();
const user = getUser();
const router = useRouter();
const controller = useSpotifyIframe();
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
function onMessage(e) {
@@ -42,6 +47,8 @@ export default function Lobby() {
getTrack();
} else if (key == "voted") {
voteUser(data[key]);
} else if (key == "done") {
router.push("/post-game");
}
}
console.log(data);
@@ -78,6 +85,7 @@ export default function Lobby() {
function startSession() {
setSessionState("voting");
setState("loading");
getTrack();
}
@@ -152,6 +160,7 @@ export default function Lobby() {
async function getTrack() {
setSongLoading(true);
setState("loading");
setUserList((prevUserList) => {
return prevUserList.map((user) => {
return { ...user, hidden: false };
@@ -174,6 +183,9 @@ export default function Lobby() {
}
async function nextTrack() {
console.log("nextTrack");
setState("loading");
setRevealed(false);
setSongLoading(true);
sessionSocket.send(
JSON.stringify({
@@ -183,19 +195,64 @@ export default function Lobby() {
);
}
async function endPlay() {
controller?.seek(100);
}
// Spotify Player stuff
useEffect(() => {
if (controller) {
console.log("Loaded track:", spotifyId);
controller.loadUri(`spotify:track:${spotifyId}`);
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 {
console.log("Spotify player not initialized");
}
}, [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() {
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") {
return (
@@ -218,7 +275,8 @@ export default function Lobby() {
</div>
<button
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
</button>
@@ -265,21 +323,17 @@ export default function Lobby() {
return (
<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-1">
{" "}
<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-1"></div>
<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={`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">
<button onClick={getTrack}>30</button>
{secondsLeft}
</div>
</div>
)}
</div>
<div className="flex flex-1 flex-row items-center justify-end gap-4">
@@ -289,15 +343,15 @@ export default function Lobby() {
>
PLAY
</button>
<Link
href="/pause"
<button
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"
>
PAUSE
</Link>
</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"
onClick={nextTrack}
onClick={endPlay}
>
NEXT
</button>