Allow any character in host profile name

Fixes #26
This commit is contained in:
Davide De Rosa 2020-02-28 18:32:04 +01:00
parent c51e578e53
commit 7db0bb0d48
8 changed files with 74 additions and 45 deletions

View File

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## 1.11.0 Beta 2276 (2020-02-27)
### Changed
- Allow any character in host profile name. [#26](https://github.com/passepartoutvpn/passepartout-ios/issues/26)
### Fixed
- Programming error in some SoftEther negotiation (Grivus). [tunnelkit#143](https://github.com/passepartoutvpn/tunnelkit/pull/143)

View File

@ -208,7 +208,7 @@ class ProductManager: NSObject {
log.debug("Checking 'Unlimited hosts'")
if !isEligible(forFeature: .unlimitedHosts) {
let ids = service.currentHostNames()
let ids = service.hostIds()
if ids.count > AppConstants.InApp.limitedNumberOfHosts {
for id in ids {
service.removeProfile(ProfileKey(.host, id))
@ -219,7 +219,7 @@ class ProductManager: NSObject {
}
log.debug("Checking providers")
for name in service.currentProviderNames() {
for name in service.providerNames() {
guard let metadata = InfrastructureFactory.shared.metadata(forName: name) else {
continue
}
@ -246,7 +246,7 @@ class ProductManager: NSObject {
extension ConnectionService {
var hasReachedMaximumNumberOfHosts: Bool {
let numberOfHosts = currentHostNames().count
let numberOfHosts = hostIds().count
return numberOfHosts >= AppConstants.InApp.limitedNumberOfHosts
}
}

View File

@ -60,6 +60,7 @@ class ConfigurationViewController: UIViewController, StrongTableHost {
// sections
if isEditable {
model.add(.reset)
model.setHeader("", forSection: .reset)
}
if !isServerPushed {
model.add(.tls)

View File

@ -85,8 +85,8 @@ class OrganizerViewController: UITableViewController, StrongTableHost {
//
providers = service.currentProviderNames().sorted()
hosts = service.currentHostNames().sortedCaseInsensitive()
providers = service.sortedProviderNames()
hosts = service.sortedHostIds()
var providerRows = [RowType](repeating: .profile, count: providers.count)
var hostRows = [RowType](repeating: .profile, count: hosts.count)
@ -467,11 +467,10 @@ extension OrganizerViewController {
if rowProfile.context == .provider {
let metadata = InfrastructureFactory.shared.metadata(forName: rowProfile.id)
cell.imageView?.image = metadata?.logo
cell.leftText = metadata?.description ?? rowProfile.id
} else {
cell.imageView?.image = nil
cell.leftText = rowProfile.id
}
cell.leftText = service.screenTitle(rowProfile)
cell.rightText = service.isActiveProfile(rowProfile) ? L10n.Core.Organizer.Cells.Profile.Value.current : nil
return cell
@ -693,7 +692,7 @@ extension OrganizerViewController: ConnectionServiceDelegate {
perform(segue: StoryboardSegue.Organizer.selectProfileSegueIdentifier, sender: profile)
}
func connectionService(didRename oldProfile: ConnectionProfile, to newProfile: ConnectionProfile) {
func connectionService(didRename profile: ConnectionProfile, to newTitle: String) {
TransientStore.shared.serialize(withProfiles: false) // rename
reloadModel()

View File

@ -34,9 +34,7 @@ private let log = SwiftyBeaver.self
class WizardHostViewController: UITableViewController, StrongTableHost {
@IBOutlet private weak var itemNext: UIBarButtonItem!
private let existingHosts: [String] = {
return TransientStore.shared.service.currentHostNames().sortedCaseInsensitive()
}()
private let existingHostIds = TransientStore.shared.service.sortedHostIds()
var parsingResult: OpenVPN.ConfigurationParser.Result? {
didSet {
@ -47,19 +45,23 @@ class WizardHostViewController: UITableViewController, StrongTableHost {
var removesConfigurationOnCancel = false
private var createdProfile: HostConnectionProfile?
private var createdTitle: String?
private var replacedProfile: ConnectionProfile?
// MARK: StrongTableHost
lazy var model: StrongTableModel<SectionType, RowType> = {
let model: StrongTableModel<SectionType, RowType> = StrongTableModel()
model.add(.meta)
model.setFooter(L10n.Core.Global.Host.TitleInput.message, forSection: .meta)
if !existingHosts.isEmpty {
// model.setFooter(L10n.Core.Global.Host.TitleInput.message, forSection: .meta)
if !existingHostIds.isEmpty {
model.add(.existing)
model.setHeader(L10n.App.Wizards.Host.Sections.Existing.header, forSection: .existing)
}
model.set([.titleInput], forSection: .meta)
model.set(.existingHost, count: existingHosts.count, forSection: .existing)
model.set(.existingHost, count: existingHostIds.count, forSection: .existing)
return model
}()
@ -104,26 +106,28 @@ class WizardHostViewController: UITableViewController, StrongTableHost {
return
}
let profile = HostConnectionProfile(title: enteredTitle, hostname: hostname)
let profile = HostConnectionProfile(hostname: hostname)
let builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration: result.configuration)
profile.parameters = builder.build()
let service = TransientStore.shared.service
guard !service.containsProfile(profile) else {
let replacedProfile = service.profile(withContext: profile.context, id: profile.id)
replacedProfile = nil
if let existingHostId = service.existingHostId(withTitle: enteredTitle) {
replacedProfile = service.profile(withContext: profile.context, id: existingHostId)
let alert = UIAlertController.asAlert(title, L10n.Core.Wizards.Host.Alerts.Existing.message)
alert.addPreferredAction(L10n.Core.Global.ok) {
self.next(withProfile: profile, replacedProfile: replacedProfile)
self.next(withProfile: profile, title: enteredTitle)
}
alert.addCancelAction(L10n.Core.Global.cancel)
present(alert, animated: true, completion: nil)
return
}
next(withProfile: profile, replacedProfile: nil)
next(withProfile: profile, title: enteredTitle)
}
private func next(withProfile profile: HostConnectionProfile, replacedProfile: ConnectionProfile?) {
private func next(withProfile profile: HostConnectionProfile, title: String) {
createdProfile = profile
createdTitle = title
let accountVC = StoryboardScene.Main.accountIdentifier.instantiate()
if let replacedProfile = replacedProfile {
@ -134,7 +138,7 @@ class WizardHostViewController: UITableViewController, StrongTableHost {
}
private func finish(withCredentials credentials: Credentials) {
guard let profile = createdProfile else {
guard let profile = createdProfile, let title = createdTitle else {
fatalError("No profile created?")
}
let service = TransientStore.shared.service
@ -150,7 +154,10 @@ class WizardHostViewController: UITableViewController, StrongTableHost {
}
}
dismiss(animated: true) {
service.addOrReplaceProfile(profile, credentials: credentials)
if let replacedProfile = self.replacedProfile {
service.removeProfile(ProfileKey(replacedProfile))
}
service.addOrReplaceProfile(profile, credentials: credentials, title: title)
}
}
@ -206,15 +213,15 @@ extension WizardHostViewController {
let cell = Cells.field.dequeue(from: tableView, for: indexPath)
cell.caption = L10n.App.Wizards.Host.Cells.TitleInput.caption
cell.captionWidth = 100.0
cell.allowedCharset = .filename
// cell.allowedCharset = .filename
cell.field.applyProfileId(.current)
cell.delegate = self
return cell
case .existingHost:
let hostTitle = existingHosts[indexPath.row]
let existingTitle = hostTitle(at: indexPath.row)
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
cell.leftText = hostTitle
cell.leftText = existingTitle
cell.accessoryType = .none
cell.isTappable = true
return cell
@ -227,15 +234,19 @@ extension WizardHostViewController {
guard let titleIndexPath = model.indexPath(forRow: .titleInput, ofSection: .meta) else {
fatalError("Could not found title cell?")
}
let hostTitle = existingHosts[indexPath.row]
let existingTitle = hostTitle(at: indexPath.row)
let cellTitle = tableView.cellForRow(at: titleIndexPath) as? FieldTableViewCell
cellTitle?.field.text = hostTitle
cellTitle?.field.text = existingTitle
tableView.deselectRow(at: indexPath, animated: true)
default:
break
}
}
private func hostTitle(at row: Int) -> String {
return TransientStore.shared.service.screenTitle(forHostId: existingHostIds[row])
}
}
// MARK: -

View File

@ -79,7 +79,11 @@ class ServiceViewController: UIViewController, StrongTableHost {
self.profile = profile
vpn.profile = profile
title = profile?.screenTitle
if let profile = profile {
title = service.screenTitle(ProfileKey(profile))
} else {
title = nil
}
navigationItem.rightBarButtonItem = (profile?.context == .host) ? itemEdit : nil
if reloadingViews {
reloadModel()
@ -230,34 +234,36 @@ class ServiceViewController: UIViewController, StrongTableHost {
}
@IBAction private func renameProfile() {
let alert = UIAlertController.asAlert(L10n.Core.Service.Alerts.Rename.title, L10n.Core.Global.Host.TitleInput.message)
let alert = UIAlertController.asAlert(L10n.Core.Service.Alerts.Rename.title, nil)
alert.addTextField { (field) in
field.text = self.profile?.id
field.text = self.service.screenTitle(ProfileKey(self.uncheckedProfile))
field.applyProfileId(.current)
field.delegate = self
}
pendingRenameAction = alert.addPreferredAction(L10n.Core.Global.ok) {
guard let newId = alert.textFields?.first?.text else {
guard let newTitle = alert.textFields?.first?.text else {
return
}
self.doRenameCurrentProfile(to: newId)
self.doRenameCurrentProfile(to: newTitle)
}
alert.addCancelAction(L10n.Core.Global.cancel)
pendingRenameAction?.isEnabled = false
present(alert, animated: true, completion: nil)
}
private func doRenameCurrentProfile(to newId: String) {
guard let renamedProfile = service.renameProfile(uncheckedHostProfile, to: newId) else {
private func doRenameCurrentProfile(to newTitle: String) {
guard let profile = profile else {
return
}
setProfile(renamedProfile, reloadingViews: false)
service.renameProfile(profile, to: newTitle)
setProfile(profile, reloadingViews: false)
}
private func toggleVpnService(cell: ToggleTableViewCell) {
if cell.isOn {
if #available(iOS 12, *) {
IntentDispatcher.donateConnection(with: uncheckedProfile)
let title = service.screenTitle(ProfileKey(uncheckedProfile))
IntentDispatcher.donateConnection(with: uncheckedProfile, title: title)
}
guard !service.needsCredentials(for: uncheckedProfile) else {
let alert = UIAlertController.asAlert(
@ -1424,7 +1430,8 @@ extension ServiceViewController: ProviderPoolViewControllerDelegate {
vpn.reinstallIfEnabled()
if #available(iOS 12, *) {
IntentDispatcher.donateConnection(with: uncheckedProviderProfile)
let title = service.screenTitle(forProviderName: uncheckedProviderProfile.name)
IntentDispatcher.donateConnection(with: uncheckedProviderProfile, title: title)
}
}

View File

@ -33,7 +33,7 @@ import Convenience
class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewControllerDelegate, StrongTableHost {
private let service = TransientStore.shared.service
private var providers: [Infrastructure.Metadata] = []
private var providers: [Infrastructure.Name] = []
private var hosts: [String] = []
@ -51,8 +51,8 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
}()
func reloadModel() {
providers = service.currentProviderMetadata().sorted()
hosts = service.currentHostNames().sortedCaseInsensitive()
providers = service.sortedProviderNames()
hosts = service.sortedHostIds()
if !providers.isEmpty {
model.add(.providers)
@ -124,10 +124,16 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
let cell = Cells.setting.dequeue(from: tableView, for: indexPath)
switch model.row(at: indexPath) {
case .providerShortcut:
cell.leftText = providers[indexPath.row].description
let name = providers[indexPath.row]
if let metadata = InfrastructureFactory.shared.metadata(forName: name) {
cell.leftText = metadata.description
} else {
cell.leftText = name
}
case .hostShortcut:
cell.leftText = hosts[indexPath.row]
let id = hosts[indexPath.row]
cell.leftText = service.screenTitle(forHostId: id)
}
return cell
}
@ -135,7 +141,7 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch model.row(at: indexPath) {
case .providerShortcut:
selectedProfile = service.profile(withContext: .provider, id: providers[indexPath.row].name)
selectedProfile = service.profile(withContext: .provider, id: providers[indexPath.row])
pickProviderLocation()
case .hostShortcut:
@ -150,7 +156,8 @@ class ShortcutsConnectToViewController: UITableViewController, ProviderPoolViewC
guard let host = selectedProfile as? HostConnectionProfile else {
fatalError("Not a HostConnectionProfile")
}
addShortcut(with: IntentDispatcher.intentConnect(profile: host))
let title = service.screenTitle(forHostId: host.id)
addShortcut(with: IntentDispatcher.intentConnect(profile: host, title: title))
}
private func addMoveToLocation(pool: Pool) {

@ -1 +1 @@
Subproject commit 872f827c80ab3a94565edb3db3ae8af5ec619d41
Subproject commit d3f2702639049d95a4c52bcf0368ce54b027cff7