Skip to content

Commit c52dd44

Browse files
committed
Mac implementation for all dialog types
1 parent 915522f commit c52dd44

File tree

6 files changed

+62
-22
lines changed

6 files changed

+62
-22
lines changed

AssetRipper.NativeDialogs.Example/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@ static async Task Main(string[] args)
7373
Console.WriteLine("Cancelled.");
7474
break;
7575
case null:
76-
Console.WriteLine("No response.");
76+
Console.WriteLine("Could not be displayed.");
7777
break;
7878
}
7979
}
8080
else if (arguments.Message)
8181
{
82-
await MessageDialog.Message("This is a message dialog.", "OK");
82+
await MessageDialog.Message("This is a message dialog.");
8383
Console.WriteLine("Message dialog displayed.");
8484
}
8585
else

AssetRipper.NativeDialogs/ConfirmationDialog.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,22 @@ public static class ConfirmationDialog
1111

1212
public static Task<bool?> Confirm(string message, string trueLabel, string falseLabel)
1313
{
14+
ArgumentException.ThrowIfNullOrEmpty(message);
15+
ArgumentException.ThrowIfNullOrEmpty(trueLabel);
16+
ArgumentException.ThrowIfNullOrEmpty(falseLabel);
17+
ArgumentOutOfRangeException.ThrowIfEqual(trueLabel, falseLabel);
18+
1419
if (OperatingSystem.IsWindows())
1520
{
16-
return ConfirmWindows();
21+
return ConfirmWindows(message, trueLabel, falseLabel);
1722
}
1823
else if (OperatingSystem.IsMacOS())
1924
{
20-
return ConfirmMacOS();
25+
return ConfirmMacOS(message, trueLabel, falseLabel);
2126
}
2227
else if (OperatingSystem.IsLinux())
2328
{
24-
return ConfirmLinux();
29+
return ConfirmLinux(message, trueLabel, falseLabel);
2530
}
2631
else
2732
{
@@ -30,19 +35,36 @@ public static class ConfirmationDialog
3035
}
3136

3237
[SupportedOSPlatform("windows")]
33-
private unsafe static Task<bool?> ConfirmWindows()
38+
private unsafe static Task<bool?> ConfirmWindows(string message, string trueLabel, string falseLabel)
3439
{
3540
return Task.FromResult<bool?>(null);
3641
}
3742

3843
[SupportedOSPlatform("macos")]
39-
private static Task<bool?> ConfirmMacOS()
44+
private static async Task<bool?> ConfirmMacOS(string message, string trueLabel, string falseLabel)
4045
{
41-
return Task.FromResult<bool?>(null);
46+
string escapedMessage = ProcessExecutor.EscapeString(message);
47+
string escapedTrueLabel = ProcessExecutor.EscapeString(trueLabel);
48+
string escapedFalseLabel = ProcessExecutor.EscapeString(falseLabel);
49+
string? result = await ProcessExecutor.TryRun("osascript",
50+
"-e", $"display dialog \"{escapedMessage}\" buttons {{\"{escapedTrueLabel}\", \"{escapedFalseLabel}\"}} default button \"{escapedTrueLabel}\"",
51+
"-e", "button returned of result");
52+
if (result == trueLabel)
53+
{
54+
return true;
55+
}
56+
else if (result == falseLabel)
57+
{
58+
return false;
59+
}
60+
else
61+
{
62+
return null; // An error occurred
63+
}
4264
}
4365

4466
[SupportedOSPlatform("linux")]
45-
private static Task<bool?> ConfirmLinux()
67+
private static Task<bool?> ConfirmLinux(string message, string trueLabel, string falseLabel)
4668
{
4769
if (Gtk.Global.IsSupported)
4870
{

AssetRipper.NativeDialogs/MessageDialog.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ public static class MessageDialog
99
OperatingSystem.IsMacOS() ||
1010
(OperatingSystem.IsLinux() && Gtk.Global.IsSupported);
1111

12-
public static Task Message(string message, string label)
12+
public static Task Message(string message)
1313
{
1414
if (OperatingSystem.IsWindows())
1515
{
16-
return MessageWindows();
16+
return MessageWindows(message);
1717
}
1818
else if (OperatingSystem.IsMacOS())
1919
{
20-
return MessageMacOS();
20+
return MessageMacOS(message);
2121
}
2222
else if (OperatingSystem.IsLinux())
2323
{
24-
return MessageLinux();
24+
return MessageLinux(message);
2525
}
2626
else
2727
{
@@ -30,19 +30,20 @@ public static Task Message(string message, string label)
3030
}
3131

3232
[SupportedOSPlatform("windows")]
33-
private unsafe static Task MessageWindows()
33+
private unsafe static Task MessageWindows(string message)
3434
{
3535
return Task.CompletedTask;
3636
}
3737

3838
[SupportedOSPlatform("macos")]
39-
private static Task MessageMacOS()
39+
private static Task MessageMacOS(string message)
4040
{
41-
return Task.CompletedTask;
41+
string escapedMessage = ProcessExecutor.EscapeString(message);
42+
return ProcessExecutor.TryRun("osascript", "-e", $"display dialog \"{escapedMessage}\"");
4243
}
4344

4445
[SupportedOSPlatform("linux")]
45-
private static Task MessageLinux()
46+
private static Task MessageLinux(string message)
4647
{
4748
if (Gtk.Global.IsSupported)
4849
{

AssetRipper.NativeDialogs/OpenFolderDialog.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,22 @@ public static class OpenFolderDialog
8282
[SupportedOSPlatform("macos")]
8383
private static async Task<string[]?> OpenFoldersMacOS()
8484
{
85-
// Todo: proper Mac implementation
86-
string? path = await OpenFolder();
87-
if (string.IsNullOrEmpty(path))
85+
ReadOnlySpan<string> arguments =
86+
[
87+
"-e", "set theFolders to choose folder with multiple selections allowed",
88+
"-e", "set folderPaths to {}",
89+
"-e", "repeat with aFolder in theFolders",
90+
"-e", "set end of folderPaths to POSIX path of aFolder",
91+
"-e", "end repeat",
92+
"-e", "set text item delimiters to \":\"",
93+
"-e", "return folderPaths as string",
94+
];
95+
string? output = await ProcessExecutor.TryRun("osascript", arguments);
96+
if (string.IsNullOrEmpty(output))
8897
{
8998
return null; // User canceled the dialog
9099
}
91-
return [path];
100+
return output.Split(':');
92101
}
93102

94103
[SupportedOSPlatform("linux")]

AssetRipper.NativeDialogs/ProcessExecutor.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ namespace AssetRipper.NativeDialogs;
44

55
internal static class ProcessExecutor
66
{
7+
public static string EscapeString(string str)
8+
{
9+
return str
10+
.Replace("\\", "\\\\")
11+
.Replace("\"", "\\\"")
12+
.Replace("'", "\\'");
13+
}
14+
715
public static Task<string?> TryRun(string command, params ReadOnlySpan<string> arguments)
816
{
917
Process p = new()

AssetRipper.NativeDialogs/SaveFileDialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public static class SaveFileDialog
7272
[SupportedOSPlatform("macos")]
7373
private static Task<string?> SaveFileMacOS()
7474
{
75-
return ProcessExecutor.TryRun("osascript", "-e", "POSIX path of (choose file)");
75+
return ProcessExecutor.TryRun("osascript", "-e", "POSIX path of (choose file name with prompt \"Save file as:\")");
7676
}
7777

7878
[SupportedOSPlatform("linux")]

0 commit comments

Comments
 (0)