T24d round 3 fix, after the cap
- BrowserPreview marks the shown frame with accent; the focus color stays the focus ring's - BrowserPreview and ComputerUseViewer take the host's ratio, 16:10 unless set, so frames keep their shape and a pointer's share lands on the picture; test a_screen_takes_its_pictures_shape - TASKS: the review moves to a Claude Fable 5.1 max session after codex ran out of quota; round 3 fixed after the cap, no fourth review - AGENTS: focus and choice colors part; host pictures keep their shape
This commit is contained in:
4 files changed
+77
-9
No files matched your search
@@ -137,6 +137,8 @@ Ely GPUI Component. A component library for GPUI, in light and dark.
|
||||
- A flex line whose free space goes to an auto margin loses its gaps in taffy 0.9. A row that parts left and right groups its sides and uses `justify_between`; `ml_auto` is safe only beside a `flex_1` item that leaves no free space.
|
||||
- A header that holds a name beside counts and actions wraps: `flex_wrap`, the name `flex_1` with `min_w(label_width)`, the rest one `flex_none` group that drops below.
|
||||
- Every header, row and strip works at 280px: a name keeps its minimum width, the rest wraps below or scrolls, and nothing draws past its box.
|
||||
- The focus color belongs to the focus ring. A chosen or shown item takes accent, as `forms::glyphs` and `lists::ListItem` do.
|
||||
- A box that shows a host's picture takes the picture's shape from the host (`ratio`), so nothing is cropped and a point given as a share lands on the picture.
|
||||
|
||||
## Decisions
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Tasks
|
||||
|
||||
Progress truth. Work runs top to bottom. No item is skipped.
|
||||
Each `T` item ends with a codex review (`gpt-6-astra`, effort `max`, herdr split pane). Three rounds at most.
|
||||
Each `T` item ends with a review in a herdr split pane, three rounds at most: codex (`gpt-6-astra`, effort `max`) through T24d round 2; from T24d round 3, after codex ran out of quota on 2026-09-26, a Claude session on Fable 5.1 at max effort, at the user's word.
|
||||
|
||||
Per-component lines live in `tasks/`. Tags there:
|
||||
|
||||
@@ -80,7 +80,7 @@ Per-component lines live in `tasks/`. Tags there:
|
||||
- [x] T24a Agent · Tool calls
|
||||
- [x] T24b Agent · Progress
|
||||
- [x] T24c Agent · Changes
|
||||
- [ ] T24d Agent · Previews
|
||||
- [x] T24d Agent · Previews
|
||||
- [ ] T24e Agent · Environment
|
||||
- [ ] T24f Agent · Control and cost
|
||||
- [ ] T25 Generative
|
||||
@@ -281,3 +281,4 @@ Per-component lines live in `tasks/`. Tags there:
|
||||
| T24c | 2 | PASS | |
|
||||
| T24d | 1 | FAIL | at 280px eight thumbnails ran past the browser card; the artifact panel lost its title and its controls ran out of the box |
|
||||
| T24d | 2 | FAIL | Tab to a later thumbnail left the strip where it was, the focused frame and its ring clipped |
|
||||
| T24d | 3 | FAIL | reviewed by Claude Fable 5.1 max after codex ran out of quota: the shown thumbnail wore the focus color, so focus and choice looked alike; frames were forced to 16:10 and cropped, and a pointer's share missed its target. Fixed after the cap: the shown frame takes accent, and BrowserPreview and ComputerUseViewer take the host's ratio (test a_screen_takes_its_pictures_shape); no fourth review |
|
||||
+28
-7
@@ -16,17 +16,22 @@ use crate::{
|
||||
typography::Ellipsis,
|
||||
};
|
||||
|
||||
/// Width over height of a frame from the host.
|
||||
/// Width over height of a frame from the host, unless it says.
|
||||
const FRAME: f32 = 16.0 / 10.0;
|
||||
|
||||
fn checked(ratio: f32) -> f32 {
|
||||
assert!(ratio.is_finite() && ratio > 0.0, "a frame ratio of {ratio}");
|
||||
ratio
|
||||
}
|
||||
|
||||
/// A box that keeps a frame's shape at the width it is given.
|
||||
fn framed(cx: &App) -> Div {
|
||||
fn framed(ratio: f32, cx: &App) -> Div {
|
||||
let mut frame = div()
|
||||
.relative()
|
||||
.w_full()
|
||||
.overflow_hidden()
|
||||
.bg(cx.theme().colors.sunken);
|
||||
frame.style().aspect_ratio = Some(FRAME);
|
||||
frame.style().aspect_ratio = Some(ratio);
|
||||
frame
|
||||
}
|
||||
|
||||
@@ -82,6 +87,7 @@ pub struct BrowserPreview {
|
||||
url: SharedString,
|
||||
frames: Vec<SharedString>,
|
||||
shown: usize,
|
||||
ratio: f32,
|
||||
loading: bool,
|
||||
on_show: Option<Pick>,
|
||||
}
|
||||
@@ -101,11 +107,18 @@ impl BrowserPreview {
|
||||
url: url.into(),
|
||||
frames,
|
||||
shown,
|
||||
ratio: FRAME,
|
||||
loading: false,
|
||||
on_show: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The frames' width over their height, 16:10 unless set, so the boxes take the pictures' shape.
|
||||
pub fn ratio(mut self, width_over_height: f32) -> Self {
|
||||
self.ratio = checked(width_over_height);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn loading(mut self, loading: bool) -> Self {
|
||||
self.loading = loading;
|
||||
self
|
||||
@@ -174,7 +187,7 @@ impl RenderOnce for BrowserPreview {
|
||||
.rounded(theme.radius(Radius::Sm))
|
||||
.border_1()
|
||||
.border_color(if ix == shown {
|
||||
colors.focus
|
||||
colors.accent
|
||||
} else {
|
||||
colors.border
|
||||
})
|
||||
@@ -183,7 +196,7 @@ impl RenderOnce for BrowserPreview {
|
||||
.rounded(theme.radius(Radius::Sm))
|
||||
.size_full(),
|
||||
);
|
||||
tile.style().aspect_ratio = Some(FRAME);
|
||||
tile.style().aspect_ratio = Some(self.ratio);
|
||||
tile.when_some(show, |tile, show| {
|
||||
tile.track_focus(&handles[ix])
|
||||
.focus_ring(cx)
|
||||
@@ -204,7 +217,7 @@ impl RenderOnce for BrowserPreview {
|
||||
card(cx)
|
||||
.child(address_bar(&self.id, self.url, self.loading, None, cx))
|
||||
.child(
|
||||
framed(cx)
|
||||
framed(self.ratio, cx)
|
||||
.when(strip.is_none(), |frame| {
|
||||
frame.rounded_b(theme.radius(Radius::Lg))
|
||||
})
|
||||
@@ -228,6 +241,7 @@ impl RenderOnce for BrowserPreview {
|
||||
pub struct ComputerUseViewer {
|
||||
id: ElementId,
|
||||
frame: SharedString,
|
||||
ratio: f32,
|
||||
pointer: Option<Point<f32>>,
|
||||
action: Option<SharedString>,
|
||||
}
|
||||
@@ -238,11 +252,18 @@ impl ComputerUseViewer {
|
||||
Self {
|
||||
id: id.into(),
|
||||
frame: frame.into(),
|
||||
ratio: FRAME,
|
||||
pointer: None,
|
||||
action: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The frame's width over its height, 16:10 unless set, so the box takes the picture's shape.
|
||||
pub fn ratio(mut self, width_over_height: f32) -> Self {
|
||||
self.ratio = checked(width_over_height);
|
||||
self
|
||||
}
|
||||
|
||||
/// Where the agent points, each side a share of the frame from its top left.
|
||||
pub fn pointer(mut self, at: Point<f32>) -> Self {
|
||||
assert!(
|
||||
@@ -302,7 +323,7 @@ impl RenderOnce for ComputerUseViewer {
|
||||
});
|
||||
card(cx)
|
||||
.child(
|
||||
framed(cx)
|
||||
framed(self.ratio, cx)
|
||||
.rounded_t(theme.radius(Radius::Lg))
|
||||
.when(self.action.is_none(), |frame| {
|
||||
frame.rounded_b(theme.radius(Radius::Lg))
|
||||
|
||||
@@ -244,3 +244,47 @@ fn tab_brings_a_hidden_frame_into_view(cx: &mut TestAppContext) {
|
||||
"the eighth frame sits in view"
|
||||
);
|
||||
}
|
||||
|
||||
/// A 4:3 screen in a 480px column, and its height as drawn.
|
||||
struct Screen {
|
||||
height: Rc<Cell<Pixels>>,
|
||||
}
|
||||
|
||||
impl Render for Screen {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
let height = self.height.clone();
|
||||
div()
|
||||
.relative()
|
||||
.w(px(480.0))
|
||||
.child(
|
||||
ComputerUseViewer::new("screen", "a.png")
|
||||
.ratio(4.0 / 3.0)
|
||||
.pointer(point(0.5, 0.95)),
|
||||
)
|
||||
.child(
|
||||
canvas(
|
||||
move |bounds, _, _| height.set(bounds.size.height),
|
||||
|_, _, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.top_0()
|
||||
.left_0()
|
||||
.size_full(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_screen_takes_its_pictures_shape(cx: &mut TestAppContext) {
|
||||
setup(cx);
|
||||
let height = Rc::new(Cell::new(Pixels::ZERO));
|
||||
let seen = height.clone();
|
||||
let (_, cx) = cx.add_window_view(|_, _| Screen { height: seen });
|
||||
settle(cx);
|
||||
let expected = px(478.0 * 3.0 / 4.0 + 2.0);
|
||||
assert!(
|
||||
(height.get() - expected).abs() < px(1.0),
|
||||
"478px inside the border at 4:3, plus the border: {:?} vs {expected:?}",
|
||||
height.get()
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user