diff --git a/Packages/VNCCore/Sources/VNCCore/Session/SessionController.swift b/Packages/VNCCore/Sources/VNCCore/Session/SessionController.swift index c9ea917..f5466ae 100644 --- a/Packages/VNCCore/Sources/VNCCore/Session/SessionController.swift +++ b/Packages/VNCCore/Sources/VNCCore/Session/SessionController.swift @@ -28,6 +28,7 @@ public final class SessionController { public let displayName: String public let host: String public let port: Int + public let username: String private let keychainTag: String private let passwordProvider: any PasswordProviding @@ -47,6 +48,7 @@ public final class SessionController { displayName: String, host: String, port: Int, + username: String = "", keychainTag: String, viewOnly: Bool = false, clipboardSyncEnabled: Bool = true, @@ -59,6 +61,7 @@ public final class SessionController { self.displayName = displayName self.host = host self.port = port + self.username = username self.keychainTag = keychainTag self.viewOnly = viewOnly self.clipboardSyncEnabled = clipboardSyncEnabled @@ -78,6 +81,7 @@ public final class SessionController { displayName: saved.displayName, host: saved.host, port: saved.port, + username: saved.username, keychainTag: saved.keychainTag, viewOnly: saved.viewOnly, clipboardSyncEnabled: saved.clipboardSyncEnabled, @@ -302,7 +306,8 @@ public final class SessionController { let adapter = DelegateAdapter( controller: self, passwordProvider: passwordProvider, - keychainTag: keychainTag + keychainTag: keychainTag, + username: username ) connection.delegate = adapter self.connection = connection @@ -366,13 +371,16 @@ private final class DelegateAdapter: NSObject, VNCConnectionDelegate, @unchecked weak var controller: SessionController? let passwordProvider: any PasswordProviding let keychainTag: String + let username: String init(controller: SessionController, passwordProvider: any PasswordProviding, - keychainTag: String) { + keychainTag: String, + username: String) { self.controller = controller self.passwordProvider = passwordProvider self.keychainTag = keychainTag + self.username = username } func connection(_ connection: VNCConnection, @@ -398,7 +406,7 @@ private final class DelegateAdapter: NSObject, VNCConnectionDelegate, @unchecked case .vnc: credential = VNCPasswordCredential(password: pwd) case .appleRemoteDesktop, .ultraVNCMSLogonII: - credential = VNCUsernamePasswordCredential(username: "", password: pwd) + credential = VNCUsernamePasswordCredential(username: username, password: pwd) @unknown default: credential = VNCPasswordCredential(password: pwd) } diff --git a/Packages/VNCCore/Sources/VNCCore/Storage/SavedConnection.swift b/Packages/VNCCore/Sources/VNCCore/Storage/SavedConnection.swift index e016b67..0a705cc 100644 --- a/Packages/VNCCore/Sources/VNCCore/Storage/SavedConnection.swift +++ b/Packages/VNCCore/Sources/VNCCore/Storage/SavedConnection.swift @@ -7,6 +7,7 @@ public final class SavedConnection { public var displayName: String public var host: String public var port: Int + public var username: String public var colorTagRaw: String public var lastConnectedAt: Date? public var preferredEncodings: [String] @@ -23,6 +24,7 @@ public final class SavedConnection { displayName: String, host: String, port: Int = 5900, + username: String = "", colorTag: ColorTag = .blue, preferredEncodings: [String] = ["7", "16", "5", "6"], keychainTag: String = UUID().uuidString, @@ -37,6 +39,7 @@ public final class SavedConnection { self.displayName = displayName self.host = host self.port = port + self.username = username self.colorTagRaw = colorTag.rawValue self.lastConnectedAt = nil self.preferredEncodings = preferredEncodings diff --git a/Packages/VNCUI/Sources/VNCUI/Edit/AddConnectionView.swift b/Packages/VNCUI/Sources/VNCUI/Edit/AddConnectionView.swift index a143aac..2490806 100644 --- a/Packages/VNCUI/Sources/VNCUI/Edit/AddConnectionView.swift +++ b/Packages/VNCUI/Sources/VNCUI/Edit/AddConnectionView.swift @@ -24,6 +24,7 @@ public struct AddConnectionView: View { @State private var displayName = "" @State private var host = "" @State private var port = "5900" + @State private var username = "" @State private var password = "" @State private var revealPassword = false @State private var colorTag: ColorTag = .blue @@ -45,6 +46,17 @@ public struct AddConnectionView: View { !host.trimmingCharacters(in: .whitespaces).isEmpty } + private var authFooterText: String { + if isEditing { + return "Leave password blank to keep the current one. Stored in iOS Keychain (this device only)." + } + return """ + Two Mac paths: + • User account (ARD) — enter your macOS short name + full account password. No length limit. Enabled in System Settings → Sharing → Screen Sharing → Allow access for… + • VNC-only password — leave the username blank; macOS truncates to 8 characters. Enabled via Screen Sharing → ⓘ → "VNC viewers may control screen with password". + """ + } + public var body: some View { NavigationStack { Form { @@ -75,12 +87,17 @@ public struct AddConnectionView: View { } Section { + TextField("Username (optional)", text: $username) + #if os(iOS) + .textInputAutocapitalization(.never) + #endif + .autocorrectionDisabled() HStack { Group { if revealPassword { - TextField("VNC password", text: $password) + TextField("Password", text: $password) } else { - SecureField(isEditing ? "Replace password" : "VNC password", + SecureField(isEditing ? "Replace password" : "Password", text: $password) } } @@ -96,9 +113,7 @@ public struct AddConnectionView: View { } header: { Text("Authentication") } footer: { - Text(isEditing - ? "Leave blank to keep the current password. Stored in iOS Keychain (this device only)." - : "macOS Screen Sharing's VNC password is limited to 8 characters. Stored in iOS Keychain (this device only).") + Text(authFooterText) } Section { @@ -199,6 +214,7 @@ public struct AddConnectionView: View { displayName = existing.displayName host = existing.host port = String(existing.port) + username = existing.username colorTag = existing.colorTag quality = existing.quality inputMode = existing.inputMode @@ -214,10 +230,12 @@ public struct AddConnectionView: View { private func save() { let portInt = Int(port) ?? 5900 + let trimmedUsername = username.trimmingCharacters(in: .whitespaces) if let existing = editing { existing.displayName = displayName existing.host = host existing.port = portInt + existing.username = trimmedUsername existing.colorTag = colorTag existing.quality = quality existing.inputMode = inputMode @@ -232,6 +250,7 @@ public struct AddConnectionView: View { displayName: displayName, host: host, port: portInt, + username: trimmedUsername, colorTag: colorTag, quality: quality, inputMode: inputMode, diff --git a/Project.yml b/Project.yml index 2043396..c06994b 100644 --- a/Project.yml +++ b/Project.yml @@ -11,6 +11,7 @@ settings: SWIFT_STRICT_CONCURRENCY: complete ENABLE_USER_SCRIPT_SANDBOXING: YES CODE_SIGN_STYLE: Automatic + DEVELOPMENT_TEAM: V3PF3M6B6U packages: VNCCore: