diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index a2cc5e9..c471906 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -126,7 +126,20 @@ fn main() { })), // Transparent native titlebar: keeps the OS window controls (traffic lights) working // while we render our own brand/workspace bar in-window. See `render_titlebar`. - titlebar: Some(gpui_component::TitleBar::title_bar_options()), + // The title is only chrome on macOS (we draw our own), but on Linux/Windows the WM + // reads it for the taskbar and alt-tab — unset, it renders as "Unnamed Window". + titlebar: Some(TitlebarOptions { + title: Some("Posel".into()), + ..gpui_component::TitleBar::title_bar_options() + }), + // Linux WMs match this to the .desktop entry for the icon and window grouping. + app_id: Some("com.starvy.posel".into()), + // The side-by-side editor/response layout needs about this much width before the + // response footer (status + metrics + Pretty/Raw/Wrap + icons) and the two tab + // strips stop fitting; verified clean at 1000x640 and cramped below it. The footer + // also clips rather than overlaps now, which covers the same squeeze arriving via + // ⌘+ font scaling at any window size. + window_min_size: Some(size(px(1000.), px(640.))), ..Default::default() }; cx.open_window(options, |window, cx| { diff --git a/crates/ui/src/response.rs b/crates/ui/src/response.rs index 3d16c22..6c07892 100644 --- a/crates/ui/src/response.rs +++ b/crates/ui/src/response.rs @@ -271,11 +271,17 @@ impl RequestView { .border_color(cx.theme().border) }) .child( + // `min_w_0` lets this group shrink, but shrinking alone doesn't stop its text from + // painting outside the box — without `overflow_hidden` the metrics overprint the + // tools group on a narrow window instead of being clipped by it. h_flex() .min_w_0() + .overflow_hidden() .items_center() .gap(tokens::GAP_11) - .child(token) + // The status itself is the one thing worth keeping at any width, so it never + // shrinks; latency and size are what get clipped away first. + .child(div().flex_shrink_0().child(token)) .children(done_metrics), ) .child( @@ -357,7 +363,9 @@ impl RequestView { fn render_timing(&self, cx: &mut Context) -> AnyElement { let tab = self.active_tab(); if matches!(tab.state, RunState::Idle) { - return self.response_placeholder("Send the request (⌘↵) to see timing.", cx); + let hint = crate::command::keybinding_hint("⌘↵"); + return self + .response_placeholder(&format!("Send the request ({hint}) to see timing."), cx); } let in_flight = matches!(tab.state, RunState::Streaming); let total = if in_flight { @@ -689,7 +697,9 @@ impl RequestView { .text_size(tokens::ui_label(cx)) .text_color(p.ghost) .child("Press") - .child(Kbd::new("⌘↵")) + // Authored in macOS glyphs and rewritten per platform — a Linux/Windows build + // must not tell the user to press ⌘. + .child(Kbd::new(crate::command::keybinding_hint("⌘↵"))) .child("to send"), ) .into_any_element() diff --git a/crates/ui/src/sidebar.rs b/crates/ui/src/sidebar.rs index c557b00..72aad71 100644 --- a/crates/ui/src/sidebar.rs +++ b/crates/ui/src/sidebar.rs @@ -236,10 +236,12 @@ impl RequestView { /// The no-workspace state: the open hint plus a clickable list of recent workspaces. fn render_welcome(&self, cx: &mut Context) -> Vec { + // Authored in macOS glyphs and rewritten per platform (⌘O → Ctrl+O off-mac). + let open_hint = format!("Open one with {}", crate::command::keybinding_hint("⌘O")); let mut out = vec![crate::widgets::empty_state( IconName::FolderOpen, "No workspace open", - "Open one with ⌘O", + &open_hint, cx, ) .into_any_element()]; diff --git a/docs/assets/posel-demo.gif b/docs/assets/posel-demo.gif index 21bf48d..2522e47 100644 Binary files a/docs/assets/posel-demo.gif and b/docs/assets/posel-demo.gif differ diff --git a/docs/assets/posel-demo.mp4 b/docs/assets/posel-demo.mp4 index 45ce888..c779e9b 100644 Binary files a/docs/assets/posel-demo.mp4 and b/docs/assets/posel-demo.mp4 differ