From 3f7ad5bf57e15afceb3482c2c1cb7c09939c0a7e Mon Sep 17 00:00:00 2001 From: Davide Date: Sun, 3 Nov 2024 08:38:53 +0100 Subject: [PATCH] Fix flashing context menu on data count update (#803) Observe tunnel in InstalledProfileView subviews to avoid redraw of whole view and context menu. --- .../Views/App/InstalledProfileView.swift | 89 +++++++++++++++---- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/Passepartout/Library/Sources/AppUIMain/Views/App/InstalledProfileView.swift b/Passepartout/Library/Sources/AppUIMain/Views/App/InstalledProfileView.swift index 8d3a631f..bd34730e 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/App/InstalledProfileView.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/App/InstalledProfileView.swift @@ -39,8 +39,7 @@ struct InstalledProfileView: View, Routable { let profile: Profile? - @ObservedObject - var tunnel: ExtendedTunnel + let tunnel: ExtendedTunnel let interactiveManager: InteractiveManager @@ -100,30 +99,25 @@ private extension InstalledProfileView { var statusView: some View { HStack { providerSelectorButton - ConnectionStatusText(tunnel: tunnel) - .font(.body) - .foregroundStyle(tunnel.statusColor(theme)) - .opacity(installedOpacity) + StatusText( + theme: theme, + tunnel: tunnel, + opacity: installedOpacity + ) } } var toggleButton: some View { - TunnelToggleButton( + ToggleButton( + theme: theme, tunnel: tunnel, profile: profile, nextProfileId: $nextProfileId, interactiveManager: interactiveManager, errorHandler: errorHandler, - onProviderEntityRequired: flow?.onEditProviderEntity, - label: { _ in - ThemeImage(.tunnelToggle) - .scaleEffect(1.5, anchor: .trailing) - } + opacity: installedOpacity, + flow: flow ) - // TODO: #584, necessary to avoid cell selection - .buttonStyle(.plain) - .foregroundStyle(tunnel.statusColor(theme)) - .opacity(installedOpacity) } var menuContent: some View { @@ -156,6 +150,69 @@ private extension InstalledProfileView { } } +// MARK: - Subviews (observing) + +private struct StatusText: View { + + @ObservedObject + var theme: Theme + + @ObservedObject + var tunnel: ExtendedTunnel + + let opacity: Double + + var body: some View { + ConnectionStatusText(tunnel: tunnel) + .font(.body) + .foregroundStyle(tunnel.statusColor(theme)) + .opacity(opacity) + } +} + +private struct ToggleButton: View { + + @ObservedObject + var theme: Theme + + @ObservedObject + var tunnel: ExtendedTunnel + + let profile: Profile? + + @Binding + var nextProfileId: Profile.ID? + + @ObservedObject + var interactiveManager: InteractiveManager + + @ObservedObject + var errorHandler: ErrorHandler + + let opacity: Double + + let flow: ProfileFlow? + + var body: some View { + TunnelToggleButton( + tunnel: tunnel, + profile: profile, + nextProfileId: $nextProfileId, + interactiveManager: interactiveManager, + errorHandler: errorHandler, + onProviderEntityRequired: flow?.onEditProviderEntity, + label: { _ in + ThemeImage(.tunnelToggle) + .scaleEffect(1.5, anchor: .trailing) + } + ) + // TODO: #584, necessary to avoid cell selection + .buttonStyle(.plain) + .foregroundStyle(tunnel.statusColor(theme)) + .opacity(opacity) + } +} + private struct ProviderCountryFlag: View { let provider: ModuleMetadata.Provider