From c19b39a343c68208c74b4d73997900834f2cf642 Mon Sep 17 00:00:00 2001
From: Ethan <39577870+ethanndickson@users.noreply.github.com>
Date: Thu, 26 Jun 2025 12:24:10 +1000
Subject: [PATCH 1/2] chore: append bundle version to mach service name (#191)
We append the CFBundleVersion to the service name to ensure a new service is used for each version. This works around the issue described in https://github.com/coder/coder-desktop-macos/issues/121, presumably caused by the XPC service cache not being invalidated on update.

---
Coder-Desktop/Coder-Desktop/Info.plist | 7 ++++++-
Coder-Desktop/Coder-Desktop/VPN/VPNSystemExtension.swift | 5 +++--
Coder-Desktop/VPN/Info.plist | 7 ++++++-
3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/Coder-Desktop/Coder-Desktop/Info.plist b/Coder-Desktop/Coder-Desktop/Info.plist
index a9555823..654a5179 100644
--- a/Coder-Desktop/Coder-Desktop/Info.plist
+++ b/Coder-Desktop/Coder-Desktop/Info.plist
@@ -29,7 +29,12 @@
NetworkExtension
NEMachServiceName
- $(TeamIdentifierPrefix)com.coder.Coder-Desktop.VPN
+
+ $(TeamIdentifierPrefix)com.coder.Coder-Desktop.VPN.$(CURRENT_PROJECT_VERSION)
SUPublicEDKey
Ae2oQLTcx89/a73XrpOt+IVvqdo+fMTjo3UKEm77VdA=
diff --git a/Coder-Desktop/Coder-Desktop/VPN/VPNSystemExtension.swift b/Coder-Desktop/Coder-Desktop/VPN/VPNSystemExtension.swift
index cb8db684..c5e4ea08 100644
--- a/Coder-Desktop/Coder-Desktop/VPN/VPNSystemExtension.swift
+++ b/Coder-Desktop/Coder-Desktop/VPN/VPNSystemExtension.swift
@@ -183,6 +183,7 @@ class SystemExtensionDelegate:
if existing.bundleVersion == `extension`.bundleVersion {
return .replace
}
+ // TODO: Workaround disabled, as we're trying another workaround
// To work around the bug described in
// https://github.com/coder/coder-desktop-macos/issues/121,
// we're going to manually reinstall after the replacement is done.
@@ -190,8 +191,8 @@ class SystemExtensionDelegate:
// it looks for an extension with the *current* version string.
// There's no way to modify the deactivate request to use a different
// version string (i.e. `existing.bundleVersion`).
- logger.info("App upgrade detected, replacing and then reinstalling")
- action = .replacing
+ // logger.info("App upgrade detected, replacing and then reinstalling")
+ // action = .replacing
return .replace
}
}
diff --git a/Coder-Desktop/VPN/Info.plist b/Coder-Desktop/VPN/Info.plist
index 97d4cce6..0040d95c 100644
--- a/Coder-Desktop/VPN/Info.plist
+++ b/Coder-Desktop/VPN/Info.plist
@@ -9,7 +9,12 @@
NetworkExtension
NEMachServiceName
- $(TeamIdentifierPrefix)com.coder.Coder-Desktop.VPN
+
+ $(TeamIdentifierPrefix)com.coder.Coder-Desktop.VPN.$(CURRENT_PROJECT_VERSION)
NEProviderClasses
com.apple.networkextension.packet-tunnel
From 15f1890fea076bc5d1ffbffb2b686496ec5e7f7e Mon Sep 17 00:00:00 2001
From: Ethan <39577870+ethanndickson@users.noreply.github.com>
Date: Wed, 9 Jul 2025 20:00:46 +1000
Subject: [PATCH 2/2] fix: correct remote file picker dropdown chevron
alignment (#192)
There appears to be a bug when a View created using `NSView` is inside a `DisclosureGroup` label - regardless of the size of the `NSView`, it breaks the alignment of the chevron that's included on the DisclosureGroup label by default:

In #184 we added an `NSView` to the spinner, causing this issue.
This is almost certainly a SwiftUI bug, and so we'll work around it by placing the spinner and error symbol to the right of the label by just setting a trailing padding on the text.
The end result (with spinners on):

---
.../Views/FileSync/FilePicker.swift | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/Coder-Desktop/Coder-Desktop/Views/FileSync/FilePicker.swift b/Coder-Desktop/Coder-Desktop/Views/FileSync/FilePicker.swift
index 6f392961..9ec26231 100644
--- a/Coder-Desktop/Coder-Desktop/Views/FileSync/FilePicker.swift
+++ b/Coder-Desktop/Coder-Desktop/Views/FileSync/FilePicker.swift
@@ -123,12 +123,18 @@ struct FilePickerEntry: View {
} label: {
Label {
Text(entry.name)
- ZStack {
- CircularProgressView(value: nil, strokeWidth: 2, diameter: 10)
- .opacity(entry.isLoading && entry.error == nil ? 1 : 0)
- Image(systemName: "exclamationmark.triangle.fill")
- .opacity(entry.error != nil ? 1 : 0)
- }
+ // The NSView within the CircularProgressView breaks
+ // the chevron alignment within the DisclosureGroup view.
+ // So, we overlay the progressview with a manual offset
+ .padding(.trailing, 20)
+ .overlay(alignment: .trailing) {
+ ZStack {
+ CircularProgressView(value: nil, strokeWidth: 2, diameter: 10)
+ .opacity(entry.isLoading && entry.error == nil ? 1 : 0)
+ Image(systemName: "exclamationmark.triangle.fill")
+ .opacity(entry.error != nil ? 1 : 0)
+ }
+ }
} icon: {
Image(systemName: "folder")
}.help(entry.error != nil ? entry.error!.description : entry.absolute_path)