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.
This commit is contained in:
1 parent
99b6ccd798
commit
d125314d39
22 files changed
+2232
-25
No files matched your search
@@ -1,11 +1,12 @@
|
||||
use gpui::{
|
||||
Context, IntoElement, Modifiers, MouseButton, Render, TestAppContext, Window, point, px,
|
||||
Context, IntoElement, KeyBinding, KeyUpEvent, Keystroke, Modifiers, MouseButton, Render,
|
||||
SharedString, TestAppContext, VisualTestContext, Window, point, px,
|
||||
};
|
||||
|
||||
use super::setup;
|
||||
use crate::{
|
||||
forms::{IconPicker, SignaturePad, Stroke},
|
||||
primitives::IconName,
|
||||
forms::{IconPicker, InlineEdit, SignaturePad, Stroke},
|
||||
primitives::{FocusNext, IconName},
|
||||
};
|
||||
|
||||
struct Icons {
|
||||
@@ -92,3 +93,54 @@ fn one_move_keeps_both_ends_of_the_stroke(cx: &mut TestAppContext) {
|
||||
assert_eq!(stroke.len(), 2, "{stroke:?}");
|
||||
assert_eq!(stroke[1] - stroke[0], point(px(60.0), px(-20.0)));
|
||||
}
|
||||
|
||||
/// An inline edit and the texts it kept.
|
||||
struct Titled(Vec<SharedString>);
|
||||
|
||||
impl Render for Titled {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let view = cx.entity();
|
||||
let value = self.0.last().cloned().unwrap_or_else(|| "Draft".into());
|
||||
InlineEdit::new("title", value).on_commit(move |text, _, cx| {
|
||||
view.update(cx, |view, cx| {
|
||||
view.0.push(text.clone());
|
||||
cx.notify();
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Presses and releases `key`, a drawn frame between.
|
||||
fn release(key: &str, cx: &mut VisualTestContext) {
|
||||
let redraw = |cx: &mut VisualTestContext| {
|
||||
cx.run_until_parked();
|
||||
cx.update(|window, _| window.refresh());
|
||||
cx.run_until_parked();
|
||||
};
|
||||
cx.simulate_keystrokes(key);
|
||||
redraw(cx);
|
||||
cx.simulate_event(KeyUpEvent {
|
||||
keystroke: Keystroke::parse(key).expect("a key"),
|
||||
});
|
||||
redraw(cx);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn an_inline_edit_takes_tab_opens_on_enter_and_takes_focus_back(cx: &mut TestAppContext) {
|
||||
setup(cx);
|
||||
cx.update(|cx| cx.bind_keys([KeyBinding::new("tab", FocusNext, None)]));
|
||||
let (view, cx) = cx.add_window_view(|_, _| Titled(Vec::new()));
|
||||
cx.update(|window, _| window.activate_window());
|
||||
cx.update(|window, _| window.focus_next());
|
||||
release("enter", cx);
|
||||
cx.simulate_input("Stairs");
|
||||
release("enter", cx);
|
||||
release("enter", cx);
|
||||
cx.simulate_input("Light");
|
||||
release("enter", cx);
|
||||
assert_eq!(
|
||||
view.read_with(cx, |view, _| view.0.clone()),
|
||||
["Stairs", "Light"],
|
||||
"focus came back after the first"
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user