'use client'; /** * The classroom pane — the third column, and the REAL classroom inside it. * * Not a preview and not an iframe: `ClassroomSurface` is the same component * `/classroom/[id]` mounts, wrapped in `WorkbenchPanelProvider` so the chrome * it does not need in here (its own header, the Pro switch, the global * controls) drops out. The provider is applied HERE rather than around the * element that built it because React resolves context by where an element * renders, not where it was constructed. * * Read-only. A course saved from Discover is not yours to edit: the classroom * already refuses (`isOwner` gates the Pro switch and the auto-edit entry, and * the server would refuse the write anyway), so this header only NAMES that * state. The start-learning button stays — learning (playing back) a saved * course is a perfectly legitimate thing to do with one. */ import { Eye, Play } from 'lucide-react'; import { memo } from 'react'; import { useI18n } from '@/lib/hooks/use-i18n'; import { cn } from '@/lib/utils/cn'; import { ClassroomSurface } from '@/components/classroom/ClassroomSurface'; import { useStageStore } from '@/lib/store/stage'; import { useWorkbenchStore } from '@/lib/workbench/session-store'; import { WorkbenchPanelProvider } from '@/lib/workbench/panel-context'; import { useWorkbenchProEditing } from '@/lib/workbench/use-workbench-pro-edit'; import { WorkspaceCourseTabs, type WorkspaceCourseTabItem } from './WorkspaceCourseTabs'; import { PaneFoldButton } from './PaneFoldButton'; export const WorkspaceClassroomPane = memo(function WorkspaceClassroomPane({ browser, readOnly, playback, hidden, onCollapse, }: { /** * The tab strip's state and callbacks. The pane owns no tab state: the * ordered set, the active id and the URL all live in the shell, and this is * the seam they arrive through. */ readonly browser: { /** The open courses, in tab order — id, display name, and whether one is being written. */ readonly tabs: readonly WorkspaceCourseTabItem[]; readonly activeCourseId: string; readonly onActivateCourse: (courseId: string) => void; /** * The real close: closing the last tab drops `?course=`, shuts the pane and * forgets this chat's set. `onCollapse` below is minimise and preserves it. */ readonly onCloseCourse: (courseId: string) => void; }; readonly readOnly: boolean; /** Full-screen playback: the pane is the whole surface and drops its header. */ readonly playback: boolean; /** * Collapsed. Hidden rather than unmounted: remounting would run the whole * classroom load again — clearing the media store and the whiteboard * history on the way — for a course that never changed. `Stage` still drops * out of edit mode because this pane publishes visibility through its host * context; the attached Chat store is not involved. */ readonly hidden: boolean; /** * Minimise this pane, leaving its reopen tab and this chat's remembered set * intact. Rendered at the end of the pane's own header — see `PaneFoldButton` * for why it is not a grip on the seam any more. */ readonly onCollapse?: () => void; }) { const courseId = browser.activeCourseId; const { t } = useI18n(); const scenes = useStageStore((s) => s.scenes); const setPlaybackOn = useWorkbenchStore((s) => s.setPlaybackOn); // Pro-mode sizing for a hosted classroom: fill the 16:9 card instead of // keeping the full-page editor's studio margin, which reads as a second // letterbox inside a pane. useWorkbenchProEditing(); return ( ); });