2024-09-23 13:02:26 +00:00
|
|
|
//
|
|
|
|
// IPView+Route.swift
|
|
|
|
// Passepartout
|
|
|
|
//
|
|
|
|
// Created by Davide De Rosa on 8/20/24.
|
|
|
|
// Copyright (c) 2024 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 PassepartoutKit
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
extension IPView {
|
|
|
|
struct RouteView: View {
|
|
|
|
|
|
|
|
@EnvironmentObject
|
|
|
|
private var theme: Theme
|
|
|
|
|
|
|
|
let family: Address.Family
|
|
|
|
|
|
|
|
let onSubmit: (Route?) -> Void
|
|
|
|
|
|
|
|
@State
|
|
|
|
private var destinationString = ""
|
|
|
|
|
|
|
|
@State
|
|
|
|
private var gatewayString = ""
|
|
|
|
|
|
|
|
@State
|
|
|
|
private var isDefault = false
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
Form {
|
|
|
|
Section {
|
2024-11-23 19:31:22 +00:00
|
|
|
Toggle(Strings.Global.Nouns.default, isOn: $isDefault.animation(theme.animation(for: .modules)))
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
if !isDefault {
|
|
|
|
Section {
|
2024-11-23 19:31:22 +00:00
|
|
|
ThemeTextField(Strings.Global.Nouns.destination, text: $destinationString, placeholder: Strings.Unlocalized.Placeholders.ipDestination(forFamily: family))
|
|
|
|
ThemeTextField(Strings.Global.Nouns.gateway, text: $gatewayString, placeholder: Strings.Unlocalized.Placeholders.ipGateway(forFamily: family))
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.themeForm()
|
|
|
|
.toolbar {
|
|
|
|
ToolbarItem(placement: .cancellationAction) {
|
2024-11-23 19:31:22 +00:00
|
|
|
Button(Strings.Global.Actions.cancel, role: .cancel) {
|
2024-09-23 13:02:26 +00:00
|
|
|
onSubmit(nil)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ToolbarItem(placement: .confirmationAction) {
|
2024-11-23 19:31:22 +00:00
|
|
|
Button(Strings.Global.Nouns.ok, action: parseAndSubmit)
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
}
|
2024-10-03 22:42:09 +00:00
|
|
|
.themeNavigationDetail()
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private extension IPView.RouteView {
|
|
|
|
func parseAndSubmit() {
|
|
|
|
let route: Route
|
|
|
|
if isDefault {
|
|
|
|
route = Route(defaultWithGateway: nil)
|
|
|
|
} else {
|
|
|
|
guard let destination = Subnet(rawValue: destinationString) else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
let gateway = Address(rawValue: gatewayString)
|
|
|
|
guard destination.address.family == family else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if let gateway {
|
|
|
|
guard gateway.family == family else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
route = Route(destination, gateway)
|
|
|
|
}
|
|
|
|
onSubmit(route)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#Preview {
|
|
|
|
struct Preview: View {
|
|
|
|
|
|
|
|
@State
|
|
|
|
private var route: Route?
|
|
|
|
|
|
|
|
@State
|
|
|
|
private var isPresented = false
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
List {
|
|
|
|
Button("Add route") {
|
|
|
|
isPresented = true
|
|
|
|
}
|
2024-10-10 22:24:06 +00:00
|
|
|
.themeModal(isPresented: $isPresented) {
|
2024-09-23 13:02:26 +00:00
|
|
|
NavigationStack {
|
|
|
|
IPView.RouteView(family: .v4) {
|
|
|
|
route = $0
|
|
|
|
isPresented = false
|
|
|
|
}
|
|
|
|
.navigationTitle("Add route")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
route.map { route in
|
|
|
|
VStack {
|
|
|
|
route.destination.map {
|
|
|
|
Text("Destination")
|
2024-10-28 20:38:26 +00:00
|
|
|
.themeTrailingValue($0.rawValue)
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
route.gateway.map {
|
|
|
|
Text("Gateway")
|
2024-10-28 20:38:26 +00:00
|
|
|
.themeTrailingValue($0.rawValue)
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Preview()
|
2024-10-02 14:05:40 +00:00
|
|
|
.withMockEnvironment()
|
2024-09-23 13:02:26 +00:00
|
|
|
}
|