CallControls holds the microphone, camera and a shared screen as
toggles, then Leave. ParticipantTile shows a camera's frame from the
host or the person's initials, their name with a mark when muted, and a
ring while they speak. VideoCallGrid lays tiles in even rows as far as
they fit across its measured width; a short last row centers at the
full rows' width. ScreenShareView names who presents and offers Stop
presenting for your own share, the call's tiles beside or below.
VoiceCallBar tells where a call is, how long it has run and who is in
it, with the microphone and Leave. IncomingCallDialog rings with the
caller's picture; Accept or Decline answers each ring once, and Escape
declines. HuddleIndicator rings while a huddle is live; a press joins.
The recorder's device toggle and the camera's name chip now have one
home in media. People: member names sort whatever their case, a
status's words save trimmed, and a profile card's local time ticks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The crate had two maps from a file's name to its icon, in chat and in the
file tree, and they disagreed. One map now lives in primitives, over the
Lucide file-* icons, and chat, agent, the file tree and the directory
listing use it. FileIcon draws it for a file or a folder. FileItem is a
file's row, a ListItem with its size and when it changed. FileList is the
directory listing. FileGrid lays tiles in the order given, with a cursor
seeded from the owner's pick: arrows by tile and by row, Home, End, Enter
and a double press to open. The count of what fits a width has one home,
layout's columns_for, and fit builds on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The floating list under a Select, Combobox or MultiSelect was at least its
trigger's width with no ceiling, so a long choice ran it past the window
and its rows never ellipsized. It now stops at the window's width less the
window margin on each side, so gpui snaps it inside. The camera preview
and the model viewer check their ratio through primitives::checked_ratio.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ScreenRecorderControls holds a recording in one pill: Record, then a live
dot and the time it has run beside pause or resume and stop, with mic and
camera toggles. CameraPreview shows host frames in the camera's shape, or
the camera off. MicLevelMeter lights segments up to the level, amber and
red near the top, with tones shared from data_display. DeviceSelector
picks a microphone, camera or speaker through Select, which may now be
empty while shut. ModelViewer shows the host's frame for an orbit that a
drag, the arrows, Command-scroll, + and - and a reset move; the orbit is
seeded from the host so fast drags add up. The gallery draws a stone
torus per orbit and frees each replaced frame.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SelectableList keeps the owner's last selection and the one it last
sent. A selection the owner makes, on first paint or later, moves the
cursor to its first row; the echo of the list's own pick leaves the
cursor where the pick put it. The playlist's keys start from the song
under way. The waveform's bar count and inset move into `fit`, tested
beside `resample`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AudioPlayer sets a song's cover, title and artist over a scrubber with
the time played and left, the transport and the volume. AudioWaveform
draws peaks gathered to the bars that fit, dark as far as it has played,
and seeks by press, drag and keys, with the time tip the scrubber shares.
AudioSpectrum shows levels by pitch. VolumeControl mutes from its speaker,
and moving its slider while muted unmutes. PlaybackSpeedControl picks from
a menu. MediaControls holds shuffle, back, play, forward and repeat.
Playlist builds on SelectableList: the song under way is lit with moving
bars, and Enter or a double press plays another.
The video player's bar now rests while the stage itself holds focus, a
key it takes wakes the bar, and a press on a resting bar only wakes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fade restarted an animation id at each rest and wake, and gpui hands
that id to every descendant: the scrubber's drag, hover and focus handle
and the buttons' focus were rebuilt under it. The bar's opacity now reads
the time since the last change through motion::since_change. The stage
tracks focus even without key handlers, so a focused bar button keeps
the bar up. The player's tests move to their own file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only the bar fades now, so the caption stays while the controls rest, and
the caption chip can shrink, so a long line wraps inside a narrow player.
A focused media button keeps Space to itself, since gpui presses it on
the release. The player and the strip let Command and Control letters
pass. The scrubber's tip splits the free width by the pointer's share and
stays over the track at both ends. An inline edit's label gives way with
an ellipsis beside fixed parts.
The player is a Tab stop only when a key does something, logs its
captions, keys its fade by its own id, and logs a failed wake.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scrubber shows what has loaded, what has played and its chapters, names
the time under the pointer, seeks by press and gpui's drag, and steps by
the slider's keys; over_media lights it for a dark layer. VideoPlayer
shows the host's frame in its shape with a caption and a control bar over
it: the scrubber, play, the time, speed, captions, picture in picture and
full screen, each only with its handler; the bar rests after a still
pointer while it plays, on one wake from the executor's timer. Keys:
Space and K, J and L, the arrows, C and F. VideoThumbnailStrip lays frames
along the length under a playhead with a trim whose handles drag and whose
ends I and O set. SubtitleEditor edits cues in place: times as mm:ss.mmm,
kept in order, a time that does not read kept out with the reason shown.
InlineEdit is a Tab stop with the ring; it hands focus back after Enter or
Escape and keeps its text on Enter's release. overlays::media_button is
shared by the lightbox and the player's bar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With an aspect, a corner drag sizes the crop by whichever side the pointer
moved further, so a drag straight up or down resizes it too. The upload
tells the host the fitted crop once per file, whether the host keeps it or
not; a host that dropped it had set off a loop of reports. The annotator's
Escape stops only when it lets a chosen mark go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ImageCropper crops a picture by a box in shares of it: a press holds a
corner, a side or the body (crop::grip_at), a drag through gpui's drag
moves them (crop::dragged), kept inside the picture with a least side;
with an aspect only the corners size it and the box keeps its shape; the
arrows move it. The picture sits inset by half a handle, the focus border
outside it, so handles on its edge stay whole and it keeps its shape.
ImageUpload (T06e) takes pictures only, from a drop or the dialog
(forms::taken, DropZone::kinds), decodes the file for its shape, and with
no crop yet reports the largest centered box of its aspect once. The
annotator draws boxes, arrows, lines and numbered pins in chart colors
through forms::pen; Select chooses a mark, Delete removes it, and Cmd-Z
and Shift-Cmd-Z undo and redo through forms::History. theme.media() holds
their sizes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage's picture carries an id, so gpui keeps its frame and asks for
the next: an animated picture plays, turned or not. A viewer whose picture
has not loaded or cannot open is no Tab stop. AGENTS.md: img() moves an
animated picture's frames only with an id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new chapter, src/media. ImageViewer fits a picture to its stage and
zooms by the document steps, by keys, buttons and Cmd-scroll about the
pointer; a drag through gpui's drag, a scroll or the arrows pan it once it
overhangs; R turns it a quarter at a time. gpui paints pictures without a
transform, so media::turn turns the decoded frames off the main thread,
an asset keyed by the picture and the turn; `image` 0.25, which gpui
already decodes with, is now a dependency. ImageThumbnail shows a picture
in its own shape with a corner label and a ring when chosen, and is a Tab
stop only with a handler. Lightbox / Gallery Viewer points to
overlays::Lightbox, which the gallery opens from the thumbnails.
T26 splits into T26a–e. AGENTS.md: the drag rule says drags that pan,
turn or slide go through gpui's drag; pictures turn by their pixels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>