diff --git a/src/app/api/run/move/route.ts b/src/app/api/run/move/route.ts index d691e2b..4df1e38 100644 --- a/src/app/api/run/move/route.ts +++ b/src/app/api/run/move/route.ts @@ -4,11 +4,11 @@ import * as Core from "@/modules/live-run/core"; import { getSession } from "@/modules/account/core"; export async function POST(req: NextRequest) { - const { runId, moves } = await req.json(); + const { runId, moves, file } = await req.json(); - if (!runId || !moves) + if (!runId || !moves || file === undefined) return NextResponse.json( - { error: "body requires runId and moves" }, + { error: "body requires runId and moves and file" }, { status: 400 }, ); @@ -27,9 +27,9 @@ export async function POST(req: NextRequest) { { status: 401 }, ); - console.log(moves); + console.log(moves, file); - const run = await Core.addLiveRunMoves(liveRun.id, moves); + const run = await Core.addLiveRunMoves(liveRun.id, file, moves); return NextResponse.json({ ok: true, run }); } diff --git a/src/app/api/view-run/route.ts b/src/app/api/view-run/route.ts index 3d68064..ca8959a 100644 --- a/src/app/api/view-run/route.ts +++ b/src/app/api/view-run/route.ts @@ -1,7 +1,7 @@ import { WebSocketServer, WebSocket } from "ws"; import Redis from "ioredis"; -import { LiveRunMove } from "@/modules/live-run/types"; import { NextRequest, NextResponse } from "next/server"; +import { LiveRunEvent } from "@/modules/live-run/types"; export function GET(req: NextRequest) { const headers = new Headers(); @@ -11,17 +11,18 @@ export function GET(req: NextRequest) { } export function UPGRADE(client: WebSocket, server: WebSocketServer) { - console.log("A client connected"); - const subscriber = new Redis(); let runId: string; client.once("message", (message) => { runId = message.toString(); + let file: string | null; const sendText = async () => { const text = await subscriber.get(`liveRunText:${runId}`); - client.send(JSON.stringify({ moves: [], text })); + if (client.readyState === WebSocket.OPEN) { + client.send(JSON.stringify({ file, moves: [], text })); + } }; sendText(); @@ -32,15 +33,14 @@ export function UPGRADE(client: WebSocket, server: WebSocketServer) { if (err) { console.error("Failed to subscribe", err); client.close(1011, "Redis subscription failed"); - } else { - console.log(`Subscribed to ${count} channels`); } }); subscriber.on("message", (channel, message) => { - const moves = JSON.parse(message); + const data: LiveRunEvent = JSON.parse(message); + file = data.file; if (client.readyState === WebSocket.OPEN) { - client.send(JSON.stringify({ moves, text: null })); + client.send(JSON.stringify({ moves: data.moves, file, text: null })); } }); }); @@ -48,7 +48,6 @@ export function UPGRADE(client: WebSocket, server: WebSocketServer) { client.once("close", async () => { if (runId) await subscriber.unsubscribe(`liveRun:${runId}`); subscriber.quit(); - console.log("Client disconnected, Redis unsubscribed"); }); client.on("error", (err) => { diff --git a/src/app/runs/[runId]/components/Editor.tsx b/src/app/runs/[runId]/components/Editor.tsx index fe16172..2036ff9 100644 --- a/src/app/runs/[runId]/components/Editor.tsx +++ b/src/app/runs/[runId]/components/Editor.tsx @@ -39,7 +39,13 @@ function getLanguageExtension(lang: Language) { } } -export default function Editor({ run }: { run: LiveRun | null | undefined }) { +export default function Editor({ + run, + setFile, +}: { + run: LiveRun | null | undefined; + setFile: (s: string | null) => void; +}) { const [editorView, setEditorView] = useState(); const scheduledTimeouts = useRef([]); const [text, setText] = useState(""); @@ -55,9 +61,13 @@ export default function Editor({ run }: { run: LiveRun | null | undefined }) { }; ws.onmessage = (m) => { - const data: { moves: LiveRunMove[]; text: string | null } = JSON.parse( - m.data, - ); + const data: { + moves: LiveRunMove[]; + file: string | null; + text: string | null; + } = JSON.parse(m.data); + + setFile(data.file); if (data.text) { setText(data.text); diff --git a/src/app/runs/[runId]/page.tsx b/src/app/runs/[runId]/page.tsx index 8c7360a..cf477c5 100644 --- a/src/app/runs/[runId]/page.tsx +++ b/src/app/runs/[runId]/page.tsx @@ -12,19 +12,20 @@ import ProblemCard from "@/app/problems/components/ProblemCard"; import ProfileCard from "./components/ProfileCard"; import { getProblem } from "@/modules/problems/actions"; import { useParams } from "next/navigation"; +import { useState } from "react"; export default function Run() { const params = useParams<{ runId: string }>(); - const [run] = useActionInterval(() => getLiveRun(params.runId), 5000, [ - params, - ]); + const [run] = useAction(() => getLiveRun(params.runId), [params]); const [problem] = useAction( async () => (run?.id ? getProblem(run.problem) : null), [run], ); + const [file, setFile] = useState(null); + const chatMessages: ChatMessage[] = [ { user: "Alice", message: "Nice split!", time: "1:53" }, { user: "Bob", message: "Watch out for the string problem!", time: "1:54" }, @@ -83,10 +84,10 @@ export default function Run() { {/* Code */}
- myfile.js + {file}
- +
diff --git a/src/modules/live-run/core.ts b/src/modules/live-run/core.ts index 1ba4876..d19915a 100644 --- a/src/modules/live-run/core.ts +++ b/src/modules/live-run/core.ts @@ -50,7 +50,11 @@ export async function removeLiveRun(id: string) { /** * Add moves to a live run (ephemeral) */ -export async function addLiveRunMoves(runId: string, moves: LiveRunMove[]) { +export async function addLiveRunMoves( + runId: string, + file: string, + moves: LiveRunMove[], +) { const redis = new Redis(); // Make sure the live run exists @@ -58,7 +62,7 @@ export async function addLiveRunMoves(runId: string, moves: LiveRunMove[]) { if (!runExists) throw "Invalid live run"; // Publish the new moves to subscribers - await redis.publish(`liveRunMoves:${runId}`, JSON.stringify(moves)); + await redis.publish(`liveRunMoves:${runId}`, JSON.stringify({ file, moves })); // Get the last text (from Redis) const lastText = (await redis.get(`liveRunText:${runId}`)) || ""; diff --git a/src/modules/live-run/types.ts b/src/modules/live-run/types.ts index 99d98e8..75b9268 100644 --- a/src/modules/live-run/types.ts +++ b/src/modules/live-run/types.ts @@ -18,3 +18,9 @@ export interface LiveRunMove { insert: string; }; } + +export interface LiveRunEvent { + moves: LiveRunMove[]; + file: string | null; + text: string | null; +}