Skip to content

feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation#133

Closed
YizukiAme wants to merge 1 commit intoTHU-MAIC:mainfrom
YizukiAme:codex/issue-102-presentation-mode
Closed

feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation#133
YizukiAme wants to merge 1 commit intoTHU-MAIC:mainfrom
YizukiAme:codex/issue-102-presentation-mode

Conversation

@YizukiAme
Copy link
Contributor

@YizukiAme YizukiAme commented Mar 19, 2026

Summary

Adds a dedicated Presentation Mode for the classroom view, addressing #102. When activated, the slide canvas fills the entire screen with all UI chrome hidden — ideal for projecting lectures to students.

Also partially addresses #115 and #60 — the new fullscreen presentation mode gives the whiteboard and quiz areas significantly more screen real estate, and repositions whiteboard hints so they aren't obscured by the controls overlay.

Features

Fullscreen Presentation

  • Entry: Toolbar button (⛶) or F11 key
  • Exit: ESC key, F11 again, or toolbar button
  • Header auto-hides, both sidebars collapse, slide fills the viewport

Idle Auto-Hide (3s)

  • After 3 seconds of no mouse activity, the toolbar/roundtable controls fade out and the cursor hides
  • Moving the mouse or touching the screen restores controls instantly
  • Smart suspension: idle-hide pauses automatically when the user is typing, recording, or processing voice input — controls stay visible during active interaction

Keyboard Navigation

  • Previous slide
  • Next slide
  • Space Play/Pause (not next-slide, matching video-player UX expectations)
  • ESC Exit fullscreen
  • Guards prevent shortcuts from hijacking focused controls (sliders, text inputs, etc.)

F11 Interception

  • F11 is intercepted to use our Fullscreen API instead of browser-native fullscreen
  • This ensures ESC can always exit fullscreen (browser F11 fullscreen normally requires F11 to exit)
  • Works reliably in Chromium-based browsers; best-effort in Firefox

Whiteboard Hint Repositioning

  • Zoom hint and reset-view button move from bottom corners to top corners in fullscreen
  • Prevents the Roundtable overlay from obscuring whiteboard controls
  • Hints re-show when entering fullscreen for discoverability

Files Changed

File Change
components/stage.tsx Core presentation state, fullscreen API, idle timer, keyboard handler, F11 interception
components/canvas/canvas-area.tsx Pass-through isPresenting and onTogglePresentation props
components/canvas/canvas-toolbar.tsx Fullscreen toggle button (Maximize2/Minimize2 icons)
components/roundtable/index.tsx Presentation overlay mode, interaction state callback
components/whiteboard/whiteboard-canvas.tsx Fullscreen-aware hint positioning
lib/i18n/stage.ts i18n strings for fullscreen button labels

Verification

  • eslint — passes on all modified files
  • prettier --check — passes on all modified files
  • tsc --noEmit — no new errors (pre-existing unrelated error in latex-to-omml.ts)
  • Manual test: Chrome fullscreen, idle-hide, keyboard navigation, F11 interception
  • Manual test: Firefox fullscreen (F11 best-effort)
  • Manual test: Whiteboard hints reposition correctly in fullscreen

Notes

  • F11 interception works best in Chromium-based browsers. Firefox may occasionally deny the Fullscreen API request from F11 keydown events due to stricter user-gesture policies — the toolbar button always works as a reliable fallback.

Closes #102

Copy link
Contributor

@wyuc wyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this! Keyboard nav and idle-hide are well thought out, especially the suspension during voice input.

One thing worth revisiting: the idle-hide currently fades out the entire Roundtable (line 913), including the speech bubble. So if an agent is mid-sentence in fullscreen, the bubble disappears after 3s of no mouse activity. That feels off for presentation use where the audience is just watching.

Maybe split it so the toolbar hides on idle but the bubble stays visible when there's active speech (currentSpeech or lectureSpeech non-null)?

@YizukiAme YizukiAme force-pushed the codex/issue-102-presentation-mode branch from 2d748ca to 59d92ca Compare March 20, 2026 04:09
@YizukiAme
Copy link
Contributor Author

Thanks for this! Keyboard nav and idle-hide are well thought out, especially the suspension during voice input.

One thing worth revisiting: the idle-hide currently fades out the entire Roundtable (line 913), including the speech bubble. So if an agent is mid-sentence in fullscreen, the bubble disappears after 3s of no mouse activity. That feels off for presentation use where the audience is just watching.

Maybe split it so the toolbar hides on idle but the bubble stays visible when there's active speech (currentSpeech or lectureSpeech non-null)?

Valid point! Working on this~~

@YizukiAme YizukiAme requested a review from wyuc March 20, 2026 04:47
@YizukiAme
Copy link
Contributor Author

YizukiAme commented Mar 20, 2026

Thanks for this! Keyboard nav and idle-hide are well thought out, especially the suspension during voice input.
One thing worth revisiting: the idle-hide currently fades out the entire Roundtable (line 913), including the speech bubble. So if an agent is mid-sentence in fullscreen, the bubble disappears after 3s of no mouse activity. That feels off for presentation use where the audience is just watching.
Maybe split it so the toolbar hides on idle but the bubble stays visible when there's active speech (currentSpeech or lectureSpeech non-null)?

Valid point! Working on this~~

Fixed in commits 5ef128bacddc99 !

The idle-hide is now split per-section inside Roundtable:

  • Toolbar, teacher avatar (left), student avatars + user controls (right) → fade out on idle as before
  • Center speech bubble → always visible, so the audience can keep reading

Additionally:

  • Container background/border/blur become transparent during idle-hide, so only the speech bubble floats over the slide — much cleaner
  • Space key (play/pause) no longer resets the idle timer, avoiding a brief panel flash mid-presentation. Arrow keys still show controls for scene navigation.

@YizukiAme YizukiAme force-pushed the codex/issue-102-presentation-mode branch from acddc99 to e86df4c Compare March 20, 2026 11:06
@wyuc
Copy link
Contributor

wyuc commented Mar 21, 2026

We've been thinking about how discussion content should work in presentation mode, and this ties into the next release roadmap (see Discussion #150).

Currently in your PR, the roundtable area becomes a frosted glass bar with bubbles still rendered on top. We'd like to take that further: instead of keeping the full roundtable strip, show discussion messages as transient popup bubbles in the corners of the screen.

The idea:

  • Bottom-left corner: teacher / current speaker bubble
  • Bottom-right corner: student agent bubble
  • Bubble slides up, stays while text is revealed, then fades out after a few seconds
  • New message from the same role replaces the previous bubble in place
  • Frosted glass background on each bubble, agent avatar + name + role color (reusing existing roundtable colors)
  • When buffer-level pause is active (your PR feat: discussion buffer-level pause (freeze text reveal without aborting SSE) #129), bubbles stay visible instead of fading
  • Toolbar toggle to turn the popup bubbles on/off

This way users still see the discussion without a persistent UI strip at the bottom. If you're interested in picking this up, we'll include it in the next release.

Like this:

image

@YizukiAme
Copy link
Contributor Author

YizukiAme commented Mar 21, 2026

Love this direction! This is exactly what I had in mind when building the presentation mode — I originally considered a danmaku-style overlay but held off because I wasn't sure it aligned with the team's vision. Great to see we're on the same page.

I'm happy to pick this up. A few thoughts on the implementation:

  • Corner popup bubbles: Slide-up + fade-out with AnimatePresence should be straightforward. I'll reuse the existing roundtable avatar/color system.
  • Buffer-pause integration (PR feat: discussion buffer-level pause (freeze text reveal without aborting SSE) #129): When paused → bubble stays pinned, no fade-out. This ties in naturally since I already have the isDiscussionPaused state wired through.
  • Toolbar toggle: Will add a Discussion toggle button (like the mockup shows) to let users turn the popup overlay on/off.

One question: this touches the whiteboard hint positioning (bottom corners → top corners during fullscreen), and #169 may revert the pan/zoom changes that include the current hint layout. Should I develop against the current codebase and resolve conflicts if #169 lands first, or should I wait for #169 to merge? My preference is to start now and rebase later — happy to hear your thoughts.

Will open a draft PR once I have the core popup mechanics working~

@wyuc
Copy link
Contributor

wyuc commented Mar 21, 2026

Thanks for the enthusiasm! A couple of clarifications on scope:

Popup bubbles vs pause UX are orthogonal. This feature is purely about the bubble display mechanics (slide-in, fade-out, replacement logic, toggle). How they interact with pause/buffer state is #129's concern — no need to couple them here. Just expose the message content; the pause integration can come later without touching this code.

Whiteboard hints are not part of presentation mode. The hint positioning is internal to the whiteboard component — on main today there's zero isPresenting awareness in whiteboard-canvas.tsx. So the #169 question doesn't apply here; you don't need to wait for it or worry about conflicts.

TL;DR: keep this focused on the corner popup bubble UI itself. No need to block on #169 or build in pause logic.

@YizukiAme
Copy link
Contributor Author

Thanks for the enthusiasm! A couple of clarifications on scope:

Popup bubbles vs pause UX are orthogonal. This feature is purely about the bubble display mechanics (slide-in, fade-out, replacement logic, toggle). How they interact with pause/buffer state is #129's concern — no need to couple them here. Just expose the message content; the pause integration can come later without touching this code.

Whiteboard hints are not part of presentation mode. The hint positioning is internal to the whiteboard component — on main today there's zero isPresenting awareness in whiteboard-canvas.tsx. So the #169 question doesn't apply here; you don't need to wait for it or worry about conflicts.

TL;DR: keep this focused on the corner popup bubble UI itself. No need to block on #169 or build in pause logic.

Agreed on the popup bubble scope! 👍 — no whiteboard code, no pause logic.

Quick separate note on this PR (#133) though: it currently modifies whiteboard-canvas.tsx to move the zoom hint and reset-view button from bottom corners to top corners during fullscreen (commits 91d264c). If #169 lands first, those elements get removed entirely, so this PR would need a rebase to drop that chunk.

Not blocking — just flagging so we're aware. Happy to rebase whenever needed~

@YizukiAme YizukiAme force-pushed the codex/issue-102-presentation-mode branch 4 times, most recently from 58f0de5 to f160c80 Compare March 21, 2026 07:30
…navigation

- Fullscreen via toolbar button or F11; exit via ESC/F11/button
- Header auto-hides, sidebars collapse, slide fills viewport
- Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible
- Smart suspension: idle-hide pauses during typing/recording/voice input
- Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit)
- F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native
- Whiteboard hints reposition from bottom to top corners in fullscreen
- i18n: fullscreen/exitFullscreen keys (zh-CN + en-US)

Closes THU-MAIC#102
@YizukiAme YizukiAme force-pushed the codex/issue-102-presentation-mode branch 2 times, most recently from 8f5e5a5 to af2b0e3 Compare March 21, 2026 09:14
@wyuc
Copy link
Contributor

wyuc commented Mar 25, 2026

Hi @YizukiAme, thanks for this PR — it laid the groundwork for presentation mode and we've since built on top of it. The main branch now includes fullscreen, idle-hide, and keyboard navigation, so this PR has been fully superseded. Closing it out, but your contribution is appreciated and credited in the roadmap. 🙏

@wyuc wyuc closed this Mar 25, 2026
@YizukiAme
Copy link
Contributor Author

Hi @YizukiAme, thanks for this PR — it laid the groundwork for presentation mode and we've since built on top of it. The main branch now includes fullscreen, idle-hide, and keyboard navigation, so this PR has been fully superseded. Closing it out, but your contribution is appreciated and credited in the roadmap. 🙏

Thanks for closing this! Yeah, I actually meant to close it myself after #195 was merged — #195 included all the functionality from #133 (plus the popup bubbles and input flow). Forgot to come back and tidy this one up 😅 Appreciate the cleanup~~!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: 希望有课程讲解的画面全屏或最大化的功能

2 participants