Skip to content

Commit

Permalink
Allow editing of OpenVPN endpoints (#335)
Browse files Browse the repository at this point in the history
Hosts only:

- Add new
- Edit/delete existing
- Reorder

Closes #206
  • Loading branch information
keeshux authored Jul 23, 2023
1 parent e0dbca2 commit 6ede6f0
Show file tree
Hide file tree
Showing 10 changed files with 322 additions and 55 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- OpenVPN: Allow editing of endpoints. [#335](https://github.com/passepartoutvpn/passepartout-apple/pull/335)

### Changed

- OpenVPN: Endpoint UX. [#332](https://github.com/passepartoutvpn/passepartout-apple/pull/332)
Expand Down
4 changes: 4 additions & 0 deletions Passepartout.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
A3A7CC4A28790BD900172D7D /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC4928790BD900172D7D /* Theme.swift */; };
A3A7CC56287D56E800172D7D /* ProviderLocationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC55287D56E800172D7D /* ProviderLocationItem.swift */; };
A3A7CC58287D576400172D7D /* ProviderLocationItem+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3A7CC57287D576400172D7D /* ProviderLocationItem+ViewModel.swift */; };
A3D5B04C2A6C6CF2008016D5 /* EndpointView+Add.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3D5B04B2A6C6CF2008016D5 /* EndpointView+Add.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -523,6 +524,7 @@
A3A7CC4928790BD900172D7D /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
A3A7CC55287D56E800172D7D /* ProviderLocationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderLocationItem.swift; sourceTree = "<group>"; };
A3A7CC57287D576400172D7D /* ProviderLocationItem+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProviderLocationItem+ViewModel.swift"; sourceTree = "<group>"; };
A3D5B04B2A6C6CF2008016D5 /* EndpointView+Add.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EndpointView+Add.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -651,6 +653,7 @@
0E49F6BA27D7638300385834 /* EndpointAdvancedView+OpenVPN.swift */,
0E49F6BC27D7639000385834 /* EndpointAdvancedView+WireGuard.swift */,
0E71ACEA27C1060D00F85C4B /* EndpointView.swift */,
A3D5B04B2A6C6CF2008016D5 /* EndpointView+Add.swift */,
0E5349C527C176C200C71BB3 /* EndpointView+OpenVPN.swift */,
0E5349C727C176D100C71BB3 /* EndpointView+WireGuard.swift */,
0EB90CC029C25BBD00E64628 /* InteractiveConnectionView.swift */,
Expand Down Expand Up @@ -1458,6 +1461,7 @@
0EBC075D27EC529000208AD9 /* DebugLog+Constants.swift in Sources */,
0E3CD47F280DA14B007075C0 /* AddProfileMenu.swift in Sources */,
0EB17EAA27D226C900D473B5 /* Constants+App.swift in Sources */,
A3D5B04C2A6C6CF2008016D5 /* EndpointView+Add.swift in Sources */,
0E3B7FD627E5173A00C66F13 /* ProfileView+VPN.swift in Sources */,
0ED89C1E27DE3F8D008B36D6 /* IntentAddView.swift in Sources */,
0E5468002867AC9A00F74D1C /* MacUtils.swift in Sources */,
Expand Down
9 changes: 7 additions & 2 deletions Passepartout/App/Constants/Theme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ extension View {
tint(themePrimaryBackgroundColor)
}

func themeDestructiveTintStyle() -> some View {
tint(themeErrorColor)
}

func themeTextButtonStyle() -> some View {
accentColor(.primary)
}
Expand Down Expand Up @@ -536,8 +540,9 @@ extension View {
.themeRawTextStyle()
}

func themeValidSocketPort() -> some View {
keyboardType(.numberPad)
func themeValidSocketPort(_ port: String?) -> some View {
themeValidating(port, validator: Validators.socketPort)
.keyboardType(.numberPad)
}

func themeValidDomainName(_ domainName: String?) -> some View {
Expand Down
4 changes: 2 additions & 2 deletions Passepartout/App/L10n/TunnelKit+L10n.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ extension IPv6Settings: StyledLocalizableEntity {

extension IPv4Settings.Route: LocalizableEntity {
public var localizedDescription: String {
"\(destination)/\(mask) -> \(gateway ?? "*")"
"\(destination)/\(mask) \(gateway ?? "*")"
}
}

extension IPv6Settings.Route: LocalizableEntity {
public var localizedDescription: String {
"\(destination)/\(prefixLength) -> \(gateway ?? "*")"
"\(destination)/\(prefixLength) \(gateway ?? "*")"
}
}
113 changes: 113 additions & 0 deletions Passepartout/App/Views/EndpointView+Add.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// EndpointView+Add.swift
// Passepartout
//
// Created by Davide De Rosa on 7/22/23.
// Copyright (c) 2023 Davide De Rosa. All rights reserved.
//
// https://github.com/passepartoutvpn
//
// This file is part of Passepartout.
//
// Passepartout is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Passepartout is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
//

import PassepartoutLibrary
import SwiftUI
import TunnelKitCore

extension EndpointView {
struct AddView: View {
@Environment(\.presentationMode) private var presentationMode

private let title: String

private let endpoint: Endpoint?

private let onSave: ((Endpoint, Endpoint?) -> Void)?

@State private var socketType: SocketType = .udp

@State private var address = ""

@State private var port = ""

@State private var didAppear = false

private let allSocketTypes: [SocketType] = [
.udp,
.udp4,
.udp6,
.tcp,
.tcp4,
.tcp6
]

init(_ title: String, endpoint: Endpoint? = nil, onSave: ((Endpoint, Endpoint?) -> Void)? = nil) {
self.title = title
self.endpoint = endpoint
self.onSave = onSave
}

var body: some View {
List {
Section {
themeTextPicker(
L10n.Global.Strings.protocol,
selection: $socketType,
values: allSocketTypes,
description: \.rawValue
)
TextField(L10n.Global.Strings.address, text: $address, onCommit: commitChanges)
.themeValidIPAddress(address)
TextField(L10n.Global.Strings.port, text: $port, onCommit: commitChanges)
.themeValidSocketPort(port)
}
}.onAppear {
guard !didAppear, let endpoint else {
return
}
socketType = endpoint.proto.socketType
address = endpoint.address
port = String(endpoint.proto.port)
didAppear = true
}.themeSecondaryView()
.navigationTitle(title)
.toolbar {
themeCloseItem(presentationMode: presentationMode)
ToolbarItem(placement: .primaryAction) {
Button(action: commitChanges, label: themeSaveButtonLabel)
}
}
}
}
}

// MARK: -

private extension EndpointView.AddView {
}

// MARK: -

private extension EndpointView.AddView {
func commitChanges() {
let endpointString = "\(address):\(socketType.rawValue):\(port)"
guard let newEndpoint = Endpoint(rawValue: endpointString) else {
return
}
onSave?(newEndpoint, endpoint)
presentationMode.wrappedValue.dismiss()
}
}
Loading

0 comments on commit 6ede6f0

Please sign in to comment.