-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathPlatformHelper.cs
More file actions
80 lines (67 loc) · 3.51 KB
/
PlatformHelper.cs
File metadata and controls
80 lines (67 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System.Linq;
namespace PolyPilot.Models;
public static class PlatformHelper
{
public static bool IsDesktop =>
// Runtime detection — OperatingSystem.IsIOS() returns true on Mac Catalyst,
// so we must exclude it explicitly to correctly identify Mac Catalyst as desktop.
OperatingSystem.IsMacCatalyst() || (!OperatingSystem.IsIOS() && !OperatingSystem.IsAndroid());
public static bool IsMobile =>
(OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsAndroid();
public static string PlatformName =>
OperatingSystem.IsMacCatalyst() ? "maccatalyst" :
OperatingSystem.IsMacOS() ? "maccatalyst" :
OperatingSystem.IsWindows() ? "windows" :
OperatingSystem.IsIOS() ? "ios" :
OperatingSystem.IsAndroid() ? "android" :
OperatingSystem.IsLinux() ? "linux" : "unknown";
public static ConnectionMode[] AvailableModes => IsDesktop
? [ConnectionMode.Embedded, ConnectionMode.Persistent, ConnectionMode.Remote]
#if DEBUG
: [ConnectionMode.Remote, ConnectionMode.Demo];
#else
: [ConnectionMode.Remote];
#endif
public static ConnectionMode DefaultMode => IsDesktop
? ConnectionMode.Persistent
: ConnectionMode.Remote;
/// <summary>
/// Shell-escapes a string for safe embedding in bash scripts using single quotes.
/// Single quotes prevent all shell expansion (variables, command substitution, etc.).
/// The only character that needs escaping inside single quotes is ' itself.
/// </summary>
public static string ShellEscape(string value) => "'" + value.Replace("'", "'\"'\"'") + "'";
/// <summary>
/// Returns the platform-appropriate shell executable and arguments for running a command.
/// On Windows uses cmd.exe /c; on Mac/Linux uses /bin/bash -c.
/// </summary>
public static (string FileName, string Arguments) GetShellCommand(string command)
{
if (OperatingSystem.IsWindows())
// Outer quotes ensure cmd.exe's quote-stripping is deterministic
return ("cmd.exe", $"/c \"{command}\"");
var escaped = command.Replace("\\", "\\\\").Replace("\"", "\\\"");
return ("/bin/bash", $"-c \"{escaped}\"");
}
/// <summary>
/// Builds a <c>vscode-remote://</c> folder URI for opening a remote folder in VS Code
/// via the Remote - Tunnels extension. Returns null when not in remote mode or machine name unknown.
/// </summary>
public static string? BuildVSCodeRemoteFolderUri(bool isRemoteMode, string? serverMachineName, string? folderPath)
{
if (!isRemoteMode || string.IsNullOrEmpty(serverMachineName) || string.IsNullOrEmpty(folderPath))
return null;
// Normalize to forward slashes for URI path
var uriPath = folderPath.Replace('\\', '/');
// Reject UNC paths (\\server\share → //server/share) — no meaningful remote URI
if (uriPath.StartsWith("//"))
return null;
// Windows paths like C:/Users/... need a leading slash → /C:/Users/...
if (uriPath.Length >= 2 && uriPath[1] == ':')
uriPath = "/" + uriPath;
// URI-encode path segments (spaces, special chars) while preserving slashes.
// Unescape ':' — it's valid in URI path segments (RFC 3986) and needed for Windows drive letters.
uriPath = string.Join("/", uriPath.Split('/').Select(s => Uri.EscapeDataString(s).Replace("%3A", ":")));
return $"vscode-remote://tunnel+{serverMachineName}{uriPath}";
}
}