multiline native dialog description

This commit is contained in:
FTCHD
2026-08-20 00:25:10 +03:00
parent a96a7a0bd6
commit 7cfb44d47a
+33 -13
View File
@@ -395,19 +395,27 @@ async fn prompt_text(
let default_value = default.unwrap_or_default(); let default_value = default.unwrap_or_default();
let is_sensitive = sensitive.unwrap_or(false); let is_sensitive = sensitive.unwrap_or(false);
// AppleScript string literals can't contain a raw newline, so a multi-line message (e.g. a
// numbered choice list) must have its newlines turned into the `\n` escape sequence. Escape
// backslashes and quotes first so the conversions don't collide.
let esc = |s: &str| s.replace('\\', "\\\\").replace('"', "\\\"");
let esc_message = esc(&message)
.replace("\r\n", "\\n")
.replace('\n', "\\n")
.replace('\r', "\\n");
let esc_title = esc(&title);
let esc_default = esc(&default_value);
let script = if is_sensitive { let script = if is_sensitive {
format!( format!(
r#"display dialog "{}" with title "{}" default answer "{}" with hidden answer"#, r#"display dialog "{}" with title "{}" default answer "{}" with hidden answer"#,
message.replace("\"", "\\\""), esc_message, esc_title, esc_default,
title.replace("\"", "\\\""),
default_value.replace("\"", "\\\""),
) )
} else { } else {
format!( format!(
r#"display dialog "{}" with title "{}" default answer "{}""#, r#"display dialog "{}" with title "{}" default answer "{}""#,
message.replace("\"", "\\\""), esc_message, esc_title, esc_default,
title.replace("\"", "\\\""),
default_value.replace("\"", "\\\""),
) )
}; };
@@ -446,12 +454,20 @@ async fn prompt_text(
let default_value = default.unwrap_or_default(); let default_value = default.unwrap_or_default();
let is_sensitive = sensitive.unwrap_or(false); let is_sensitive = sensitive.unwrap_or(false);
// Use PowerShell to create a simple text input dialog // Use PowerShell to create a simple text input dialog. PowerShell single-quoted strings keep
// literal newlines, so a multi-line message (e.g. a numbered choice list) renders across
// lines in the label — we just have to grow the label/form to fit its line count.
let ps_default = default_value.replace('\'', "''"); let ps_default = default_value.replace('\'', "''");
let ps_title = title.replace('\'', "''"); let ps_title = title.replace('\'', "''");
let ps_message = message.replace('\'', "''"); let ps_message = message.replace('\'', "''");
let ps_password_flag = if is_sensitive { "$true" } else { "$false" }; let ps_password_flag = if is_sensitive { "$true" } else { "$false" };
let line_count = message.lines().count().max(1) as i32;
let label_height = (line_count * 18 + 8).clamp(40, 380);
let textbox_y = 15 + label_height + 8;
let button_y = textbox_y + 34;
let form_height = button_y + 70;
let powershell_script = format!( let powershell_script = format!(
r#" r#"
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Windows.Forms
@@ -459,7 +475,7 @@ async fn prompt_text(
$form = New-Object System.Windows.Forms.Form $form = New-Object System.Windows.Forms.Form
$form.Text = '{title}' $form.Text = '{title}'
$form.Size = New-Object System.Drawing.Size(350, 180) $form.Size = New-Object System.Drawing.Size(350, {form_height})
$form.StartPosition = 'CenterScreen' $form.StartPosition = 'CenterScreen'
$form.FormBorderStyle = 'FixedDialog' $form.FormBorderStyle = 'FixedDialog'
$form.MaximizeBox = $false $form.MaximizeBox = $false
@@ -468,19 +484,19 @@ async fn prompt_text(
$label = New-Object System.Windows.Forms.Label $label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10, 15) $label.Location = New-Object System.Drawing.Point(10, 15)
$label.Size = New-Object System.Drawing.Size(320, 40) $label.Size = New-Object System.Drawing.Size(320, {label_height})
$label.Text = '{message}' $label.Text = '{message}'
$form.Controls.Add($label) $form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox $textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10, 60) $textBox.Location = New-Object System.Drawing.Point(10, {textbox_y})
$textBox.Size = New-Object System.Drawing.Size(320, 20) $textBox.Size = New-Object System.Drawing.Size(320, 20)
$textBox.Text = '{default}' $textBox.Text = '{default}'
$textBox.UseSystemPasswordChar = {password} $textBox.UseSystemPasswordChar = {password}
$form.Controls.Add($textBox) $form.Controls.Add($textBox)
$okButton = New-Object System.Windows.Forms.Button $okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(175, 100) $okButton.Location = New-Object System.Drawing.Point(175, {button_y})
$okButton.Size = New-Object System.Drawing.Size(75, 23) $okButton.Size = New-Object System.Drawing.Size(75, 23)
$okButton.Text = 'OK' $okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
@@ -488,7 +504,7 @@ async fn prompt_text(
$form.Controls.Add($okButton) $form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button $cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(255, 100) $cancelButton.Location = New-Object System.Drawing.Point(255, {button_y})
$cancelButton.Size = New-Object System.Drawing.Size(75, 23) $cancelButton.Size = New-Object System.Drawing.Size(75, 23)
$cancelButton.Text = 'Cancel' $cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
@@ -505,7 +521,11 @@ async fn prompt_text(
title = ps_title, title = ps_title,
message = ps_message, message = ps_message,
default = ps_default, default = ps_default,
password = ps_password_flag password = ps_password_flag,
form_height = form_height,
label_height = label_height,
textbox_y = textbox_y,
button_y = button_y,
); );
let output = Command::new("powershell") let output = Command::new("powershell")