From 047e7eacec0987a06d395d6698e3f0d9fef4e6b6 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 30 May 2025 23:26:27 +0800 Subject: [PATCH] gpui: Improve `window.prompt` to support ESC with non-English cancel text on macOS (#29538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release Notes: - N/A ---- The before version GPUI used `Cancel` for cancel text, if we use non-English text (e.g.: "取消" in Chinese), then the press `Esc` to cancel will not work. So this PR to change it by use `PromptButton` to instead the `&str`, then we can use `PromptButton::cancel("取消")` for the `Cancel` button. Run `cargo run -p gpui --example window` to test. --- Platform Test: - [x] macOS - [x] Windows - [x] Linux (x11 and Wayland) --------- Co-authored-by: Mikayla Maki Co-authored-by: Mikayla Maki --- crates/gpui/examples/window.rs | 41 +++++++++++++- crates/gpui/src/app.rs | 12 ++--- crates/gpui/src/app/async_context.rs | 13 +++-- crates/gpui/src/platform.rs | 54 ++++++++++++++++++- .../gpui/src/platform/linux/wayland/window.rs | 6 +-- crates/gpui/src/platform/linux/x11/window.rs | 8 +-- crates/gpui/src/platform/mac/events.rs | 2 +- crates/gpui/src/platform/mac/window.rs | 20 ++++--- crates/gpui/src/platform/test/platform.rs | 8 +-- crates/gpui/src/platform/test/window.rs | 6 +-- crates/gpui/src/platform/windows/window.rs | 10 ++-- crates/gpui/src/window.rs | 36 ++++++++----- crates/gpui/src/window/prompts.rs | 14 ++--- crates/ui_prompt/src/ui_prompt.rs | 10 ++-- 14 files changed, 174 insertions(+), 66 deletions(-) diff --git a/crates/gpui/examples/window.rs b/crates/gpui/examples/window.rs index abd6e815ea73936735e652359256414bdb573d10..30f3697b223d6d85a9db573eb3659e9689af60a5 100644 --- a/crates/gpui/examples/window.rs +++ b/crates/gpui/examples/window.rs @@ -1,6 +1,6 @@ use gpui::{ - App, Application, Bounds, Context, KeyBinding, SharedString, Timer, Window, WindowBounds, - WindowKind, WindowOptions, actions, div, prelude::*, px, rgb, size, + App, Application, Bounds, Context, KeyBinding, PromptButton, PromptLevel, SharedString, Timer, + Window, WindowBounds, WindowKind, WindowOptions, actions, div, prelude::*, px, rgb, size, }; struct SubWindow { @@ -169,6 +169,42 @@ impl Render for WindowDemo { let content_size = window.bounds().size; window.resize(size(content_size.height, content_size.width)); })) + .child(button("Prompt", |window, cx| { + let answer = window.prompt( + PromptLevel::Info, + "Are you sure?", + None, + &["Ok", "Cancel"], + cx, + ); + + cx.spawn(async move |_| { + if answer.await.unwrap() == 0 { + println!("You have clicked Ok"); + } else { + println!("You have clicked Cancel"); + } + }) + .detach(); + })) + .child(button("Prompt (non-English)", |window, cx| { + let answer = window.prompt( + PromptLevel::Info, + "Are you sure?", + None, + &[PromptButton::ok("确定"), PromptButton::cancel("取消")], + cx, + ); + + cx.spawn(async move |_| { + if answer.await.unwrap() == 0 { + println!("You have clicked Ok"); + } else { + println!("You have clicked Cancel"); + } + }) + .detach(); + })) } } @@ -195,6 +231,7 @@ fn main() { }, ) .unwrap(); + cx.activate(true); cx.on_action(|_: &Quit, cx| cx.quit()); cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]); diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 780c7dc4144ad10832b89b573cc3941cd326a799..dc9fa0ced34c14c60bedf38e533e603fc97c07d2 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -37,10 +37,10 @@ use crate::{ AssetSource, BackgroundExecutor, Bounds, ClipboardItem, CursorStyle, DispatchPhase, DisplayId, EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, KeyContext, Keymap, Keystroke, LayoutId, Menu, MenuItem, OwnedMenu, PathPromptOptions, Pixels, Platform, - PlatformDisplay, PlatformKeyboardLayout, Point, PromptBuilder, PromptHandle, PromptLevel, - Render, RenderImage, RenderablePromptHandle, Reservation, ScreenCaptureSource, SharedString, - SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, Window, WindowAppearance, - WindowHandle, WindowId, WindowInvalidator, + PlatformDisplay, PlatformKeyboardLayout, Point, PromptBuilder, PromptButton, PromptHandle, + PromptLevel, Render, RenderImage, RenderablePromptHandle, Reservation, ScreenCaptureSource, + SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextSystem, Window, + WindowAppearance, WindowHandle, WindowId, WindowInvalidator, colors::{Colors, GlobalColors}, current_platform, hash, init_app_menus, }; @@ -1578,14 +1578,14 @@ impl App { PromptLevel, &str, Option<&str>, - &[&str], + &[PromptButton], PromptHandle, &mut Window, &mut App, ) -> RenderablePromptHandle + 'static, ) { - self.prompt_builder = Some(PromptBuilder::Custom(Box::new(renderer))) + self.prompt_builder = Some(PromptBuilder::Custom(Box::new(renderer))); } /// Reset the prompt builder to the default implementation. diff --git a/crates/gpui/src/app/async_context.rs b/crates/gpui/src/app/async_context.rs index 657bf095e1d07eb42427bf8ba32a84c7aeba4bd0..c3b60dd580483771f683b6d76fd76e52b3f531ad 100644 --- a/crates/gpui/src/app/async_context.rs +++ b/crates/gpui/src/app/async_context.rs @@ -1,7 +1,7 @@ use crate::{ AnyView, AnyWindowHandle, App, AppCell, AppContext, BackgroundExecutor, BorrowAppContext, - Entity, EventEmitter, Focusable, ForegroundExecutor, Global, PromptLevel, Render, Reservation, - Result, Subscription, Task, VisualContext, Window, WindowHandle, + Entity, EventEmitter, Focusable, ForegroundExecutor, Global, PromptButton, PromptLevel, Render, + Reservation, Result, Subscription, Task, VisualContext, Window, WindowHandle, }; use anyhow::Context as _; use derive_more::{Deref, DerefMut}; @@ -314,13 +314,16 @@ impl AsyncWindowContext { /// Present a platform dialog. /// The provided message will be presented, along with buttons for each answer. /// When a button is clicked, the returned Receiver will receive the index of the clicked button. - pub fn prompt( + pub fn prompt( &mut self, level: PromptLevel, message: &str, detail: Option<&str>, - answers: &[&str], - ) -> oneshot::Receiver { + answers: &[T], + ) -> oneshot::Receiver + where + T: Clone + Into, + { self.window .update(self, |_, window, cx| { window.prompt(level, message, detail, answers, cx) diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index e7390fd562062477b1e67163c21fb8f338e1d8f2..f84a590db07b43fcbaadc437afc14d344358283a 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -418,7 +418,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { level: PromptLevel, msg: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], ) -> Option>; fn activate(&self); fn is_active(&self) -> bool; @@ -1244,6 +1244,58 @@ pub enum PromptLevel { Critical, } +/// Prompt Button +#[derive(Clone, Debug, PartialEq)] +pub enum PromptButton { + /// Ok button + Ok(SharedString), + /// Cancel button + Cancel(SharedString), + /// Other button + Other(SharedString), +} + +impl PromptButton { + /// Create a button with label + pub fn new(label: impl Into) -> Self { + PromptButton::Other(label.into()) + } + + /// Create an Ok button + pub fn ok(label: impl Into) -> Self { + PromptButton::Ok(label.into()) + } + + /// Create a Cancel button + pub fn cancel(label: impl Into) -> Self { + PromptButton::Cancel(label.into()) + } + + #[allow(dead_code)] + pub(crate) fn is_cancel(&self) -> bool { + matches!(self, PromptButton::Cancel(_)) + } + + /// Returns the label of the button + pub fn label(&self) -> &SharedString { + match self { + PromptButton::Ok(label) => label, + PromptButton::Cancel(label) => label, + PromptButton::Other(label) => label, + } + } +} + +impl From<&str> for PromptButton { + fn from(value: &str) -> Self { + match value.to_lowercase().as_str() { + "ok" => PromptButton::Ok("Ok".into()), + "cancel" => PromptButton::Cancel("Cancel".into()), + _ => PromptButton::Other(SharedString::from(value.to_owned())), + } + } +} + /// The style of the cursor (pointer) #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] pub enum CursorStyle { diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index 4178bea4a35c4c128cb3bb021cf7acc1d3929eec..82f3d931ab3dad0e4be49e1a2d60ebccf37c9166 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -29,8 +29,8 @@ use crate::platform::{ use crate::scene::Scene; use crate::{ AnyWindowHandle, Bounds, Decorations, Globals, GpuSpecs, Modifiers, Output, Pixels, - PlatformDisplay, PlatformInput, Point, PromptLevel, RequestFrameOptions, ResizeEdge, - ScaledPixels, Size, Tiling, WaylandClientStatePtr, WindowAppearance, + PlatformDisplay, PlatformInput, Point, PromptButton, PromptLevel, RequestFrameOptions, + ResizeEdge, ScaledPixels, Size, Tiling, WaylandClientStatePtr, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, WindowParams, px, size, }; @@ -862,7 +862,7 @@ impl PlatformWindow for WaylandWindow { _level: PromptLevel, _msg: &str, _detail: Option<&str>, - _answers: &[&str], + _answers: &[PromptButton], ) -> Option> { None } diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 7a4cd1c35a8698e5036fcd29fba919e6d78233bc..7a9949c6e42b684611d0cd5cab4def07d9f82489 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -4,9 +4,9 @@ use crate::platform::blade::{BladeContext, BladeRenderer, BladeSurfaceConfig}; use crate::{ AnyWindowHandle, Bounds, Decorations, DevicePixels, ForegroundExecutor, GpuSpecs, Modifiers, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, - Point, PromptLevel, RequestFrameOptions, ResizeEdge, ScaledPixels, Scene, Size, Tiling, - WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowDecorations, WindowKind, - WindowParams, X11ClientStatePtr, px, size, + Point, PromptButton, PromptLevel, RequestFrameOptions, ResizeEdge, ScaledPixels, Scene, Size, + Tiling, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowDecorations, + WindowKind, WindowParams, X11ClientStatePtr, px, size, }; use blade_graphics as gpu; @@ -1227,7 +1227,7 @@ impl PlatformWindow for X11Window { _level: PromptLevel, _msg: &str, _detail: Option<&str>, - _answers: &[&str], + _answers: &[PromptButton], ) -> Option> { None } diff --git a/crates/gpui/src/platform/mac/events.rs b/crates/gpui/src/platform/mac/events.rs index 58f5d9bc1c29a4ca955cd3b7d0b8f953053eb0ba..b90e8f10dc29a479827e40bf5eb638770130478a 100644 --- a/crates/gpui/src/platform/mac/events.rs +++ b/crates/gpui/src/platform/mac/events.rs @@ -21,7 +21,7 @@ const BACKSPACE_KEY: u16 = 0x7f; const SPACE_KEY: u16 = b' ' as u16; const ENTER_KEY: u16 = 0x0d; const NUMPAD_ENTER_KEY: u16 = 0x03; -const ESCAPE_KEY: u16 = 0x1b; +pub(crate) const ESCAPE_KEY: u16 = 0x1b; const TAB_KEY: u16 = 0x09; const SHIFT_TAB_KEY: u16 = 0x19; diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index c49219bff18dfbdf56b05a37b6cedf7d94ad88a6..dd5ec4eb3100d4389df7c9f286244dae88d16195 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -3,8 +3,8 @@ use crate::{ AnyWindowHandle, Bounds, DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, - PlatformWindow, Point, PromptLevel, RequestFrameOptions, ScaledPixels, Size, Timer, - WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowKind, WindowParams, + PlatformWindow, Point, PromptButton, PromptLevel, RequestFrameOptions, ScaledPixels, Size, + Timer, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowKind, WindowParams, platform::PlatformInputHandler, point, px, size, }; use block::ConcreteBlock; @@ -902,7 +902,7 @@ impl PlatformWindow for MacWindow { level: PromptLevel, msg: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], ) -> Option> { // macOs applies overrides to modal window buttons after they are added. // Two most important for this logic are: @@ -926,7 +926,7 @@ impl PlatformWindow for MacWindow { .iter() .enumerate() .rev() - .find(|(_, label)| **label != "Cancel") + .find(|(_, label)| !label.is_cancel()) .filter(|&(label_index, _)| label_index > 0); unsafe { @@ -948,11 +948,19 @@ impl PlatformWindow for MacWindow { .enumerate() .filter(|&(ix, _)| Some(ix) != latest_non_cancel_label.map(|(ix, _)| ix)) { - let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer)]; + let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer.label())]; let _: () = msg_send![button, setTag: ix as NSInteger]; + + if answer.is_cancel() { + // Bind Escape Key to Cancel Button + if let Some(key) = std::char::from_u32(super::events::ESCAPE_KEY as u32) { + let _: () = + msg_send![button, setKeyEquivalent: ns_string(&key.to_string())]; + } + } } if let Some((ix, answer)) = latest_non_cancel_label { - let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer)]; + let button: id = msg_send![alert, addButtonWithTitle: ns_string(answer.label())]; let _: () = msg_send![button, setTag: ix as NSInteger]; } diff --git a/crates/gpui/src/platform/test/platform.rs b/crates/gpui/src/platform/test/platform.rs index bc3c2b89a8d84584adc3a1339406d895822b3836..eb3b6e94611a41ff3fb3f81d94b90fb39a481fa7 100644 --- a/crates/gpui/src/platform/test/platform.rs +++ b/crates/gpui/src/platform/test/platform.rs @@ -1,8 +1,8 @@ use crate::{ AnyWindowHandle, BackgroundExecutor, ClipboardItem, CursorStyle, DevicePixels, ForegroundExecutor, Keymap, NoopTextSystem, Platform, PlatformDisplay, PlatformKeyboardLayout, - PlatformTextSystem, ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream, Size, Task, - TestDisplay, TestWindow, WindowAppearance, WindowParams, size, + PlatformTextSystem, PromptButton, ScreenCaptureFrame, ScreenCaptureSource, ScreenCaptureStream, + Size, Task, TestDisplay, TestWindow, WindowAppearance, WindowParams, size, }; use anyhow::Result; use collections::VecDeque; @@ -165,10 +165,10 @@ impl TestPlatform { &self, msg: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], ) -> oneshot::Receiver { let (tx, rx) = oneshot::channel(); - let answers: Vec = answers.iter().map(|&s| s.to_string()).collect(); + let answers: Vec = answers.iter().map(|s| s.label().to_string()).collect(); self.background_executor() .set_waiting_hint(Some(format!("PROMPT: {:?} {:?}", msg, detail))); self.prompts diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 42ea7d8af467976cceca14510506ae463963de38..3dd75ed7bc6d5e93001b189f0a941f5173752608 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -1,8 +1,8 @@ use crate::{ AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, DispatchEventResult, GpuSpecs, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, - Point, RequestFrameOptions, ScaledPixels, Size, TestPlatform, TileId, WindowAppearance, - WindowBackgroundAppearance, WindowBounds, WindowParams, + Point, PromptButton, RequestFrameOptions, ScaledPixels, Size, TestPlatform, TileId, + WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowParams, }; use collections::HashMap; use parking_lot::Mutex; @@ -164,7 +164,7 @@ impl PlatformWindow for TestWindow { _level: crate::PromptLevel, msg: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], ) -> Option> { Some( self.0 diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index ccca2b664adef5e24b1e4ff52e06b5a824a10001..671cf72c96658265801af7067b02cdfd2b87aef6 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -608,7 +608,7 @@ impl PlatformWindow for WindowsWindow { level: PromptLevel, msg: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], ) -> Option> { let (done_tx, done_rx) = oneshot::channel(); let msg = msg.to_string(); @@ -616,8 +616,8 @@ impl PlatformWindow for WindowsWindow { Some(info) => Some(info.to_string()), None => None, }; - let answers = answers.iter().map(|s| s.to_string()).collect::>(); let handle = self.0.hwnd; + let answers = answers.to_vec(); self.0 .executor .spawn(async move { @@ -653,9 +653,9 @@ impl PlatformWindow for WindowsWindow { let mut button_id_map = Vec::with_capacity(answers.len()); let mut buttons = Vec::new(); let mut btn_encoded = Vec::new(); - for (index, btn_string) in answers.iter().enumerate() { - let encoded = HSTRING::from(btn_string); - let button_id = if btn_string == "Cancel" { + for (index, btn) in answers.iter().enumerate() { + let encoded = HSTRING::from(btn.label().as_ref()); + let button_id = if btn.is_cancel() { IDCANCEL.0 } else { index as i32 - 100 diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index b992b2139fab3d467eaa56e8bb61591d62a086f2..8636268a7abb88626cb811d5ecf1a5311738ea9e 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -9,13 +9,13 @@ use crate::{ KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, - PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, - RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR, - SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, - SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, - TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance, - WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem, - point, prelude::*, px, rems, size, transparent_black, + PlatformWindow, Point, PolychromeSprite, PromptButton, PromptLevel, Quad, Render, + RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, + SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS, ScaledPixels, Scene, Shadow, SharedString, Size, + StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, + TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, + WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, WindowOptions, + WindowParams, WindowTextSystem, point, prelude::*, px, rems, size, transparent_black, }; use anyhow::{Context as _, Result, anyhow}; use collections::{FxHashMap, FxHashSet}; @@ -3821,28 +3821,36 @@ impl Window { /// Present a platform dialog. /// The provided message will be presented, along with buttons for each answer. /// When a button is clicked, the returned Receiver will receive the index of the clicked button. - pub fn prompt( + pub fn prompt( &mut self, level: PromptLevel, message: &str, detail: Option<&str>, - answers: &[&str], + answers: &[T], cx: &mut App, - ) -> oneshot::Receiver { + ) -> oneshot::Receiver + where + T: Clone + Into, + { let prompt_builder = cx.prompt_builder.take(); let Some(prompt_builder) = prompt_builder else { unreachable!("Re-entrant window prompting is not supported by GPUI"); }; + let answers = answers + .iter() + .map(|answer| answer.clone().into()) + .collect::>(); + let receiver = match &prompt_builder { PromptBuilder::Default => self .platform_window - .prompt(level, message, detail, answers) + .prompt(level, message, detail, &answers) .unwrap_or_else(|| { - self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx) + self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx) }), PromptBuilder::Custom(_) => { - self.build_custom_prompt(&prompt_builder, level, message, detail, answers, cx) + self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx) } }; @@ -3857,7 +3865,7 @@ impl Window { level: PromptLevel, message: &str, detail: Option<&str>, - answers: &[&str], + answers: &[PromptButton], cx: &mut App, ) -> oneshot::Receiver { let (sender, receiver) = oneshot::channel(); diff --git a/crates/gpui/src/window/prompts.rs b/crates/gpui/src/window/prompts.rs index f3307b3861a15382e8f35af1bc0fae5ba269bb23..778ee1dab0eb8312161dcbca0ddf8964afe0c6bb 100644 --- a/crates/gpui/src/window/prompts.rs +++ b/crates/gpui/src/window/prompts.rs @@ -4,7 +4,7 @@ use futures::channel::oneshot; use crate::{ AnyView, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable, - InteractiveElement, IntoElement, ParentElement, PromptLevel, Render, + InteractiveElement, IntoElement, ParentElement, PromptButton, PromptLevel, Render, StatefulInteractiveElement, Styled, div, opaque_grey, white, }; @@ -74,7 +74,7 @@ pub fn fallback_prompt_renderer( level: PromptLevel, message: &str, detail: Option<&str>, - actions: &[&str], + actions: &[PromptButton], handle: PromptHandle, window: &mut Window, cx: &mut App, @@ -83,7 +83,7 @@ pub fn fallback_prompt_renderer( _level: level, message: message.to_string(), detail: detail.map(ToString::to_string), - actions: actions.iter().map(ToString::to_string).collect(), + actions: actions.to_vec(), focus: cx.focus_handle(), }); @@ -95,7 +95,7 @@ pub struct FallbackPromptRenderer { _level: PromptLevel, message: String, detail: Option, - actions: Vec, + actions: Vec, focus: FocusHandle, } @@ -138,7 +138,7 @@ impl Render for FallbackPromptRenderer { .rounded_xs() .cursor_pointer() .text_sm() - .child(action.clone()) + .child(action.label().clone()) .id(ix) .on_click(cx.listener(move |_, _, _, cx| { cx.emit(PromptResponse(ix)); @@ -202,7 +202,7 @@ pub(crate) enum PromptBuilder { PromptLevel, &str, Option<&str>, - &[&str], + &[PromptButton], PromptHandle, &mut Window, &mut App, @@ -216,7 +216,7 @@ impl Deref for PromptBuilder { PromptLevel, &str, Option<&str>, - &[&str], + &[PromptButton], PromptHandle, &mut Window, &mut App, diff --git a/crates/ui_prompt/src/ui_prompt.rs b/crates/ui_prompt/src/ui_prompt.rs index dfec2221b34b8e24d72c2abaaeb5361fac0011e8..dc6aee177d72dc5898f6dcc43895d02aa02f7714 100644 --- a/crates/ui_prompt/src/ui_prompt.rs +++ b/crates/ui_prompt/src/ui_prompt.rs @@ -1,8 +1,8 @@ use gpui::{ App, AppContext as _, Context, Entity, EventEmitter, FocusHandle, Focusable, FontWeight, - InteractiveElement, IntoElement, ParentElement, PromptHandle, PromptLevel, PromptResponse, - Refineable, Render, RenderablePromptHandle, SharedString, Styled, TextStyleRefinement, Window, - div, + InteractiveElement, IntoElement, ParentElement, PromptButton, PromptHandle, PromptLevel, + PromptResponse, Refineable, Render, RenderablePromptHandle, SharedString, Styled, + TextStyleRefinement, Window, div, }; use markdown::{Markdown, MarkdownElement, MarkdownStyle}; use settings::{Settings, SettingsStore}; @@ -35,7 +35,7 @@ fn zed_prompt_renderer( level: PromptLevel, message: &str, detail: Option<&str>, - actions: &[&str], + actions: &[PromptButton], handle: PromptHandle, window: &mut Window, cx: &mut App, @@ -44,7 +44,7 @@ fn zed_prompt_renderer( |cx| ZedPromptRenderer { _level: level, message: message.to_string(), - actions: actions.iter().map(ToString::to_string).collect(), + actions: actions.iter().map(|a| a.label().to_string()).collect(), focus: cx.focus_handle(), active_action_id: 0, detail: detail