From 026dacde06c9141445f4d0a7fa494861f33f5d8f Mon Sep 17 00:00:00 2001 From: Jaden Scali Date: Fri, 11 Sep 2026 00:23:59 -0400 Subject: [PATCH] Fix: bug anon in transcript --- src/app/room/classChat/index.tsx | 69 ++++++++++++++------------------ src/app/room/page.tsx | 18 ++++++--- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/app/room/classChat/index.tsx b/src/app/room/classChat/index.tsx index 34ce543..dc5a860 100644 --- a/src/app/room/classChat/index.tsx +++ b/src/app/room/classChat/index.tsx @@ -8,7 +8,7 @@ import PostItem from "./post"; import ChatHeader from "./ChatHeader"; import ChatInput from "./ChatInput"; import FilterTabs from "./FilterTabs"; -import type { Question, Comment, Role } from "@/utils/types"; +import type { Question, Comment, Role, User } from "@/utils/types"; import { showRateLimitToast } from "@/components/RateLimitToast"; // --------------------------------------------------------------------------- @@ -416,21 +416,18 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) { authorRole: Role; }) => { if (!payload.authorName) return; - setQuestions((prev) => - prev.map((q) => - q.id === payload.id - ? { - ...q, - user: { - id: payload.authorId, - utorid: payload.authorUtorid ?? undefined, - username: payload.authorName!, - pfp: "", - role: payload.authorRole, - }, - } - : q - ) + const author: User = { + id: payload.authorId, + utorid: payload.authorUtorid ?? undefined, + username: payload.authorName, + pfp: "", + role: payload.authorRole, + }; + setQuestions((prev) => prev.map((q) => (q.id === payload.id ? { ...q, user: author } : q))); + // The export reads historyRef, so the reveal has to land there too — + // otherwise a live anonymous question stays unattributed in the transcript. + historyRef.current = historyRef.current.map((q) => + q.id === payload.id ? { ...q, user: author } : q ); }; @@ -443,29 +440,23 @@ export default function ClassChat({ chatHistoryRef }: ClassChatProps) { authorRole: Role; }) => { if (!payload.authorName) return; - setQuestions((prev) => - prev.map((q) => - q.id === payload.questionId - ? { - ...q, - replies: q.replies.map((r) => - r.id === payload.id - ? { - ...r, - user: { - id: payload.authorId, - utorid: payload.authorUtorid ?? undefined, - username: payload.authorName!, - pfp: "", - role: payload.authorRole, - }, - } - : r - ), - } - : q - ) - ); + const author: User = { + id: payload.authorId, + utorid: payload.authorUtorid ?? undefined, + username: payload.authorName, + pfp: "", + role: payload.authorRole, + }; + const attachAuthor = (q: Question): Question => + q.id === payload.questionId + ? { + ...q, + replies: q.replies.map((r) => (r.id === payload.id ? { ...r, user: author } : r)), + } + : q; + + setQuestions((prev) => prev.map(attachAuthor)); + historyRef.current = historyRef.current.map(attachAuthor); }; // Rate-limit refusals arrive already phrased for the user, and they are not diff --git a/src/app/room/page.tsx b/src/app/room/page.tsx index e5b1ddd..d3ab0e2 100644 --- a/src/app/room/page.tsx +++ b/src/app/room/page.tsx @@ -43,9 +43,17 @@ function generateAndDownloadTxt(questions: Question[], sessionTitle: string): vo const sep = "─".repeat(44); const lines: string[] = [`=== ${sessionTitle} ===`, new Date().toLocaleString(), ""]; - function label(user: { username: string; utorid?: string } | null): string { - if (!user) return "Anonymous"; - return user.utorid ? `${user.username} - ${user.utorid}` : user.username; + // Transcripts are instructor-only, so they mirror the reveal view rather than + // the student view: an anonymous author is named and tagged, never redacted. + function label(post: { + user: { username: string; utorid?: string } | null; + isAnonymous?: boolean; + }): string { + if (!post.user) return "Anonymous"; + const name = post.user.utorid + ? `${post.user.username} - ${post.user.utorid}` + : post.user.username; + return post.isAnonymous ? `${name} (anonymous)` : name; } if (questions.length === 0) { @@ -53,12 +61,12 @@ function generateAndDownloadTxt(questions: Question[], sessionTitle: string): vo } else { for (const q of questions) { lines.push(sep); - lines.push(`${q.timestamp} — ${label(q.user)}`); + lines.push(`${q.timestamp} — ${label(q)}`); lines.push(`Q: ${q.content}`); if (q.replies.length > 0) { lines.push(""); for (const r of q.replies) { - lines.push(` ${r.timestamp} — ${label(r.user)}`); + lines.push(` ${r.timestamp} — ${label(r)}`); lines.push(` A: ${r.content}`); } }