Tunnel detail: Start off with the tunnel detail view
Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
parent
88c7657eb7
commit
c14d816b87
|
@ -9,6 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
|
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
|
||||||
6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3E217F3413003482A3 /* DNSServer.swift */; };
|
6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3E217F3413003482A3 /* DNSServer.swift */; };
|
||||||
|
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; };
|
||||||
6F693A562179E556008551C1 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F693A552179E556008551C1 /* Endpoint.swift */; };
|
6F693A562179E556008551C1 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F693A552179E556008551C1 /* Endpoint.swift */; };
|
||||||
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774DF217181B1006A79B3 /* MainViewController.swift */; };
|
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774DF217181B1006A79B3 /* MainViewController.swift */; };
|
||||||
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E0217181B1006A79B3 /* AppDelegate.swift */; };
|
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E0217181B1006A79B3 /* AppDelegate.swift */; };
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = "<group>"; };
|
6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = "<group>"; };
|
||||||
6F628C3E217F3413003482A3 /* DNSServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; };
|
6F628C3E217F3413003482A3 /* DNSServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; };
|
||||||
|
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; };
|
||||||
6F693A552179E556008551C1 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
|
6F693A552179E556008551C1 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
|
||||||
6F7774DF217181B1006A79B3 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
6F7774DF217181B1006A79B3 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
||||||
6F7774E0217181B1006A79B3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
6F7774E0217181B1006A79B3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
@ -70,6 +72,7 @@
|
||||||
6F7774DF217181B1006A79B3 /* MainViewController.swift */,
|
6F7774DF217181B1006A79B3 /* MainViewController.swift */,
|
||||||
6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */,
|
6F7774E321718281006A79B3 /* TunnelsListTableViewController.swift */,
|
||||||
6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */,
|
6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */,
|
||||||
|
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */,
|
||||||
);
|
);
|
||||||
path = iOS;
|
path = iOS;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -216,6 +219,7 @@
|
||||||
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */,
|
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */,
|
||||||
6F7774EA217229DB006A79B3 /* IPAddressRange.swift in Sources */,
|
6F7774EA217229DB006A79B3 /* IPAddressRange.swift in Sources */,
|
||||||
6F7774E82172020C006A79B3 /* Configuration.swift in Sources */,
|
6F7774E82172020C006A79B3 /* Configuration.swift in Sources */,
|
||||||
|
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */,
|
||||||
6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */,
|
6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */,
|
||||||
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */,
|
6F7774E1217181B1006A79B3 /* MainViewController.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
//
|
||||||
|
// TunnelDetailTableViewController.swift
|
||||||
|
// WireGuard
|
||||||
|
//
|
||||||
|
// Created by Roopesh Chander on 17/10/18.
|
||||||
|
// Copyright © 2018 Roopesh Chander. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
// MARK: TunnelDetailTableViewController
|
||||||
|
|
||||||
|
class TunnelDetailTableViewController: UITableViewController {
|
||||||
|
|
||||||
|
let interfaceFieldsBySection: [[TunnelViewModel.InterfaceField]] = [
|
||||||
|
[.name],
|
||||||
|
[.publicKey, .copyPublicKey],
|
||||||
|
[.addresses, .listenPort, .mtu, .dns]
|
||||||
|
]
|
||||||
|
|
||||||
|
let peerFieldsBySection: [[TunnelViewModel.PeerField]] = [
|
||||||
|
[.publicKey, .preSharedKey, .endpoint,
|
||||||
|
.allowedIPs, .persistentKeepAlive]
|
||||||
|
]
|
||||||
|
|
||||||
|
let tunnelsManager: TunnelsManager
|
||||||
|
let tunnelViewModel: TunnelViewModel
|
||||||
|
|
||||||
|
init(tunnelsManager tm: TunnelsManager, tunnelConfiguration: TunnelConfiguration) {
|
||||||
|
tunnelsManager = tm
|
||||||
|
tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnelConfiguration)
|
||||||
|
super.init(style: .grouped)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
self.title = tunnelViewModel.interfaceData[.name]
|
||||||
|
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(editTapped))
|
||||||
|
|
||||||
|
self.tableView.rowHeight = 44
|
||||||
|
self.tableView.register(TunnelDetailTableViewKeyValueCell.self, forCellReuseIdentifier: TunnelDetailTableViewKeyValueCell.id)
|
||||||
|
self.tableView.register(TunnelDetailTableViewButtonCell.self, forCellReuseIdentifier: TunnelDetailTableViewButtonCell.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func editTapped() {
|
||||||
|
print("Edit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: UITableViewDataSource
|
||||||
|
|
||||||
|
extension TunnelDetailTableViewController {
|
||||||
|
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||||
|
let numberOfPeerSections = peerFieldsBySection.count
|
||||||
|
let numberOfPeers = tunnelViewModel.peersData.count
|
||||||
|
|
||||||
|
return numberOfInterfaceSections + (numberOfPeers * numberOfPeerSections) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||||
|
let numberOfPeerSections = peerFieldsBySection.count
|
||||||
|
let numberOfPeers = tunnelViewModel.peersData.count
|
||||||
|
|
||||||
|
if (section < numberOfInterfaceSections) {
|
||||||
|
// Interface
|
||||||
|
return interfaceFieldsBySection[section].count
|
||||||
|
} else if ((numberOfPeers > 0) && (section < (numberOfInterfaceSections + numberOfPeers * numberOfPeerSections))) {
|
||||||
|
// Peer
|
||||||
|
let fieldIndex = (section - numberOfInterfaceSections) % numberOfPeerSections
|
||||||
|
return peerFieldsBySection[fieldIndex].count
|
||||||
|
} else {
|
||||||
|
// Add peer
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||||
|
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||||
|
let numberOfPeerSections = peerFieldsBySection.count
|
||||||
|
let numberOfPeers = tunnelViewModel.peersData.count
|
||||||
|
|
||||||
|
if (section < numberOfInterfaceSections) {
|
||||||
|
// Interface
|
||||||
|
return (section == 0) ? "Interface" : nil
|
||||||
|
} else if ((numberOfPeers > 0) && (section < (numberOfInterfaceSections + numberOfPeers * numberOfPeerSections))) {
|
||||||
|
// Peer
|
||||||
|
let fieldIndex = (section - numberOfInterfaceSections) % numberOfPeerSections
|
||||||
|
return (fieldIndex == 0) ? "Peer" : nil
|
||||||
|
} else {
|
||||||
|
// Add peer
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let numberOfInterfaceSections = interfaceFieldsBySection.count
|
||||||
|
let numberOfPeerSections = peerFieldsBySection.count
|
||||||
|
let numberOfPeers = tunnelViewModel.peersData.count
|
||||||
|
|
||||||
|
let section = indexPath.section
|
||||||
|
let row = indexPath.row
|
||||||
|
|
||||||
|
if (section < numberOfInterfaceSections) {
|
||||||
|
// Interface
|
||||||
|
let interfaceData = tunnelViewModel.interfaceData
|
||||||
|
let field = interfaceFieldsBySection[section][row]
|
||||||
|
if (field == .copyPublicKey) {
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelDetailTableViewButtonCell.id, for: indexPath) as! TunnelDetailTableViewButtonCell
|
||||||
|
cell.buttonText = field.rawValue
|
||||||
|
cell.onTapped = {
|
||||||
|
print("Copying public key is unimplemented") // TODO
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
} else {
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelDetailTableViewKeyValueCell.id, for: indexPath) as! TunnelDetailTableViewKeyValueCell
|
||||||
|
// Set key and value
|
||||||
|
cell.key = field.rawValue
|
||||||
|
cell.value = interfaceData[field]
|
||||||
|
if (field != .publicKey) {
|
||||||
|
cell.detailTextLabel?.allowsDefaultTighteningForTruncation = true
|
||||||
|
cell.detailTextLabel?.adjustsFontSizeToFitWidth = true
|
||||||
|
cell.detailTextLabel?.minimumScaleFactor = 0.85
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
} else if ((numberOfPeers > 0) && (section < (numberOfInterfaceSections + numberOfPeers * numberOfPeerSections))) {
|
||||||
|
// Peer
|
||||||
|
let peerIndex = Int((section - numberOfInterfaceSections) / numberOfPeerSections)
|
||||||
|
let peerSectionIndex = (section - numberOfInterfaceSections) % numberOfPeerSections
|
||||||
|
let peerData = tunnelViewModel.peersData[peerIndex]
|
||||||
|
let field = peerFieldsBySection[peerSectionIndex][row]
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelDetailTableViewKeyValueCell.id, for: indexPath) as! TunnelDetailTableViewKeyValueCell
|
||||||
|
// Set key and value
|
||||||
|
cell.key = field.rawValue
|
||||||
|
cell.value = peerData[field]
|
||||||
|
if (field != .publicKey && field != .preSharedKey) {
|
||||||
|
cell.detailTextLabel?.allowsDefaultTighteningForTruncation = true
|
||||||
|
cell.detailTextLabel?.adjustsFontSizeToFitWidth = true
|
||||||
|
cell.detailTextLabel?.minimumScaleFactor = 0.85
|
||||||
|
}
|
||||||
|
|
||||||
|
return cell
|
||||||
|
} else {
|
||||||
|
assert(section == (numberOfInterfaceSections + numberOfPeers * numberOfPeerSections))
|
||||||
|
// Delete configuration
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: TunnelDetailTableViewButtonCell.id, for: indexPath) as! TunnelDetailTableViewButtonCell
|
||||||
|
cell.buttonText = "Delete tunnel"
|
||||||
|
cell.onTapped = {
|
||||||
|
print("Delete peer unimplemented")
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TunnelDetailTableViewKeyValueCell: UITableViewCell {
|
||||||
|
static let id: String = "TunnelDetailTableViewKeyValueCell"
|
||||||
|
var key: String {
|
||||||
|
get { return textLabel?.text ?? "" }
|
||||||
|
set(value) { textLabel?.text = value }
|
||||||
|
}
|
||||||
|
var value: String {
|
||||||
|
get { return detailTextLabel?.text ?? "" }
|
||||||
|
set(value) { detailTextLabel?.text = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: .value1, reuseIdentifier: TunnelDetailTableViewKeyValueCell.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
super.prepareForReuse()
|
||||||
|
key = ""
|
||||||
|
value = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TunnelDetailTableViewButtonCell: UITableViewCell {
|
||||||
|
static let id: String = "TunnelsEditTableViewButtonCell"
|
||||||
|
var buttonText: String {
|
||||||
|
get { return button.title(for: .normal) ?? "" }
|
||||||
|
set(value) { button.setTitle(value, for: .normal) }
|
||||||
|
}
|
||||||
|
var onTapped: (() -> Void)? = nil
|
||||||
|
|
||||||
|
let button: UIButton
|
||||||
|
|
||||||
|
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||||
|
button = UIButton(type: .system)
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
contentView.addSubview(button)
|
||||||
|
button.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
|
||||||
|
button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor)
|
||||||
|
])
|
||||||
|
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func buttonTapped() {
|
||||||
|
onTapped?()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func prepareForReuse() {
|
||||||
|
buttonText = ""
|
||||||
|
onTapped = nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,6 +81,18 @@ extension TunnelsListTableViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: UITableViewDelegate
|
||||||
|
|
||||||
|
extension TunnelsListTableViewController {
|
||||||
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
guard let tunnelsManager = tunnelsManager else { return }
|
||||||
|
let tunnelConfiguration = tunnelsManager.tunnel(at: indexPath.row).tunnelProvider.tunnelConfiguration
|
||||||
|
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager,
|
||||||
|
tunnelConfiguration: tunnelConfiguration)
|
||||||
|
showDetailViewController(tunnelDetailVC, sender: self) // Shall get propagated up to the split-vc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: TunnelsManagerDelegate
|
// MARK: TunnelsManagerDelegate
|
||||||
|
|
||||||
extension TunnelsListTableViewController: TunnelsManagerDelegate {
|
extension TunnelsListTableViewController: TunnelsManagerDelegate {
|
||||||
|
|
Loading…
Reference in New Issue