8000 disable header settings while vpn is on · coder/coder-desktop-macos@2638e0c · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 2638e0c

Browse files
committed
disable header settings while vpn is on
1 parent cea139b commit 2638e0c

File tree

13 files changed

+174
-82
lines changed
  • Views
  • Coder Desktop.xcodeproj
  • Coder DesktopTests
  • 13 files changed

    +174
    -82
    lines changed

    Coder Desktop/Coder Desktop.xcodeproj/project.pbxproj

    Lines changed: 17 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -25,6 +25,7 @@
    2525
    AA8BC3392D0060A900E1ABAA /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC3382D0060A900E1ABAA /* ViewInspector */; };
    2626
    AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC33E2D0061F200E1ABAA /* FluidMenuBarExtra */; };
    2727
    AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC4CE2D00A4B700E1ABAA /* KeychainAccess */; };
    28+
    AA8EECF72D3A22320049DD09 /* SettingsAccess in Frameworks */ = {isa = PBXBuildFile; productRef = AA8EECF62D3A22320049DD09 /* SettingsAccess */; };
    2829
    /* End PBXBuildFile section */
    2930

    3031
    /* Begin PBXContainerItemProxy section */
    @@ -232,6 +233,7 @@
    232233
    AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */,
    233234
    AA2C690F2D34F6920059AFAF /* LaunchAtLogin in Frameworks */,
    234235
    AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */,
    236+
    AA8EECF72D3A22320049DD09 /* SettingsAccess in Frameworks */,
    235237
    );
    236238
    runOnlyForDeploymentPostprocessing = 0;
    237239
    };
    @@ -382,6 +384,7 @@
    382384
    AA8BC33E2D0061F200E1ABAA /* FluidMenuBarExtra */,
    383385
    AA8BC4CE2D00A4B700E1ABAA /* KeychainAccess */,
    384386
    AA2C690E2D34F6920059AFAF /* LaunchAtLogin */,
    387+
    AA8EECF62D3A22320049DD09 /* SettingsAccess */,
    385388
    );
    386389
    productName = "Coder Desktop";
    387390
    productReference = 961678FC2CFF100D00B2B6DF /* Coder Desktop.app */;
    @@ -623,6 +626,7 @@
    623626
    AA3B3E8A2D2E0FE10099996A /* XCRemoteSwiftPackageReference "Mocker" */,
    624627
    AA2C690D2D34F6920059AFAF /* XCRemoteSwiftPackageReference "LaunchAtLogin-modern" */,
    625628
    AA2C698A2D354A600059AFAF /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */,
    629+
    AA8EECF52D3A22320049DD09 /* XCRemoteSwiftPackageReference "SettingsAccess" */,
    626630
    );
    627631
    preferredProjectObjectVersion = 77;
    628632
    productRefGroup = 961678FD2CFF100D00B2B6DF /* Products */;
    @@ -1533,6 +1537,14 @@
    15331537
    kind = branch;
    15341538
    };
    15351539
    };
    1540+
    AA8EECF52D3A22320049DD09 /* XCRemoteSwiftPackageReference "SettingsAccess" */ = {
    1541+
    isa = XCRemoteSwiftPackageReference;
    1542+
    repositoryURL = "https://github.com/orchetect/SettingsAccess";
    1543+
    requirement = {
    1544+
    kind = upToNextMajorVersion;
    1545+
    minimumVersion = 2.1.0;
    1546+
    };
    1547+
    };
    15361548
    /* End XCRemoteSwiftPackageReference section */
    15371549

    15381550
    /* Begin XCSwiftPackageProductDependency section */
    @@ -1621,6 +1633,11 @@
    16211633
    package = AA8BC4CD2D00A4B700E1ABAA /* XCRemoteSwiftPackageReference "KeychainAccess" */;
    16221634
    productName = KeychainAccess;
    16231635
    };
    1636+
    AA8EECF62D3A22320049DD09 /* SettingsAccess */ = {
    1637+
    isa = XCSwiftPackageProductDependency;
    1638+
    package = AA8EECF52D3A22320049DD09 /* XCRemoteSwiftPackageReference "SettingsAccess" */;
    1639+
    productName = SettingsAccess;
    1640+
    };
    16241641
    /* End XCSwiftPackageProductDependency section */
    16251642
    };
    16261643
    rootObject = 961678F42CFF100D00B2B6DF /* Project object */;

    Coder Desktop/Coder Desktop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

    Lines changed: 10 additions & 1 deletion
    Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

    Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

    Lines changed: 10 additions & 13 deletions
    Original file line numberDiff line numberDiff line change
    @@ -12,10 +12,13 @@ struct DesktopApp: App {
    1212
    EmptyView()
    1313
    }
    1414
    Window("Sign In", id: Windows.login.rawValue) {
    15-
    LoginForm<PreviewSession>().environmentObject(appDelegate.session)
    15+
    LoginForm<SecureSession>().environmentObject(appDelegate.session)
    16+
    }
    17+
    .windowResizability(.contentSize)
    18+
    SwiftUI.Settings { SettingsView<PreviewVPN>()
    19+
    .environmentObject(appDelegate.vpn)
    20+
    .environmentObject(appDelegate.settings)
    1621
    }
    17-
    .windowResizability(.contentSize)
    18-
    Settings { SettingsView() }.modelContainer(appDelegate.modelContainer)
    1922
    }
    2023
    }
    2124

    @@ -24,27 +27,21 @@ class AppDelegate: NSObject, NSApplicationDelegate {
    2427
    private var menuBarExtra: FluidMenuBarExtra?
    2528
    let vpn: PreviewVPN
    2629
    let session: PreviewSession
    27-
    let modelContainer: ModelContainer
    30+
    let settings: Settings
    2831

    2932
    override init() {
    30-
    // TODO: Replace with real implementations
    33+
    // TODO: Replace with real implementation
    3134
    vpn = PreviewVPN()
    35+
    settings = Settings()
    3236
    session = PreviewSession()
    33-
    modelContainer = try! ModelContainer( // swiftlint:disable:this force_try
    34-
    for: LiteralHeader.self,
    35-
    configurations: ModelConfiguration(
    36-
    url: .applicationSupportDirectory
    37-
    .appending(component: Bundle.main.bundleIdentifier!)
    38-
    .appending(component: "Store.sqlite")
    39-
    )
    40-
    )
    4137
    }
    4238

    4339
    func applicationDidFinishLaunching(_: Notification) {
    4440
    menuBarExtra = FluidMenuBarExtra(title: "Coder Desktop", image: "MenuBarIcon") {
    4541
    VPNMenu<PreviewVPN, PreviewSession>().frame(width: 256)
    4642
    .environmentObject(self.vpn)
    4743
    .environmentObject(self.session)
    44+
    .environmentObject(self.settings)
    4845
    }
    4946
    }
    5047

    Coder Desktop/Coder Desktop/Models/LiteralHeader.swift

    Lines changed: 0 additions & 19 deletions
    This file was deleted.

    Coder Desktop/Coder Desktop/Session.swift renamed to Coder Desktop/Coder Desktop/State.swift

    Lines changed: 46 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,8 @@
    1+
    import CoderSDK
    12
    import Foundation
    23
    import KeychainAccess
    34
    import NetworkExtension
    5+
    import SwiftUI
    46

    57
    protocol Session: ObservableObject {
    68
    var hasSession: Bool { get }
    @@ -89,3 +91,47 @@ class SecureSession: ObservableObject, Session {
    8991
    static let sessionToken = "sessionToken"
    9092
    }
    9193
    }
    94+
    95+
    class Settings: ObservableObject {
    96+
    let store: UserDefaults
    97+
    @AppStorage(Keys.useLiteralHeaders) var useLiteralHeaders = false
    98+
    99+
    @Published var literalHeaders: [LiteralHeader] {
    100+
    didSet {
    101+
    try? store.set(JSONEncoder().encode(literalHeaders), forKey: Keys.literalHeaders)
    102+
    }
    103+
    }
    104+
    105+
    init(store: UserDefaults = UserDefaults.standard) {
    106+
    self.store = store
    107+
    _literalHeaders = Published(
    108+
    initialValue: UserDefaults.standard.data(
    109+
    forKey: Keys.literalHeaders
    110+
    ).flatMap { try? JSONDecoder().decode([LiteralHeader].self, from: $0) } ?? []
    111+
    )
    112+
    }
    113+
    114+
    enum Keys {
    115+
    static let useLiteralHeaders = "UseLiteralHeaders"
    116+
    static let literalHeaders = "LiteralHeaders"
    117+
    }
    118+
    }
    119+
    120+
    struct LiteralHeader: Hashable, Identifiable, Equatable, Codable {
    121+
    var header: String
    122+
    var value: String
    123+
    var id: String {
    124+
    "\(header):\(value)"
    125+
    }
    126+
    127+
    init(header: String, value: String) {
    128+
    self.header = header
    129+
    self.value = value
    130+
    }
    131+
    }
    132+
    133+
    extension LiteralHeader {
    134+
    func toSDKHeader() -> HTTPHeader {
    135+
    return .init(header: header, value: value)
    136+
    }
    137+
    }

    Coder Desktop/Coder Desktop/Views/LoginForm.swift

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -4,6 +4,7 @@ import SwiftUI
    44

    55
    struct LoginForm<S: Session>: View {
    66
    @EnvironmentObject var session: S
    7+
    @EnvironmentObject var settings: Settings
    78
    @Environment(\.dismiss) private var dismiss
    89

    910
    @State private var baseAccessURL: String = ""
    @@ -12,7 +13,6 @@ struct LoginForm<S: Session>: View {
    1213
    @State private var currentPage: LoginPage = .serverURL
    1314
    @State private var loading: Bool = false
    1415
    @FocusState private var focusedField: LoginField?
    15-
    @Query private var headers: [LiteralHeader]
    1616

    1717
    let inspection = Inspection<Self>()
    1818

    @@ -70,7 +70,7 @@ struct LoginForm<S: Session>: View {
    7070
    }
    7171
    loading = true
    7272
    defer { loading = false }
    73-
    let client = Client(url: url, token: sessionToken, headers: headers.map { $0.toSDKHeader() })
    73+
    let client = Client(url: url, token: sessionToken, headers: settings.literalHeaders.map { $0.toSDKHeader() })
    7474
    do {
    7575
    _ = try await client.user("me")
    7676
    } catch {

    Coder Desktop/Coder Desktop/Views/Settings/LiteralHeaderModal.swift

    Lines changed: 10 additions & 11 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3,10 +3,12 @@ import SwiftUI
    33

    44
    struct LiteralHeaderModal: View {
    55
    var existingHeader: LiteralHeader?
    6+
    7+
    @EnvironmentObject var settings: Settings
    8+
    @Environment(\.dismiss) private var dismiss
    9+
    610
    @State private var header: String = ""
    711
    @State private var value: String = ""
    8-
    @Environment(\.dismiss) private var dismiss
    9-
    @Environment(\.modelContext) private var modelContext
    1012

    1113
    var body: some View {
    1214
    VStack(spacing: 0) {
    @@ -32,16 +34,13 @@ struct LiteralHeaderModal: View {
    3234
    }
    3335

    3436
    func submit() {
    37+
    defer { dismiss() }
    3538
    if let existingHeader {
    36-
    existingHeader.header = header
    37-
    existingHeader.value = value
    38-
    } else {
    39-
    modelContext.insert(LiteralHeader(header: header, value: value))
    39+
    settings.literalHeaders.removeAll { $0 == existingHeader }
    40+
    }
    41+
    let newHeader = LiteralHeader(header: header, value: value)
    42+
    if !settings.literalHeaders.contains(newHeader) {
    43+
    settings.literalHeaders.append(newHeader)
    4044
    }
    41-
    dismiss()
    4245
    }
    4346
    }
    44-
    45-
    #Preview {
    46-
    LiteralHeaderModal()
    47-
    }
    Lines changed: 17 additions & 20 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,27 +1,29 @@
    11
    import SwiftData
    22
    import SwiftUI
    33

    4-
    struct LiteralHeadersSection: View {
    5-
    @AppStorage("UseLiteralHeaders") private var useLiteralHeaders = false
    6-
    @Environment(\.modelContext) private var modelContext
    4+
    struct LiteralHeadersSection<VPN: VPNService>: View {
    5+
    @EnvironmentObject var vpn: VPN
    6+
    @EnvironmentObject var settings: Settings
    77

    8-
    @State private var selectedHeader: PersistentIdentifier?
    8+
    @State private var selectedHeader: LiteralHeader.ID?
    99
    @State private var editingHeader: LiteralHeader?
    1010
    @State private var addingNewHeader = false
    11-
    @Query private var headers: [LiteralHeader]
    11+
    12+
    let inspection = 10000 Inspection<Self>()
    1213

    1314
    var body: some View {
    1415
    Section {
    15-
    Toggle(isOn: $useLiteralHeaders) {
    16+
    Toggle(isOn: settings.$useLiteralHeaders) {
    1617
    Text("HTTP Headers")
    1718
    Text("When enabled, these headers will be included on all outgoing HTTP requests.")
    19+
    if vpn.state != .disabled { Text("Cannot be modified while Coder VPN is enabled.") }
    1820
    }
    1921
    .controlSize(.large)
    2022

    21-
    Table(headers, selection: $selectedHeader) {
    23+
    Table(settings.literalHeaders, selection: $selectedHeader) {
    2224
    TableColumn("Header", value: \.header)
    2325
    TableColumn("Value", value: \.value)
    24-
    }.opacity(useLiteralHeaders ? 1 : 0.5)
    26+
    }.opacity(settings.useLiteralHeaders ? 1 : 0.5)
    2527
    .frame(minWidth: 400, minHeight: 200)
    2628
    .padding(.bottom, 25)
    2729
    .overlay(alignment: .bottom) {
    @@ -36,7 +38,8 @@ struct LiteralHeadersSection: View {
    3638
    }
    3739
    Divider()
    3840
    Button {
    39-
    removeSelection()
    41+
    settings.literalHeaders.removeAll { $0.id == selectedHeader }
    42+
    selectedHeader = nil
    4043
    } label: {
    4144
    Image(systemName: "minus")
    4245
    .frame(width: 24, height: 24)
    @@ -48,13 +51,13 @@ struct LiteralHeadersSection: View {
    4851
    .fixedSize(horizontal: false, vertical: true)
    4952
    }
    5053
    .background(.primary.opacity(0.04))
    51-
    .contextMenu(forSelectionType: PersistentIdentifier.self, menu: { _ in },
    54+
    .contextMenu(forSelectionType: LiteralHeader.ID.self, menu: { _ in },
    5255
    primaryAction: { selectedHeaders in
    5356
    if let firstHeader = selectedHeaders.first {
    54-
    editingHeader = headers.first(where: { $0.id == firstHeader })
    57+
    editingHeader = settings.literalHeaders.first(where: { $0.id == firstHeader })
    5558
    }
    5659
    })
    57-
    .disabled(!useLiteralHeaders)
    60+
    .disabled(!settings.useLiteralHeaders)
    5861
    }
    5962
    .sheet(isPresented: $addingNewHeader) {
    6063
    LiteralHeaderModal()
    @@ -63,13 +66,7 @@ struct LiteralHeadersSection: View {
    6366
    LiteralHeaderModal(existingHeader: header)
    6467
    }.onTapGesture {
    6568
    selectedHeader = nil
    66-
    }
    67-
    }
    68-
    69-
    func removeSelection() {
    70-
    if let selectedHeader, let header = headers.first(where: { $0.id == selectedHeader }) {
    71-
    modelContext.delete(header)
    72-
    self.selectedHeader = nil
    73-
    }
    69+
    }.disabled(vpn.state != .disabled)
    70+
    .onReceive(inspection.notice) { self.inspection.visit(self, $0) } // ViewInspector
    7471
    }
    7572
    }
    Lines changed: 3 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,15 +1,15 @@
    11
    import SwiftData
    22
    import SwiftUI
    33

    4-
    struct NetworkTab: View {
    4+
    struct NetworkTab<VPN: VPNService>: View {
    55
    var body: some View {
    66
    Form {
    7-
    LiteralHeadersSection()
    7+
    LiteralHeadersSection<VPN>()
    88
    }
    99
    .formStyle(.grouped)
    1010
    }
    1111
    }
    1212

    1313
    #Preview {
    14-
    NetworkTab()
    14+
    NetworkTab<PreviewVPN>()
    1515
    }

    Coder Desktop/Coder Desktop/Views/Settings/Settings.swift

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,6 @@
    11
    import SwiftUI
    22

    3-
    struct SettingsView: View {
    3+
    struct SettingsView<VPN: VPNService>: View {
    44
    @AppStorage("SettingsSelectedIndex") private var selection: SettingsTab = .general
    55

    66
    var body: some View {
    @@ -9,7 +9,7 @@ struct SettingsView: View {
    99
    .tabItem {
    1010
    Label("General", systemImage: "gearshape")
    1111
    }.tag(SettingsTab.general)
    12-
    NetworkTab()
    12+
    NetworkTab<VPN>()
    1313
    .tabItem {
    1414
    Label("Network", systemImage: "dot.radiowaves.left.and.right")
    1515
    }.tag(SettingsTab.network)

    0 commit comments

    Comments
     (0)
    0