Skip to content

Commit

Permalink
Fix divider not being completely hidden when applicable
Browse files Browse the repository at this point in the history
  • Loading branch information
rablador committed Jan 7, 2025
1 parent 712d19e commit 497bcd4
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 56 deletions.
4 changes: 4 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@
7AA1309F2D007B2500640DF9 /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */; };
7AA130A12D01B1E200640DF9 /* SplitMainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */; };
7AA513862BC91C6B00D081A4 /* LogRotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */; };
7AA636382D2D3BB0009B2C89 /* View+Conditionals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA636372D2D3BAC009B2C89 /* View+Conditionals.swift */; };
7AA7046A2C8EFE2B0045699D /* StoredRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA704682C8EFE050045699D /* StoredRelays.swift */; };
7AB2B6702BA1EB8C00B03E3B /* ListCustomListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */; };
7AB2B6712BA1EB8C00B03E3B /* ListCustomListCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66F2BA1EB8C00B03E3B /* ListCustomListCoordinator.swift */; };
Expand Down Expand Up @@ -2002,6 +2003,7 @@
7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectView.swift; sourceTree = "<group>"; };
7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitMainButton.swift; sourceTree = "<group>"; };
7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotationTests.swift; sourceTree = "<group>"; };
7AA636372D2D3BAC009B2C89 /* View+Conditionals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Conditionals.swift"; sourceTree = "<group>"; };
7AA704682C8EFE050045699D /* StoredRelays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredRelays.swift; sourceTree = "<group>"; };
7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCustomListViewController.swift; sourceTree = "<group>"; };
7AB2B66F2BA1EB8C00B03E3B /* ListCustomListCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCustomListCoordinator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3173,6 +3175,7 @@
7A21DACE2A30AA3700A787A9 /* UITextField+Appearance.swift */,
5878F4FF29CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift */,
7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */,
7AA636372D2D3BAC009B2C89 /* View+Conditionals.swift */,
7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */,
7A8A18FA2CE4B66C000BCB5B /* View+TapAreaSize.swift */,
);
Expand Down Expand Up @@ -5946,6 +5949,7 @@
F01DAE332C2B032A00521E46 /* RelaySelection.swift in Sources */,
58B993B12608A34500BA7811 /* LoginContentView.swift in Sources */,
7A516C2E2B6D357500BBD33D /* URL+Scoping.swift in Sources */,
7AA636382D2D3BB0009B2C89 /* View+Conditionals.swift in Sources */,
5878A27529093A310096FC88 /* StorePaymentEvent.swift in Sources */,
7A7AD28D29DC677800480EF1 /* FirstTimeLaunch.swift in Sources */,
F062000C2CB7EB5D002E6DB9 /* UIImage+Helpers.swift in Sources */,
Expand Down
41 changes: 41 additions & 0 deletions ios/MullvadVPN/Extensions/View+Conditionals.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// View+Conditionals.swift
// MullvadVPN
//
// Created by Jon Petersson on 2025-01-07.
// Copyright © 2025 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

extension View {
@ViewBuilder func `if`<Content: View>(
_ conditional: Bool,
@ViewBuilder _ content: (Self) -> Content
) -> some View {
if conditional {
content(self)
} else {
self
}
}

@ViewBuilder func ifLet<Content: View, T>(
_ conditional: T?,
@ViewBuilder _ content: (Self, _ value: T) -> Content
) -> some View {
if let value = conditional {
content(self, value)
} else {
self
}
}

@ViewBuilder func showIf(_ conditional: Bool) -> some View {
if conditional {
self
} else {
EmptyView()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ struct ChipContainerView<ViewModel>: View where ViewModel: ChipViewModelProtocol
createChipViews(chips: chipsToAdd, containerWidth: containerWidth)
}

if showMoreButton {
Text(LocalizedStringKey("\(viewModel.chips.count - chipsToAdd.count) more..."))
.font(.subheadline)
.lineLimit(1)
.foregroundStyle(UIColor.primaryTextColor.color)
.onTapGesture {
isExpanded.toggle()
}
}
Text(LocalizedStringKey("\(viewModel.chips.count - chipsToAdd.count) more..."))
.font(.subheadline)
.lineLimit(1)
.foregroundStyle(UIColor.primaryTextColor.color)
.onTapGesture {
isExpanded.toggle()
}
.showIf(showMoreButton)

Spacer()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ extension ConnectionView {
text: viewModel.localizedTitleForSelectLocationButton,
image: .iconReload,
style: .default,
accessibilityId: .selectLocationButton,
primaryAction: { action?(.selectLocation) },
secondaryAction: { action?(.reconnect) }
)
.accessibilityIdentifier(AccessibilityIdentifier.selectLocationButton.asString)
case .disconnecting, .pendingReconnect, .disconnected:
MainButton(
text: viewModel.localizedTitleForSelectLocationButton,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ struct ConnectionView: View {

var body: some View {
Spacer()
.accessibilityIdentifier(AccessibilityIdentifier.connectionView.asString)

VStack(spacing: 22) {
if connectionViewModel.showsActivityIndicator {
CustomProgressView(style: .large)
}
CustomProgressView(style: .large)
.showIf(connectionViewModel.showsActivityIndicator)

ZStack {
BlurView(style: .dark)

VStack(alignment: .leading, spacing: 16) {
HeaderView(viewModel: connectionViewModel, isExpanded: $isExpanded)

if connectionViewModel.showConnectionDetails {
DetailsContainer(
viewModel: connectionViewModel,
indicatorsViewModel: indicatorsViewModel,
isExpanded: $isExpanded
)
}
DetailsContainer(
connectionViewModel: connectionViewModel,
indicatorsViewModel: indicatorsViewModel,
isExpanded: $isExpanded
)
.showIf(connectionViewModel.showConnectionDetails)

ButtonPanel(viewModel: connectionViewModel, action: action)
}
Expand All @@ -46,18 +46,12 @@ struct ConnectionView: View {
.padding(16)
}
.padding(.bottom, 8) // Adding some spacing so as not to overlap with the map legal link.
.accessibilityIdentifier(AccessibilityIdentifier.connectionView.asString)
.onChange(of: isExpanded) { _ in
onContentUpdate?()
}
.onReceive(connectionViewModel.combinedState) { _, _ in
onContentUpdate?()

if !connectionViewModel.showConnectionDetails {
// withAnimation {
isExpanded = false
// }
}
isExpanded = connectionViewModel.showConnectionDetails
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ extension ConnectionViewViewModel {
var showConnectionDetails: Bool {
switch tunnelStatus.state {
case .connecting, .reconnecting, .waitingForConnectivity(.noConnection), .negotiatingEphemeralPeer,
.connected, .pendingReconnect, .waitingForConnectivity(.noNetwork):
.connected, .pendingReconnect:
true
case .disconnecting, .disconnected, .error:
case .disconnecting, .disconnected, .waitingForConnectivity(.noNetwork), .error:
false
}
}
Expand Down Expand Up @@ -130,9 +130,10 @@ extension ConnectionViewViewModel {

var localizedTitleForSelectLocationButton: LocalizedStringKey {
switch tunnelStatus.state {
case .disconnecting, .pendingReconnect, .disconnected:
case .disconnecting, .pendingReconnect, .disconnected, .waitingForConnectivity(.noNetwork):
LocalizedStringKey("Select location")
case .connecting, .connected, .reconnecting, .waitingForConnectivity, .negotiatingEphemeralPeer, .error:
case .connecting, .connected, .reconnecting, .waitingForConnectivity(.noConnection),
.negotiatingEphemeralPeer, .error:
LocalizedStringKey("Switch location")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,16 @@ import SwiftUI

extension ConnectionView {
internal struct DetailsContainer: View {
@StateObject var viewModel: ConnectionViewViewModel
@StateObject var connectionViewModel: ConnectionViewViewModel
@StateObject var indicatorsViewModel: FeatureIndicatorsViewModel
@Binding var isExpanded: Bool

@State private var scrollViewHeight: CGFloat = 0

var body: some View {
// if isExpanded {
Divider()
.background(UIColor.secondaryTextColor.color)
.opacity(isExpanded ? 1.0 : 0.0)
// }
.showIf(isExpanded)

// This geometry reader is somewhat of a workaround. It's "smart" in that it takes up as much
// space as it can and thereby helps the view to understand the maximum allowed height when
Expand All @@ -30,17 +28,15 @@ extension ConnectionView {
GeometryReader { _ in
ScrollView {
VStack(spacing: 16) {
if !indicatorsViewModel.chips.isEmpty {
FeatureIndicatorsView(
viewModel: indicatorsViewModel,
isExpanded: $isExpanded
)
}
FeatureIndicatorsView(
viewModel: indicatorsViewModel,
isExpanded: $isExpanded
)
.showIf(!indicatorsViewModel.chips.isEmpty)

if isExpanded {
DetailsView(viewModel: viewModel)
.transition(.move(edge: .bottom))
}
DetailsView(viewModel: connectionViewModel)
.transition(.move(edge: .bottom))
.showIf(isExpanded)
}
.sizeOfView { scrollViewHeight = $0.height }
}
Expand All @@ -53,7 +49,7 @@ extension ConnectionView {
#Preview {
ConnectionViewComponentPreview(showIndicators: true, isExpanded: true) { indicatorModel, viewModel, isExpanded in
ConnectionView.DetailsContainer(
viewModel: viewModel,
connectionViewModel: viewModel,
indicatorsViewModel: indicatorModel,
isExpanded: isExpanded
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,22 @@ extension ConnectionView {
}
.accessibilityLabel(viewModel.localizedAccessibilityLabelForSecureLabel)

if viewModel.showConnectionDetails {
Group {
Spacer()
Image(.iconChevron)
.renderingMode(.template)
.rotationEffect(isExpanded ? .degrees(-90) : .degrees(90))
.foregroundStyle(.white)
.accessibilityIdentifier(AccessibilityIdentifier.relayStatusCollapseButton.asString)
.transaction { transaction in
transaction.animation = nil
}
}
.showIf(viewModel.showConnectionDetails)
}
.accessibilityIdentifier(AccessibilityIdentifier.relayStatusCollapseButton.asString)
.contentShape(Rectangle())
.onTapGesture {
// withAnimation {
isExpanded.toggle()
// }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ struct FeatureIndicatorsView<ViewModel>: View where ViewModel: ChipViewModelProt

var body: some View {
VStack(alignment: .leading, spacing: 0) {
if isExpanded {
Text(LocalizedStringKey("Active features"))
.font(.footnote.weight(.semibold))
.foregroundStyle(UIColor.primaryTextColor.color.opacity(0.6))
.padding(.bottom, 8)
}
Text(LocalizedStringKey("Active features"))
.font(.footnote.weight(.semibold))
.foregroundStyle(UIColor.primaryTextColor.color.opacity(0.6))
.padding(.bottom, 8)
.showIf(isExpanded)

ChipContainerView(viewModel: viewModel, isExpanded: $isExpanded)
}
Expand Down
5 changes: 5 additions & 0 deletions ios/MullvadVPN/Views/SplitMainButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct SplitMainButton: View {
var text: LocalizedStringKey
var image: ImageResource
var style: MainButtonStyle.Style
var accessibilityId: AccessibilityIdentifier?

@State private var secondaryButtonWidth: CGFloat = 0

Expand All @@ -28,6 +29,10 @@ struct SplitMainButton: View {
}
.padding(.trailing, -secondaryButtonWidth)
})
.ifLet(accessibilityId) { view, value in
view.accessibilityIdentifier(value.asString)
}

Button(action: secondaryAction, label: {
Image(image)
.resizable()
Expand Down

0 comments on commit 497bcd4

Please sign in to comment.