From e91f74df2d95054397cd2780483f498a4c41b65c Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 17 Jul 2023 09:36:58 +0200 Subject: [PATCH 1/8] vendor: update FloatingPanel to v2.6.3 --- IVPNClient.xcodeproj/project.pbxproj | 4 +- .../FloatingPanelController+Ext.swift | 3 +- .../FloatingPanelMainLayout.swift | 163 ++++++++++++++---- .../MainScreen/MainViewController+Ext.swift | 6 +- .../MainScreen/MainViewController.swift | 3 +- 5 files changed, 136 insertions(+), 43 deletions(-) diff --git a/IVPNClient.xcodeproj/project.pbxproj b/IVPNClient.xcodeproj/project.pbxproj index d422ef218..703f5a118 100644 --- a/IVPNClient.xcodeproj/project.pbxproj +++ b/IVPNClient.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 53; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -3324,7 +3324,7 @@ repositoryURL = "https://github.com/scenee/FloatingPanel"; requirement = { kind = exactVersion; - version = 1.7.2; + version = 2.6.3; }; }; 82EC884529A12D510024CC40 /* XCRemoteSwiftPackageReference "SnapKit" */ = { diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelController+Ext.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelController+Ext.swift index 5196bab9d..bfa23c373 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelController+Ext.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelController+Ext.swift @@ -27,8 +27,7 @@ import FloatingPanel extension FloatingPanelController { func setup() { - surfaceView.shadowHidden = true - surfaceView.contentInsets = .init(top: 20, left: 0, bottom: 0, right: 0) + surfaceView.contentPadding = .init(top: 20, left: 0, bottom: 0, right: 0) surfaceView.backgroundColor = UIColor.init(named: Theme.ivpnBackgroundPrimary) let contentViewController = NavigationManager.getControlPanelViewController() diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift index 01715b4cd..8272f954d 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift @@ -26,9 +26,9 @@ import FloatingPanel class FloatingPanelMainLayout: FloatingPanelLayout { - // MARK: - Override public properties - + var position: FloatingPanelPosition { .bottom } - public var initialPosition: FloatingPanelPosition { + var initialState: FloatingPanelState { if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { return .full } @@ -36,12 +36,11 @@ class FloatingPanelMainLayout: FloatingPanelLayout { return .half } - public var supportedPositions: Set { - if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { - return [.full] - } - - return [.full, .half] + var anchors: [FloatingPanelState: FloatingPanelLayoutAnchoring] { + return [ + .full: FloatingPanelLayoutAnchor(absoluteInset: 0, edge: .top, referenceGuide: .safeArea), + .half: FloatingPanelLayoutAnchor(absoluteInset: halfHeight, edge: .bottom, referenceGuide: .safeArea) + ] } // MARK: - Private properties - @@ -60,37 +59,19 @@ class FloatingPanelMainLayout: FloatingPanelLayout { return 230 - bottomSafeArea } - // MARK: - Override public methods - - - public func insetFor(position: FloatingPanelPosition) -> CGFloat? { - if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { - switch position { - case .full: - return -20 - default: - return nil - } - } - - switch position { - case .full: - return 10 - case .half: - return halfHeight - default: - return nil - } - } - public func prepareLayout(surfaceView: UIView, in view: UIView) -> [NSLayoutConstraint] { - if let surfaceView = surfaceView as? FloatingPanelSurfaceView { + if let surfaceView = surfaceView as? SurfaceView { + let appearance = SurfaceAppearance() + if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { surfaceView.grabberHandle.isHidden = true - surfaceView.cornerRadius = 0 + appearance.cornerRadius = 0 } else { surfaceView.grabberHandle.isHidden = false - surfaceView.cornerRadius = 15 + appearance.cornerRadius = 15 } + + surfaceView.appearance = appearance } if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { @@ -113,8 +94,8 @@ class FloatingPanelMainLayout: FloatingPanelLayout { ] } - public func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { - if position == .full && (UIDevice.current.userInterfaceIdiom == .phone || UIWindow.isPortrait) { + public func backdropAlpha(for state: FloatingPanelState) -> CGFloat { + if state == .full && (UIDevice.current.userInterfaceIdiom == .phone || UIWindow.isPortrait) { return 0.3 } @@ -122,3 +103,115 @@ class FloatingPanelMainLayout: FloatingPanelLayout { } } + +class MainFloatingPanelBehavior: FloatingPanelBehavior { + + func allowsRubberBanding(for edge: UIRectEdge) -> Bool { + return false + } + + func shouldProjectMomentum(_ fpc: FloatingPanelController, to proposedTargetPosition: FloatingPanelState) -> Bool { + return false + } + +} + +//class FloatingPanelMainLayout: FloatingPanelLayout { +// +// // MARK: - Override public properties - +// +// public var initialPosition: FloatingPanelPosition { +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { +// return .full +// } +// +// return .half +// } +// +// public var supportedPositions: Set { +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { +// return [.full] +// } +// +// return [.full, .half] +// } +// +// // MARK: - Private properties - +// +// private let bottomSafeArea = UIWindow.keyWindow?.safeAreaInsets.bottom ?? 0 +// +// private var halfHeight: CGFloat { +// if Application.shared.settings.connectionProtocol.tunnelType() != .ipsec && UserDefaults.shared.isMultiHop { +// return 359 - bottomSafeArea +// } +// +// if Application.shared.settings.connectionProtocol.tunnelType() != .ipsec { +// return 274 - bottomSafeArea +// } +// +// return 230 - bottomSafeArea +// } +// +// // MARK: - Override public methods - +// +// public func insetFor(position: FloatingPanelPosition) -> CGFloat? { +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { +// switch position { +// case .full: +// return -20 +// default: +// return nil +// } +// } +// +// switch position { +// case .full: +// return 10 +// case .half: +// return halfHeight +// default: +// return nil +// } +// } +// +// public func prepareLayout(surfaceView: UIView, in view: UIView) -> [NSLayoutConstraint] { +// if let surfaceView = surfaceView as? FloatingPanelSurfaceView { +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { +// surfaceView.grabberHandle.isHidden = true +// surfaceView.cornerRadius = 0 +// } else { +// surfaceView.grabberHandle.isHidden = false +// surfaceView.cornerRadius = 15 +// } +// } +// +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { +// return [ +// surfaceView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 0), +// surfaceView.widthAnchor.constraint(equalToConstant: 375) +// ] +// } +// +// if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isPortrait && !UIApplication.shared.isSplitOrSlideOver { +// return [ +// surfaceView.widthAnchor.constraint(equalToConstant: 520), +// surfaceView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor) +// ] +// } +// +// return [ +// surfaceView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 0), +// surfaceView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: 0) +// ] +// } +// +// public func backdropAlphaFor(position: FloatingPanelPosition) -> CGFloat { +// if position == .full && (UIDevice.current.userInterfaceIdiom == .phone || UIWindow.isPortrait) { +// return 0.3 +// } +// +// return 0 +// } +// +//} + diff --git a/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift b/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift index a6f43f1ec..ac69a0dd3 100644 --- a/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift +++ b/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift @@ -28,7 +28,7 @@ import FloatingPanel extension MainViewController: FloatingPanelControllerDelegate { - func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { + func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout { updateAccessibilityLabel(vc: vc) return FloatingPanelMainLayout() @@ -44,7 +44,7 @@ extension MainViewController: FloatingPanelControllerDelegate { func updateAccessibilityLabel(vc: FloatingPanelController) { if let controlPanelViewController = floatingPanel.contentViewController, UIDevice.current.userInterfaceIdiom != .pad { - if vc.position == .full { + if vc.state == .full { controlPanelViewController.view.accessibilityLabel = "Swipe down to collapse control panel" } else { controlPanelViewController.view.accessibilityLabel = "Swipe up to expan control panel" @@ -59,7 +59,7 @@ extension MainViewController: FloatingPanelControllerDelegate { extension MainViewController: UIAdaptivePresentationControllerDelegate { func presentationControllerWillDismiss(_ presentationController: UIPresentationController) { - floatingPanel.updateLayout() + floatingPanel.invalidateLayout() NotificationCenter.default.post(name: Notification.Name.UpdateControlPanel, object: nil) } diff --git a/IVPNClient/Scenes/MainScreen/MainViewController.swift b/IVPNClient/Scenes/MainScreen/MainViewController.swift index 0539f5e6b..c0c83d0e5 100644 --- a/IVPNClient/Scenes/MainScreen/MainViewController.swift +++ b/IVPNClient/Scenes/MainScreen/MainViewController.swift @@ -202,7 +202,7 @@ class MainViewController: UIViewController { // MARK: - Private methods - @objc private func updateFloatingPanelLayout() { - floatingPanel.updateLayout() + floatingPanel.invalidateLayout() mainView.setupView(animated: false) } @@ -237,6 +237,7 @@ class MainViewController: UIViewController { floatingPanel.delegate = self floatingPanel.addPanel(toParent: self) floatingPanel.show(animated: true) + floatingPanel.behavior = MainFloatingPanelBehavior() } private func startAPIUpdate() { From c9ba3571621e53729dd37dbe173277bdcb95e59d Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 17 Jul 2023 17:31:02 +0200 Subject: [PATCH 2/8] vendor: update FloatingPanelMainLayout.swift --- .../MainScreen/ControlPanel/FloatingPanelMainLayout.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift index 8272f954d..eb7680fb8 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift @@ -62,6 +62,10 @@ class FloatingPanelMainLayout: FloatingPanelLayout { public func prepareLayout(surfaceView: UIView, in view: UIView) -> [NSLayoutConstraint] { if let surfaceView = surfaceView as? SurfaceView { let appearance = SurfaceAppearance() + let shadow = SurfaceAppearance.Shadow() + shadow.color = .clear + appearance.shadows = [shadow] + appearance.backgroundColor = UIColor.init(named: Theme.ivpnBackgroundPrimary) if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { surfaceView.grabberHandle.isHidden = true From 63144cb686c6e3c8493e09637d558b2b6e7fef56 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 29 Sep 2023 09:04:45 +0200 Subject: [PATCH 3/8] refactor: update FloatingPanelControllerDelegate in MainViewController+Ext --- IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift b/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift index 975fbac50..72ecae325 100644 --- a/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift +++ b/IVPNClient/Scenes/MainScreen/MainViewController+Ext.swift @@ -52,6 +52,13 @@ extension MainViewController: FloatingPanelControllerDelegate { } } + func floatingPanelDidMove(_ fpc: FloatingPanelController) { + let loc = fpc.surfaceLocation + let minY = fpc.surfaceLocation(for: .full).y - 6.0 + let maxY = fpc.surfaceLocation(for: .half).y + 6.0 + fpc.surfaceLocation = CGPoint(x: loc.x, y: min(max(loc.y, minY), maxY)) + } + } // MARK: - UIAdaptivePresentationControllerDelegate - From dc67c3a00536b22fd78d3a270948237afe91a674 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 29 Sep 2023 09:31:07 +0200 Subject: [PATCH 4/8] refactor: update FloatingPanelMainLayout --- .../ControlPanel/FloatingPanelMainLayout.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift index f7bbd3896..aa55b1624 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/FloatingPanelMainLayout.swift @@ -26,7 +26,13 @@ import FloatingPanel class FloatingPanelMainLayout: FloatingPanelLayout { - var position: FloatingPanelPosition { .bottom } + var position: FloatingPanelPosition { + if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { + return .top + } + + return .bottom + } var initialState: FloatingPanelState { if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { @@ -37,6 +43,12 @@ class FloatingPanelMainLayout: FloatingPanelLayout { } var anchors: [FloatingPanelState: FloatingPanelLayoutAnchoring] { + if UIDevice.current.userInterfaceIdiom == .pad && UIWindow.isLandscape && !UIApplication.shared.isSplitOrSlideOver { + return [ + .full: FloatingPanelLayoutAnchor(absoluteInset: 0, edge: .bottom, referenceGuide: .superview) + ] + } + return [ .full: FloatingPanelLayoutAnchor(absoluteInset: 0, edge: .top, referenceGuide: .safeArea), .half: FloatingPanelLayoutAnchor(absoluteInset: halfHeight, edge: .bottom, referenceGuide: .safeArea) From f8462fefebfa97811477a226fb9e62178324ea66 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Fri, 29 Sep 2023 11:10:33 +0200 Subject: [PATCH 5/8] refactor: add showFloatingPanel method in MainViewController --- IVPNClient/Scenes/MainScreen/MainViewController.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/IVPNClient/Scenes/MainScreen/MainViewController.swift b/IVPNClient/Scenes/MainScreen/MainViewController.swift index ef79093e7..096097fd2 100644 --- a/IVPNClient/Scenes/MainScreen/MainViewController.swift +++ b/IVPNClient/Scenes/MainScreen/MainViewController.swift @@ -82,6 +82,9 @@ class MainViewController: UIViewController { refreshUI() initConnectionInfo() startPingService() + DispatchQueue.async { [self] in + showFloatingPanel() + } } deinit { @@ -202,6 +205,10 @@ class MainViewController: UIViewController { // MARK: - Private methods - @objc private func updateFloatingPanelLayout() { + guard floatingPanel != nil else { + return + } + floatingPanel.invalidateLayout() mainView.setupView(animated: false) } @@ -240,6 +247,10 @@ class MainViewController: UIViewController { floatingPanel.behavior = MainFloatingPanelBehavior() } + private func showFloatingPanel() { + floatingPanel.show(animated: true) + } + private func startAPIUpdate() { updateServersList() Timer.scheduledTimer(timeInterval: 60 * 15, target: self, selector: #selector(updateServersList), userInfo: nil, repeats: true) From 22e1594d35ae49b0f19d23083038225f3745ffda Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Mon, 23 Oct 2023 14:37:26 +0200 Subject: [PATCH 6/8] fix: update ControlPanelViewController+Ext.swift --- .../ControlPanel/ControlPanelViewController+Ext.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift index e960f759f..8225a83b7 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift @@ -29,6 +29,8 @@ import JGProgressHUD extension ControlPanelViewController { override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + controlPanelView.networkView.isHidden = !UserDefaults.shared.networkProtectionEnabled + if indexPath.row == 0 { return 100 } if indexPath.row == 1 && Application.shared.settings.connectionProtocol.tunnelType() == .ipsec { return 0 } if indexPath.row == 1 { return 44 } From d6e28c4b6665a9757726bb2bbf999544d6cab699 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 24 Oct 2023 11:41:58 +0200 Subject: [PATCH 7/8] fix: update ControlPanelViewController+Ext.swift --- .../MainScreen/ControlPanel/ControlPanelViewController+Ext.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift b/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift index 8225a83b7..ecc123ff4 100644 --- a/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift +++ b/IVPNClient/Scenes/MainScreen/ControlPanel/ControlPanelViewController+Ext.swift @@ -30,6 +30,7 @@ extension ControlPanelViewController { override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { controlPanelView.networkView.isHidden = !UserDefaults.shared.networkProtectionEnabled + controlPanelView.exitServerTableCell.isHidden = !UserDefaults.shared.isMultiHop if indexPath.row == 0 { return 100 } if indexPath.row == 1 && Application.shared.settings.connectionProtocol.tunnelType() == .ipsec { return 0 } From 1fdaa6fa9f8a80b3903a4a3862b640b11f57b9d7 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 25 Oct 2023 11:48:51 +0200 Subject: [PATCH 8/8] refactor: clean up main view --- IVPNClient/Scenes/Base.lproj/Main.storyboard | 97 +++++--------------- 1 file changed, 24 insertions(+), 73 deletions(-) diff --git a/IVPNClient/Scenes/Base.lproj/Main.storyboard b/IVPNClient/Scenes/Base.lproj/Main.storyboard index fa3f6c7f4..6408521fd 100644 --- a/IVPNClient/Scenes/Base.lproj/Main.storyboard +++ b/IVPNClient/Scenes/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -21,7 +21,7 @@ - +