From f36f39ef51602d619a44411598c134ab1b86f51f Mon Sep 17 00:00:00 2001 From: valeboth <109695782+valeboth@users.noreply.github.com> Date: Wed, 26 Aug 2026 11:38:43 +0300 Subject: [PATCH] fix: keep the room on refresh + Overseerr button in the matches list - persist the current room in localStorage (saveRoom on enterSwipe); on load, if a room is saved, resume the swipe session instead of dropping to the lobby. Invite link (?code) still wins; Start over clears it. - add the Overseerr request button to the matches list too (in solo, likes show up here), reusing the room request route + the shared PIN flow - health -> v3.2 --- public/app.js | 34 +++++++++++++++++++++++++++++++++- src/index.ts | 2 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/public/app.js b/public/app.js index 19c4f4c..cf787bd 100644 --- a/public/app.js +++ b/public/app.js @@ -370,10 +370,35 @@ async function enterSwipe() { state.lastSwiped = null; updateUndo(); syncMediaToggle(); + saveRoom(); // persist so a refresh restores the session instead of kicking to the lobby connectWs(); await loadDeck(); } +// Persist / restore the current room so a page refresh keeps you in the game. +function saveRoom() { + if (state.room) { + localStorage.setItem("cinemate_room", JSON.stringify({ ...state.room, soloMode: state.soloMode })); + } +} +function clearRoom() { + localStorage.removeItem("cinemate_room"); +} +function restoreRoom() { + const raw = localStorage.getItem("cinemate_room"); + if (!raw) return false; + try { + const r = JSON.parse(raw); + if (!r || !r.id) return false; + state.room = r; + state.soloMode = !!r.soloMode; + state.mediaType = r.media_type || "movie"; + return true; + } catch { + return false; + } +} + async function loadDeck() { $("card").classList.add("hidden"); $("deck-empty").classList.add("hidden"); @@ -755,7 +780,9 @@ async function showMatchesList() { list.innerHTML = "

Loading…

"; try { const res = await api(`/api/rooms/${state.room.id}/matches`); - renderCardList(list, res.matches || [], "No matches yet."); + renderCardList(list, res.matches || [], "No matches yet.", (m) => + overseerrRequest(`/api/rooms/${state.room.id}/request`, { tmdb_id: m.tmdb_id }), + ); } catch (e) { list.innerHTML = "

Error: " + e.message + "

"; } @@ -788,6 +815,7 @@ function resetData() { state.userId = null; state.username = null; exitEditMode(); + clearRoom(); state.genreLevels = {}; state.avoidGenres = new Set(); state.seeds = []; @@ -858,8 +886,12 @@ function init() { if (state.userId && state.username) { updateUserBadge(); if (pendingCode) { + // An invite link wins over any saved room. $("join-code-input").value = pendingCode; handleJoinRoom(); + } else if (restoreRoom()) { + // Refreshed mid-game → resume the room instead of dropping to the lobby. + enterSwipe(); } else { showScreen("screen-lobby"); } diff --git a/src/index.ts b/src/index.ts index 5f137ef..f57571c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,7 @@ export { Room } from "./durable-objects/room"; const app = new Hono<{ Bindings: Env }>(); -app.get("/api/health", (c) => c.json({ ok: true, service: "cinemate", version: "v3.1" })); +app.get("/api/health", (c) => c.json({ ok: true, service: "cinemate", version: "v3.2" })); app.route("/api/users", users); app.route("/api/profile", profile);