T26c Media: video

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>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-09-26 17:07:26 -04:00
1 parent f7f20b5146
commit d0175edb7b
22 files changed
+2232 -25

No files matched your search

+9 -5
View File
@@ -7,10 +7,11 @@ use gpui::{
};
use crate::{
buttons::label_size,
forms::Run,
motion,
primitives::{FocusRing, FocusScope, Icon, IconName, Image, give_back, take_focus},
theme::{ActiveTheme, ControlSize, IconSize, TextSize},
theme::{ActiveTheme, ControlSize, TextSize},
};
/// One picture in a lightbox, and the line under it.
@@ -31,10 +32,11 @@ impl Slide {
type OnStep = Rc<dyn Fn(usize, &mut Window, &mut App)>;
/// A round button drawn for the dark layer: light icon, a faint fill on hover, dim when it has nowhere to go.
fn media_button(
/// A round button drawn for a dark layer over pictures: light icon, a faint fill on hover, dim when it has nowhere to go.
pub(crate) fn media_button(
id: (ElementId, &'static str),
icon: IconName,
size: ControlSize,
enabled: bool,
run: impl Fn(&mut Window, &mut App) + 'static,
cx: &App,
@@ -47,11 +49,11 @@ fn media_button(
.flex_none()
.items_center()
.justify_center()
.size(theme.control_height(ControlSize::Lg))
.size(theme.control_height(size))
.rounded_full()
.border_1()
.border_color(gpui::transparent_black())
.child(Icon::new(icon).size(IconSize::Md).color(if enabled {
.child(Icon::new(icon).size(label_size(size).1).color(if enabled {
light
} else {
light.opacity(0.3)
@@ -147,6 +149,7 @@ impl RenderOnce for Lightbox {
media_button(
(self.id.clone(), name),
icon,
ControlSize::Lg,
to.is_some(),
move |window, cx| {
if let Some(to) = to {
@@ -206,6 +209,7 @@ impl RenderOnce for Lightbox {
.child(div().flex().justify_end().p_3().child(media_button(
(self.id.clone(), "close"),
IconName::X,
ControlSize::Lg,
true,
move |window, cx| button(window, cx),
cx,
+1
View File
@@ -12,6 +12,7 @@ pub use dialog::{Close, Dialog};
pub use dialogs::{AlertDialog, ConfirmDialog, PromptDialog};
pub use floats::{FloatingToolbar, Peek};
pub use hover::HoverCard;
pub(crate) use lightbox::media_button;
pub use lightbox::{Lightbox, Slide};
pub use popover::Popover;
pub use spotlight::{Spotlight, Tour, TourStep};