parent
c51e578e53
commit
7db0bb0d48
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ class ConfigurationViewController: UIViewController, StrongTableHost {
|
|||
// sections
|
||||
if isEditable {
|
||||
model.add(.reset)
|
||||
model.setHeader("", forSection: .reset)
|
||||
}
|
||||
if !isServerPushed {
|
||||
model.add(.tls)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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: -
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue