From a16d340cb7332ac8d669dfd441ac63156e99fda0 Mon Sep 17 00:00:00 2001 From: Johnny322 Date: Tue, 24 Feb 2026 21:46:27 +0100 Subject: [PATCH] Fix multiplayer responsiveness for viewer --- .gitea/workflows/on-push-feature.yml | 10 +++++ .gitea/workflows/on-push-master.yml | 1 - src/App.vue | 65 +++++++++++++++++++++------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/.gitea/workflows/on-push-feature.yml b/.gitea/workflows/on-push-feature.yml index 42291b7..2715732 100644 --- a/.gitea/workflows/on-push-feature.yml +++ b/.gitea/workflows/on-push-feature.yml @@ -44,3 +44,13 @@ jobs: mkdir -p /www/jeopardy-test find /www/jeopardy-test -mindepth 1 -maxdepth 1 -exec rm -rf {} + cp -r /repos/music-jeopardy/dist/. /www/jeopardy-test/ + - name: Restart realtime service (if available) + run: | + set -e + if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload + systemctl enable --now music-jeopardy-realtime.service + systemctl restart music-jeopardy-realtime.service + else + echo "systemctl not available in this runner container. Restart on host manually." + fi diff --git a/.gitea/workflows/on-push-master.yml b/.gitea/workflows/on-push-master.yml index 045b9ea..9efac44 100644 --- a/.gitea/workflows/on-push-master.yml +++ b/.gitea/workflows/on-push-master.yml @@ -36,7 +36,6 @@ jobs: mkdir -p /www/jeopardy find /www/jeopardy -mindepth 1 -maxdepth 1 -exec rm -rf {} + cp -r /repos/music-jeopardy/dist/. /www/jeopardy/ - - name: Restart realtime service (if available) run: | set -e diff --git a/src/App.vue b/src/App.vue index e035ac1..787e04f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -540,22 +540,6 @@ export default { const socket = new WebSocket(wsUrl) this.socket = socket - await new Promise((resolve, reject) => { - socket.onopen = () => { - if (this.socket !== socket) return - this.socketConnected = true - this.syncError = '' - if (this.isHost) this.publishState() - resolve() - } - socket.onerror = () => { - if (this.socket !== socket) return - this.socketConnected = false - this.syncError = 'Realtime connection failed' - reject(new Error('Realtime connection failed')) - } - }).catch(() => {}) - socket.onmessage = async (event) => { let message: RealtimeMessage | null = null try { @@ -574,6 +558,22 @@ export default { this.socketConnected = false } } + + await new Promise((resolve, reject) => { + socket.onopen = () => { + if (this.socket !== socket) return + this.socketConnected = true + this.syncError = '' + if (this.isHost) this.publishState() + resolve() + } + socket.onerror = () => { + if (this.socket !== socket) return + this.socketConnected = false + this.syncError = 'Realtime connection failed' + reject(new Error('Realtime connection failed')) + } + }).catch(() => {}) }, buildRealtimeState(): RealtimeState { return { @@ -611,6 +611,7 @@ export default { this.queuedRemoteState = state return } + const previousClipUrl = this.currentClipUrl this.isApplyingRemote = true try { const selected = state.selectedGameName @@ -628,6 +629,38 @@ export default { } finally { this.isApplyingRemote = false } + await nextTick() + this.syncRemotePlayback(previousClipUrl !== this.currentClipUrl) + }, + getCurrentTileStatus() { + if (!this.currentTileKey) return 'available' + return this.tiles[this.currentTileKey]?.status || 'available' + }, + syncRemotePlayback(forceReload: boolean) { + if (this.canControlGame) return + const player = this.getPlayer() + if (!player) return + const tileStatus = this.getCurrentTileStatus() + + if (!this.currentClipUrl || tileStatus === 'won' || tileStatus === 'void') { + player.pause() + return + } + + if (forceReload) { + player.currentTime = 0 + player.load() + } + + if (tileStatus === 'paused') { + player.pause() + return + } + + if (tileStatus === 'playing' || tileStatus === 'guessed') { + this.ensureAudioContext() + player.play().catch(() => {}) + } }, getPlayer() { return this.$refs.player as HTMLAudioElement | undefined