Skip to main content

Going Fullscreen

Every camera tile and every Location View panel can go fullscreen — a big view of the camera with a toolbar for switching between the 60° image, the 360° pano, the map, and timelapse playback. Simple feature, but there's one conceptual snag worth learning properly, because it confuses everyone: the app has two different definitions of "fullscreen," and both are true.

The two fullscreen signals​

Signal 1: expandedCameraId. One field in mapCameraInteractiveStore — a camera id or null. Every CameraDetails tile derives its own state from it:

const isImgExpanded = expandedCameraId === cameraDetails.cId;

That single comparison is the one-camera-at-a-time rule: setting a new id implicitly collapses whoever was expanded before, with no bookkeeping.

Signal 2: isLocationViewInFullscreen(visibleLocationViewPanels). The Location View can also be "fullscreen" in a different sense — showing exactly one of its three panels (image / map / wide). The helper just counts true flags and returns visibleCount === 1. Crucially, a map-only view is fullscreen by this definition while expandedCameraId stays null — there's no camera being expanded, just a panel filling the screen.

Consumers that need "is anything fullscreen right now?" — like MapButtonsFL deciding whether to show collapse buttons and the view-switching toolbar — must OR the two:

const isCameraDetailsExpanded =
expandedCameraId || isLocationViewInFullscreen(visibleLocationViewPanels);

If you're debugging a stuck expand/collapse button, first ask which signal is active. An expanded tile and an expanded map panel look identical on screen and completely different in state.

Ways in​

Expand mode opens from more places than you'd guess: the tile's expand button, the mobile more-options drawer ("View Full Screen", "See 360 view" — which opens straight into 360 mode — and "View Time Lapse", which opens with playback pre-loaded), a parent passing a fullscreenRequest prop (how the pinned-cameras section drives it), and Location View's image panel entering fullscreen (fullscreen === 'image', which sets expandedCameraId via an effect in CameraImageWrapper).

Inside, ExpandMode shows one of three views — camera, 360, or map (an embedded FeatureMap) — switched by the toolbar's toggle.

One toolbar, three hosts​

ExpandedImageButtons is the bottom toolbar in every expanded view, and it's rendered by three different parents — ExpandMode, CameraImageWrapper, and MapButtonsFL. It shows the camera name and last-moved time, a playback button (and scrub slider during playback), the camera/360/map toggle, an open-in-new link, and a compass readout of the pano scroll offset. Hosts hide what doesn't apply via btnsToHide, and — the important part — each host wires the toggle differently:

  • ExpandMode → flips local expandedMode state
  • CameraImageWrapper → rewrites visibleLocationViewPanels (a real layout change)
  • MapButtonsFL → routes to the tile-view or location-view handler depending on context

Same toolbar, three meanings of "switch view." When a toggle behaves oddly, identify the host first.

Ways out​

Every close path resolves to one of the two signals: the X inside ExpandMode, the backdrop click, and exitFullscreenRequest all setExpandedCameraId(null); the map panel's collapse resets visibleLocationViewPanels to a split layout, which flips isLocationViewInFullscreen back to false. If fullscreen "won't close," you're clearing the wrong signal.

Wrapping up​

Two orthogonal fullscreen signals — a camera id and a panel count — OR'd together by anything that needs the whole truth; a single toolbar with three hosts that interpret its toggle three ways; and every entrance and exit reducible to writes on those two signals.

Next feature: Timelapse, which you've already seen hiding inside this toolbar.