gpui: Add support for custom prompt text in PathPromptOptions (#36410)

Anthony Eid created

This will be used to improve the clarity of the git clone UI

### MacOS
<img width="1322" height="128" alt="image"
src="https://github.com/user-attachments/assets/3e511143-12c1-4440-89dd-841b21b2e98e"
/>

### Windows 
<img width="338" height="80" alt="image"
src="https://github.com/user-attachments/assets/766d08d6-0c72-4175-ad24-59dc6188d5f1"
/>

### Linux

<img width="387" height="72" alt="Screenshot From 2025-08-18 15-32-06"
src="https://github.com/user-attachments/assets/3125a7c4-3975-462a-a547-d5d4fac48f22"
/>



Release Notes:

- N/A

Change summary

crates/extensions_ui/src/extensions_ui.rs    | 1 +
crates/git_ui/src/git_panel.rs               | 1 +
crates/gpui/src/platform.rs                  | 4 +++-
crates/gpui/src/platform/linux/platform.rs   | 1 +
crates/gpui/src/platform/mac/platform.rs     | 6 ++++++
crates/gpui/src/platform/windows/platform.rs | 6 ++++++
crates/gpui/src/shared_string.rs             | 5 +++++
crates/workspace/src/workspace.rs            | 3 +++
crates/zed/src/zed.rs                        | 2 ++
9 files changed, 28 insertions(+), 1 deletion(-)

Detailed changes

crates/git_ui/src/git_panel.rs 🔗

@@ -2088,6 +2088,7 @@ impl GitPanel {
             files: false,
             directories: true,
             multiple: false,
+            prompt: Some("Select as Repository Destination".into()),
         });
 
         let workspace = self.workspace.clone();

crates/gpui/src/platform.rs 🔗

@@ -1278,7 +1278,7 @@ pub enum WindowBackgroundAppearance {
 }
 
 /// The options that can be configured for a file dialog prompt
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
 pub struct PathPromptOptions {
     /// Should the prompt allow files to be selected?
     pub files: bool,
@@ -1286,6 +1286,8 @@ pub struct PathPromptOptions {
     pub directories: bool,
     /// Should the prompt allow multiple files to be selected?
     pub multiple: bool,
+    /// The prompt to show to a user when selecting a path
+    pub prompt: Option<SharedString>,
 }
 
 /// What kind of prompt styling to show

crates/gpui/src/platform/linux/platform.rs 🔗

@@ -294,6 +294,7 @@ impl<P: LinuxClient + 'static> Platform for P {
                 let request = match ashpd::desktop::file_chooser::OpenFileRequest::default()
                     .modal(true)
                     .title(title)
+                    .accept_label(options.prompt.as_ref().map(crate::SharedString::as_str))
                     .multiple(options.multiple)
                     .directory(options.directories)
                     .send()

crates/gpui/src/platform/mac/platform.rs 🔗

@@ -705,6 +705,7 @@ impl Platform for MacPlatform {
                     panel.setCanChooseDirectories_(options.directories.to_objc());
                     panel.setCanChooseFiles_(options.files.to_objc());
                     panel.setAllowsMultipleSelection_(options.multiple.to_objc());
+
                     panel.setCanCreateDirectories(true.to_objc());
                     panel.setResolvesAliases_(false.to_objc());
                     let done_tx = Cell::new(Some(done_tx));
@@ -730,6 +731,11 @@ impl Platform for MacPlatform {
                         }
                     });
                     let block = block.copy();
+
+                    if let Some(prompt) = options.prompt {
+                        let _: () = msg_send![panel, setPrompt: ns_string(&prompt)];
+                    }
+
                     let _: () = msg_send![panel, beginWithCompletionHandler: block];
                 }
             })

crates/gpui/src/platform/windows/platform.rs 🔗

@@ -787,6 +787,12 @@ fn file_open_dialog(
 
     unsafe {
         folder_dialog.SetOptions(dialog_options)?;
+
+        if let Some(prompt) = options.prompt {
+            let prompt: &str = &prompt;
+            folder_dialog.SetOkButtonLabel(&HSTRING::from(prompt))?;
+        }
+
         if folder_dialog.Show(window).is_err() {
             // User cancelled
             return Ok(None);

crates/gpui/src/shared_string.rs 🔗

@@ -23,6 +23,11 @@ impl SharedString {
     pub fn new(str: impl Into<Arc<str>>) -> Self {
         SharedString(ArcCow::Owned(str.into()))
     }
+
+    /// Get a &str from the underlying string.
+    pub fn as_str(&self) -> &str {
+        &self.0
+    }
 }
 
 impl JsonSchema for SharedString {

crates/workspace/src/workspace.rs 🔗

@@ -561,6 +561,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut App) {
                         files: true,
                         directories: true,
                         multiple: true,
+                        prompt: None,
                     },
                     cx,
                 );
@@ -578,6 +579,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut App) {
                         files: true,
                         directories,
                         multiple: true,
+                        prompt: None,
                     },
                     cx,
                 );
@@ -2655,6 +2657,7 @@ impl Workspace {
                 files: false,
                 directories: true,
                 multiple: true,
+                prompt: None,
             },
             DirectoryLister::Project(self.project.clone()),
             window,

crates/zed/src/zed.rs 🔗

@@ -645,6 +645,7 @@ fn register_actions(
                     files: true,
                     directories: true,
                     multiple: true,
+                    prompt: None,
                 },
                 DirectoryLister::Local(
                     workspace.project().clone(),
@@ -685,6 +686,7 @@ fn register_actions(
                     files: true,
                     directories: true,
                     multiple: true,
+                    prompt: None,
                 },
                 DirectoryLister::Project(workspace.project().clone()),
                 window,