Restore reconnect action (#232)
* Add "Reconnect" in profile view * Add "Reconnect" in profile context menu * Update CHANGELOG * Restrict "Reconnect" in context menu to iOS 16 SwiftUI does not react properly to state updates.
This commit is contained in:
parent
9962401d74
commit
c0cc10ab94
|
@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- OpenVPN: Support for `--remote-random-hostname`. [tunnelkit#286](https://github.com/passepartoutvpn/tunnelkit/pull/286)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Restore "Reconnect" action in profiles. [#232](https://github.com/passepartoutvpn/passepartout-apple/pull/232)
|
||||
|
||||
## 2.0.1 (2022-10-17)
|
||||
|
||||
### Added
|
||||
|
|
|
@ -245,6 +245,10 @@ extension View {
|
|||
"ellipsis.circle"
|
||||
}
|
||||
|
||||
var themeReconnectImage: String {
|
||||
"arrow.clockwise"
|
||||
}
|
||||
|
||||
var themeShortcutsImage: String {
|
||||
"mic"
|
||||
}
|
||||
|
@ -290,10 +294,6 @@ extension View {
|
|||
"slider.horizontal.3"
|
||||
}
|
||||
|
||||
var themeProviderRefreshImage: String {
|
||||
"arrow.clockwise"
|
||||
}
|
||||
|
||||
var themeNetworkSettingsImage: String {
|
||||
// "network"
|
||||
"globe"
|
||||
|
|
|
@ -85,8 +85,7 @@ extension OrganizerView {
|
|||
} label: {
|
||||
profileLabel(forHeader: header)
|
||||
}.contextMenu {
|
||||
duplicateButton(forHeader: header)
|
||||
deleteButton(forHeader: header)
|
||||
ProfileContextMenu(header: header)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,23 +96,6 @@ extension OrganizerView {
|
|||
)
|
||||
}
|
||||
|
||||
private func duplicateButton(forHeader header: Profile.Header) -> some View {
|
||||
ProfileView.DuplicateButton(
|
||||
header: header,
|
||||
setAsCurrent: false
|
||||
)
|
||||
}
|
||||
|
||||
private func deleteButton(forHeader header: Profile.Header) -> some View {
|
||||
DestructiveButton {
|
||||
withAnimation {
|
||||
profileManager.removeProfiles(withIds: [header.id])
|
||||
}
|
||||
} label: {
|
||||
Label(L10n.Global.Strings.delete, systemImage: themeDeleteImage)
|
||||
}
|
||||
}
|
||||
|
||||
private var sortedHeaders: [Profile.Header] {
|
||||
profileManager.headers
|
||||
.sorted()
|
||||
|
@ -146,3 +128,52 @@ extension OrganizerView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension OrganizerView {
|
||||
struct ProfileContextMenu: View {
|
||||
@ObservedObject private var profileManager: ProfileManager
|
||||
|
||||
@ObservedObject private var currentVPNState: ObservableVPNState
|
||||
|
||||
let header: Profile.Header
|
||||
|
||||
init(header: Profile.Header) {
|
||||
profileManager = .shared
|
||||
currentVPNState = .shared
|
||||
self.header = header
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
if #available(iOS 16, *), isActiveProfileNotDisconnected {
|
||||
reconnectButton
|
||||
}
|
||||
duplicateButton
|
||||
deleteButton
|
||||
}
|
||||
|
||||
private var isActiveProfileNotDisconnected: Bool {
|
||||
profileManager.isActiveProfile(header.id) && currentVPNState.vpnStatus != .disconnected
|
||||
}
|
||||
|
||||
private var reconnectButton: some View {
|
||||
ProfileView.ReconnectButton()
|
||||
}
|
||||
|
||||
private var duplicateButton: some View {
|
||||
ProfileView.DuplicateButton(
|
||||
header: header,
|
||||
setAsCurrent: false
|
||||
)
|
||||
}
|
||||
|
||||
private var deleteButton: some View {
|
||||
DestructiveButton {
|
||||
withAnimation {
|
||||
profileManager.removeProfiles(withIds: [header.id])
|
||||
}
|
||||
} label: {
|
||||
Label(L10n.Global.Strings.delete, systemImage: themeDeleteImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ extension ProfileView {
|
|||
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
|
||||
@ObservedObject private var currentVPNState: ObservableVPNState
|
||||
|
||||
@ObservedObject private var currentProfile: ObservableProfile
|
||||
|
||||
private var header: Profile.Header {
|
||||
|
@ -61,6 +63,7 @@ extension ProfileView {
|
|||
init(currentProfile: ObservableProfile, modalType: Binding<ModalType?>) {
|
||||
profileManager = .shared
|
||||
vpnManager = .shared
|
||||
currentVPNState = .shared
|
||||
self.currentProfile = currentProfile
|
||||
_modalType = modalType
|
||||
}
|
||||
|
@ -90,10 +93,20 @@ extension ProfileView {
|
|||
|
||||
private var mainView: some View {
|
||||
Menu {
|
||||
shortcutsButton
|
||||
if isActiveProfileNotDisconnected {
|
||||
ReconnectButton()
|
||||
}
|
||||
ShortcutsButton(
|
||||
modalType: $modalType
|
||||
)
|
||||
Divider()
|
||||
renameButton
|
||||
duplicateButton
|
||||
RenameButton(
|
||||
modalType: $modalType
|
||||
)
|
||||
DuplicateButton(
|
||||
header: header,
|
||||
setAsCurrent: true
|
||||
)
|
||||
uninstallVPNButton
|
||||
Divider()
|
||||
deleteProfileButton
|
||||
|
@ -102,25 +115,10 @@ extension ProfileView {
|
|||
}
|
||||
}
|
||||
|
||||
private var shortcutsButton: some View {
|
||||
ShortcutsButton(
|
||||
modalType: $modalType
|
||||
)
|
||||
}
|
||||
|
||||
private var renameButton: some View {
|
||||
RenameButton(
|
||||
modalType: $modalType
|
||||
)
|
||||
private var isActiveProfileNotDisconnected: Bool {
|
||||
profileManager.isActiveProfile(header.id) && currentVPNState.vpnStatus != .disconnected
|
||||
}
|
||||
|
||||
private var duplicateButton: some View {
|
||||
DuplicateButton(
|
||||
header: currentProfile.value.header,
|
||||
setAsCurrent: true
|
||||
)
|
||||
}
|
||||
|
||||
private var uninstallVPNButton: some View {
|
||||
Button {
|
||||
actionSheetType = .uninstallVPN
|
||||
|
@ -149,6 +147,26 @@ extension ProfileView {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ProfileView {
|
||||
struct ReconnectButton: View {
|
||||
@ObservedObject private var vpnManager: VPNManager
|
||||
|
||||
init() {
|
||||
vpnManager = .shared
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
Task { @MainActor in
|
||||
await vpnManager.reconnect()
|
||||
}
|
||||
} label: {
|
||||
Label(L10n.Global.Strings.reconnect, systemImage: themeReconnectImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ShortcutsButton: View {
|
||||
@ObservedObject private var productManager: ProductManager
|
||||
|
|
Loading…
Reference in New Issue