feat: screenshare fullscreen button + pip spotlight, fix screenshare view

- Remove revert-to-grid logic that was overriding EC's natural screenshare
  spotlight, causing fullscreen to show user avatars instead of the screen
- Add fullscreen button to call controls (visible when screensharing) that
  requests fullscreen on the call embed container
- Add FullscreenButton component with enter/exit SVG icons to Controls.tsx
- PIP mode: sync setPipMode to CallControl; auto-enable spotlight when
  screenshare is active in pip so the screenshare fills the window
- Make useCallControlState accept undefined control for safe use in
  CallEmbedProvider
- Add package-lock.json to .gitignore (generated by local npm install)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 23:16:43 -04:00
parent e07c9cc491
commit eeba02aeca
6 changed files with 106 additions and 13 deletions
+21
View File
@@ -21,6 +21,7 @@ import * as css from './styles.css';
import {
ChatButton,
ControlDivider,
FullscreenButton,
MicrophoneButton,
ScreenShareButton,
SoundButton,
@@ -32,13 +33,16 @@ import { settingsAtom } from '../../state/settings';
import { useResizeObserver } from '../../hooks/useResizeObserver';
import { stopPropagation } from '../../utils/keyboard';
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
import { useCallEmbedRef } from '../../hooks/useCallEmbed';
type CallControlsProps = {
callEmbed: CallEmbed;
};
export function CallControls({ callEmbed }: CallControlsProps) {
const controlRef = useRef<HTMLDivElement>(null);
const callEmbedRef = useCallEmbedRef();
const [compact, setCompact] = useState(document.body.clientWidth < 500);
const [isFullscreen, setIsFullscreen] = useState(false);
useResizeObserver(
useCallback(() => {
@@ -49,6 +53,20 @@ export function CallControls({ callEmbed }: CallControlsProps) {
useCallback(() => controlRef.current, []),
);
useEffect(() => {
const onFullscreenChange = () => setIsFullscreen(!!document.fullscreenElement);
document.addEventListener('fullscreenchange', onFullscreenChange);
return () => document.removeEventListener('fullscreenchange', onFullscreenChange);
}, []);
const handleFullscreen = useCallback(() => {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
callEmbedRef.current?.requestFullscreen();
}
}, [callEmbedRef]);
const { microphone, video, sound, screenshare, spotlight } = useCallControlState(
callEmbed.control,
);
@@ -338,6 +356,9 @@ export function CallControls({ callEmbed }: CallControlsProps) {
screenshare ? callEmbed.control.toggleScreenshare() : setShareConfirm(true)
}
/>
{screenshare && (
<FullscreenButton isFullscreen={isFullscreen} onToggle={handleFullscreen} />
)}
</Box>
</Box>
{!compact && <ControlDivider />}