diff --git a/Coder-Desktop/Coder-Desktop/Theme.swift b/Coder-Desktop/Coder-Desktop/Theme.swift index f5a2213..ca7e77c 100644 --- a/Coder-Desktop/Coder-Desktop/Theme.swift +++ b/Coder-Desktop/Coder-Desktop/Theme.swift @@ -11,6 +11,8 @@ enum Theme { static let appIconWidth: CGFloat = 17 static let appIconHeight: CGFloat = 17 static let appIconSize: CGSize = .init(width: appIconWidth, height: appIconHeight) + + static let tableFooterIconSize: CGFloat = 28 } enum Animation { diff --git a/Coder-Desktop/Coder-Desktop/Views/FileSync/FileSyncConfig.swift b/Coder-Desktop/Coder-Desktop/Views/FileSync/FileSyncConfig.swift index 7400635..302bd13 100644 --- a/Coder-Desktop/Coder-Desktop/Views/FileSync/FileSyncConfig.swift +++ b/Coder-Desktop/Coder-Desktop/Views/FileSync/FileSyncConfig.swift @@ -47,7 +47,7 @@ struct FileSyncConfig: View { } }) .frame(minWidth: 400, minHeight: 200) - .padding(.bottom, 25) + .padding(.bottom, Theme.Size.tableFooterIconSize) .overlay(alignment: .bottom) { tableFooter } @@ -121,8 +121,8 @@ struct FileSyncConfig: View { Button { addingNewSession = true } label: { - Image(systemName: "plus") - .frame(width: 24, height: 24).help("Create") + FooterIcon(systemName: "plus") + .help("Create") }.disabled(vpn.menuState.agents.isEmpty) sessionControls } @@ -139,21 +139,25 @@ struct FileSyncConfig: View { Divider() Button { Task { await delete(session: selectedSession) } } label: { - Image(systemName: "minus").frame(width: 24, height: 24).help("Terminate") + FooterIcon(systemName: "minus") + .help("Terminate") } Divider() Button { Task { await pauseResume(session: selectedSession) } } label: { if selectedSession.status.isResumable { - Image(systemName: "play").frame(width: 24, height: 24).help("Pause") + FooterIcon(systemName: "play") + .help("Resume") } else { - Image(systemName: "pause").frame(width: 24, height: 24).help("Resume") + FooterIcon(systemName: "pause") + .help("Pause") } } Divider() Button { Task { await reset(session: selectedSession) } } label: { - Image(systemName: "arrow.clockwise").frame(width: 24, height: 24).help("Reset") + FooterIcon(systemName: "arrow.clockwise") + .help("Reset") } } } @@ -199,6 +203,18 @@ struct FileSyncConfig: View { } } +struct FooterIcon: View { + let systemName: String + + var body: some View { + Image(systemName: systemName) + .frame( + width: Theme.Size.tableFooterIconSize, + height: Theme.Size.tableFooterIconSize + ) + } +} + #if DEBUG #Preview { FileSyncConfig() diff --git a/Coder-Desktop/Coder-Desktop/Views/VPN/VPNMenuItem.swift b/Coder-Desktop/Coder-Desktop/Views/VPN/VPNMenuItem.swift index 7f681be..880241a 100644 --- a/Coder-Desktop/Coder-Desktop/Views/VPN/VPNMenuItem.swift +++ b/Coder-Desktop/Coder-Desktop/Views/VPN/VPNMenuItem.swift @@ -235,10 +235,12 @@ struct MenuItemIcons: View { MenuItemIconButton(systemName: "doc.on.doc", action: copyToClipboard) .font(.system(size: 9)) .symbolVariant(.fill) + .help("Copy hostname") MenuItemIconButton(systemName: "globe", action: { openURL(wsURL) }) .contentShape(Rectangle()) .font(.system(size: 12)) .padding(.trailing, Theme.Size.trayMargin) + .help("Open in browser") } } diff --git a/Coder-Desktop/VPNLib/Download.swift b/Coder-Desktop/VPNLib/Download.swift index 99febc2..f6ffe5b 100644 --- a/Coder-Desktop/VPNLib/Download.swift +++ b/Coder-Desktop/VPNLib/Download.swift @@ -146,15 +146,15 @@ func etag(data: Data) -> String { } public enum DownloadError: Error { - case unexpectedStatusCode(Int) + case unexpectedStatusCode(Int, url: String) case invalidResponse case networkError(any Error, url: String) case fileOpError(any Error) public var description: String { switch self { - case let .unexpectedStatusCode(code): - "Unexpected HTTP status code: \(code)" + case let .unexpectedStatusCode(code, url): + "Unexpected HTTP status code: \(code) - \(url)" case let .networkError(error, url): "Network error: \(url) - \(error.localizedDescription)" case let .fileOpError(error): @@ -232,7 +232,12 @@ extension DownloadManager: URLSessionDownloadDelegate { } guard httpResponse.statusCode == 200 else { - continuation.resume(throwing: DownloadError.unexpectedStatusCode(httpResponse.statusCode)) + continuation.resume( + throwing: DownloadError.unexpectedStatusCode( + httpResponse.statusCode, + url: httpResponse.url?.absoluteString ?? "Unknown URL" + ) + ) return }