Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Packages/App/Sources/AppUIMain/Domain/Issue+Metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ extension Issue {

let tunnelLog: Data?

// FIXME: #1369, diagnostics/logs must be per-tunnel
// live tunnel log
if metadata.tunnel.status != .inactive {
if !metadata.tunnel.activeProfiles.isEmpty {
tunnelLog = await metadata.tunnel.currentLog(parameters: metadata.parameters)
.joined(separator: "\n")
.data(using: .utf8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ private extension AppCoordinator {
builder.saveModule(newModule)
let newProfile = try builder.tryBuild()

let wasConnected = newProfile.id == tunnel.currentProfile?.id && tunnel.status == .active
let wasConnected = tunnel.status(ofProfileId: newProfile.id) == .active
try await profileManager.save(newProfile, isLocal: true)

guard profile.shouldConnectToProviderServer else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,18 @@ private extension InstalledProfileView {
var statusView: some View {
HStack {
providerServerButton
StatusText(theme: theme, tunnel: tunnel)
statusText
}
}

var providerServerButton: some View {
profile?.providerSelectorButton(onSelect: flow?.connectionFlow?.onProviderEntityRequired)
}

var statusText: some View {
ConnectionStatusText(tunnel: tunnel, profileId: profile?.id)
}

var toggleButton: some View {
TunnelToggle(
tunnel: tunnel,
Expand All @@ -127,20 +131,6 @@ private extension InstalledProfileView {

// MARK: - Subviews (observing)

private struct StatusText: View {

@ObservedObject
var theme: Theme

@ObservedObject
var tunnel: ExtendedTunnel

var body: some View {
debugChanges()
return ConnectionStatusText(tunnel: tunnel)
}
}

private struct HeaderModifier: ViewModifier {

@EnvironmentObject
Expand Down
13 changes: 3 additions & 10 deletions Packages/App/Sources/AppUIMain/Views/App/ProfileCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct ProfileCardView: View {
}
.uiAccessibility(.App.profileEdit)

tunnelView
statusView
.font(.subheadline)

Spacer(minLength: .zero)
Expand All @@ -68,15 +68,8 @@ struct ProfileCardView: View {
}

private extension ProfileCardView {

@ViewBuilder
var tunnelView: some View {
if tunnel.currentProfile?.id == preview.id {
ConnectionStatusText(tunnel: tunnel)
} else {
Text(Strings.Entities.TunnelStatus.inactive)
.foregroundStyle(.secondary)
}
var statusView: some View {
ConnectionStatusText(tunnel: tunnel, profileId: preview.id)
}
}

Expand Down
16 changes: 6 additions & 10 deletions Packages/App/Sources/AppUIMain/Views/App/ProfileGridView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,20 @@ struct ProfileGridView: View, Routable, TunnelInstallationProviding {

var flow: ProfileFlow?

@State
private var currentProfile: TunnelCurrentProfile?

private let columns: [GridItem] = [GridItem(.adaptive(minimum: 300.0))]

var body: some View {
debugChanges()
return ScrollViewReader { scrollProxy in
ScrollView {
VStack(spacing: .zero) {
#if os(iOS)
if !isUITesting && !isSearching && pinsActiveProfile {
headerView(scrollProxy: scrollProxy)
.padding(.bottom)
.unanimated()
}
#endif
LazyVGrid(columns: columns) {
ForEach(allPreviews, content: profileView)
.onDelete { offsets in
Expand All @@ -84,11 +83,6 @@ struct ProfileGridView: View, Routable, TunnelInstallationProviding {
.themeAnimation(on: profileManager.isReady, category: .profiles)
.themeAnimation(on: profileManager.previews, category: .profiles)
}
.task {
for await newCurrentProfile in tunnel.currentProfileStream {
currentProfile = newCurrentProfile
}
}
}
}

Expand All @@ -99,17 +93,18 @@ private extension ProfileGridView {
profileManager.previews
}

#if os(iOS)
func headerView(scrollProxy: ScrollViewProxy) -> some View {
InstalledProfileView(
layout: .grid,
profileManager: profileManager,
profile: currentProfile,
profile: installedProfile,
tunnel: tunnel,
errorHandler: errorHandler,
flow: flow
)
.contextMenu {
currentProfile.map {
installedProfile.map {
ProfileContextMenu(
style: .installedProfile,
profileManager: profileManager,
Expand All @@ -121,6 +116,7 @@ private extension ProfileGridView {
}
}
}
#endif

func profileView(for preview: ProfilePreview) -> some View {
ProfileRowView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ struct ProfileListView: View, Routable, TunnelInstallationProviding {
var body: some View {
debugChanges()
return Form {
#if os(iOS)
if !isUITesting && !isSearching && pinsActiveProfile {
headerView
.unanimated()
}
#endif
Section {
ForEach(allPreviews, content: profileView)
.onDelete { offsets in
Expand All @@ -84,17 +86,18 @@ private extension ProfileListView {
profileManager.previews
}

#if os(iOS)
var headerView: some View {
InstalledProfileView(
layout: .list,
profileManager: profileManager,
profile: currentProfile,
profile: installedProfile,
tunnel: tunnel,
errorHandler: errorHandler,
flow: flow
)
.contextMenu {
currentProfile.map {
installedProfile.map {
ProfileContextMenu(
style: .installedProfile,
profileManager: profileManager,
Expand All @@ -107,6 +110,7 @@ private extension ProfileListView {
}
.modifier(HideActiveProfileModifier())
}
#endif

func profileView(for preview: ProfilePreview) -> some View {
ProfileRowView(
Expand Down
13 changes: 11 additions & 2 deletions Packages/App/Sources/AppUIMain/Views/App/TunnelRestartButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct TunnelRestartButton<Label>: View where Label: View {
guard let profile else {
return
}
guard tunnel.status == .active else {
guard tunnel.status(ofProfileId: profile.id) == .active else {
return
}
Task {
Expand All @@ -54,6 +54,15 @@ struct TunnelRestartButton<Label>: View where Label: View {
} label: {
label()
}
.disabled(profile == nil || tunnel.status != .active)
.disabled(isDisabled)
}
}

private extension TunnelRestartButton {
var isDisabled: Bool {
guard let profile else {
return true
}
return tunnel.status(ofProfileId: profile.id) != .active
}
}
34 changes: 27 additions & 7 deletions Packages/App/Sources/AppUIMain/Views/AppMenu/macOS/AppMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ private extension AppMenu {

private extension AppMenu {
var isTunnelActionable: Bool {
[.activating, .active].contains(tunnel.status)
// FIXME: #218, must be per-tunnel
[.activating, .active].contains(tunnelStatus)
}

func showApp(completion: (() -> Void)? = nil) {
Expand All @@ -139,14 +140,16 @@ private extension AppMenu {

func reconnect() {
Task {
guard let currentProfileId = tunnel.currentProfile?.id else {
// FIXME: #218, must be per-tunnel
// guard let activeProfileId = tunnel.activeProfile?.id else {
guard let installedProfile else {
return
}
guard let profile = profileManager.profile(withId: currentProfileId) else {
guard let profile = profileManager.profile(withId: installedProfile.id) else {
return
}
do {
try await tunnel.disconnect()
try await tunnel.disconnect(from: installedProfile.id)
try await tunnel.connect(with: profile)
} catch {
pp_log(.app, .error, "Unable to reconnect to profile \(profile.id) from menu: \(error)")
Expand All @@ -157,15 +160,19 @@ private extension AppMenu {
func disconnect() {
Task {
do {
try await tunnel.disconnect()
// FIXME: #218, must be per-tunnel
guard let installedProfile else {
return
}
try await tunnel.disconnect(from: installedProfile.id)
} catch {
pp_log(.app, .error, "Unable to disconnect from menu: \(error)")
}
}
}

func isProfileActive(_ preview: ProfilePreview) -> Bool {
preview.id == tunnel.currentProfile?.id && tunnel.status != .inactive
tunnel.status(ofProfileId: preview.id) != .inactive
}

func toggleProfile(_ isOn: Bool, for preview: ProfilePreview) {
Expand All @@ -177,7 +184,7 @@ private extension AppMenu {
if isOn {
try await tunnel.connect(with: profile)
} else {
try await tunnel.disconnect()
try await tunnel.disconnect(from: profile.id)
}
} catch {
pp_log(.app, .error, "Unable to toggle profile \(preview.id) from menu: \(error)")
Expand All @@ -196,4 +203,17 @@ private extension AppMenu {
}
}

private extension AppMenu {

// FIXME: #218, must be per-tunnel
var tunnelStatus: TunnelStatus {
installedProfile?.status ?? .inactive
}

// FIXME: #218, must be per-tunnel
var installedProfile: TunnelActiveProfile? {
tunnel.activeProfiles.first?.value
}
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,17 @@ public struct AppMenuImage: View {
}

public var body: some View {
ThemeMenuImage(tunnel.connectionStatus.imageName)
ThemeMenuImage(connectionStatus.imageName)
}
}

private extension AppMenuImage {
var connectionStatus: TunnelStatus {
// FIXME: #218, must be per-tunnel
guard let id = tunnel.activeProfiles.first?.value.id else {
return .inactive
}
return tunnel.connectionStatus(ofProfileId: id)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,22 @@ private extension DiagnosticsView {
}

var openVPNSection: some View {
tunnel.value(forKey: TunnelEnvironmentKeys.OpenVPN.serverConfiguration)
.map { cfg in
Group {
NavigationLink(Strings.Views.Diagnostics.Openvpn.Rows.serverConfiguration) {
OpenVPNView(serverConfiguration: cfg)
.navigationTitle(Strings.Views.Diagnostics.Openvpn.Rows.serverConfiguration)
// FIXME: #1369, diagnostics/logs must be per-tunnel
tunnel.activeProfiles.first
.map {
tunnel.value(
forKey: TunnelEnvironmentKeys.OpenVPN.serverConfiguration,
ofProfileId: $0.key
)
.map { cfg in
Group {
NavigationLink(Strings.Views.Diagnostics.Openvpn.Rows.serverConfiguration) {
OpenVPNView(serverConfiguration: cfg)
.navigationTitle(Strings.Views.Diagnostics.Openvpn.Rows.serverConfiguration)
}
}
.themeSection(header: Strings.Unlocalized.openVPN)
}
.themeSection(header: Strings.Unlocalized.openVPN)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ struct ReportIssueButton {
@State
var modalRoute: ModalRoute?

// FIXME: #1369, diagnostics/logs must be per-tunnel
var installedProfile: Profile? {
guard let id = tunnel.currentProfile?.id else {
guard let id = tunnel.activeProfiles.first?.value.id else {
return nil
}
return profileManager.profile(withId: id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct ActiveProfileView: View {
VStack(spacing: .zero) {
VStack {
VStack {
currentProfileView
activeProfileView
statusView
}
.padding(.bottom)
Expand All @@ -80,7 +80,7 @@ struct ActiveProfileView: View {
}

private extension ActiveProfileView {
var currentProfileView: some View {
var activeProfileView: some View {
Text(profile?.name ?? Strings.Views.App.InstalledProfile.None.name)
.font(.title)
.fontWeight(theme.relevantWeight)
Expand All @@ -89,7 +89,7 @@ private extension ActiveProfileView {
}

var statusView: some View {
ConnectionStatusText(tunnel: tunnel)
ConnectionStatusText(tunnel: tunnel, profileId: profile?.id)
.font(.title2)
.frame(maxWidth: .infinity, alignment: .leading)
.brightness(0.2)
Expand Down
Loading