From 4fc0216f0544f5e78886e877b1b9caa688015dd7 Mon Sep 17 00:00:00 2001 From: Steffen Ernst Date: Thu, 16 Jan 2025 13:44:28 +0100 Subject: [PATCH] Simplify daita and multihop view logic --- .../Settings/Views/SettingsInfoView.swift | 116 +++++++++++++----- 1 file changed, 88 insertions(+), 28 deletions(-) diff --git a/ios/MullvadVPN/Coordinators/Settings/Views/SettingsInfoView.swift b/ios/MullvadVPN/Coordinators/Settings/Views/SettingsInfoView.swift index 095d5d8ceda7..ac0a9d63f216 100644 --- a/ios/MullvadVPN/Coordinators/Settings/Views/SettingsInfoView.swift +++ b/ios/MullvadVPN/Coordinators/Settings/Views/SettingsInfoView.swift @@ -27,44 +27,42 @@ struct SettingsInfoView: View { var body: some View { ZStack { - // Renders (and hide) the content of each page, to push the view to the maximum possible size. - VStack { - ZStack { - ForEach(viewModel.pages, id: \.self) { page in - contentView(for: page) - } - } - Spacer() - .frame(height: pageIndicatorSpacing) - } - .hidden() TabView { - ForEach(viewModel.pages, id: \.self) { page in - VStack { - contentView(for: page) - Spacer() - } - .padding(UIMetrics.SettingsInfoView.layoutMargins) - } + contentView() } + .padding(UIMetrics.SettingsInfoView.layoutMargins) .tabViewStyle(.page) .foregroundColor(Color(.primaryTextColor)) .background { Color(.secondaryColor) } + hiddenViewToStretchHeightInsideScrollView() } } - private func contentView(for page: SettingsInfoViewModelPage) -> some View { - VStack(alignment: .leading, spacing: 16) { - Image(page.image) - .resizable() - .aspectRatio(contentMode: .fit) - Text(page.body) - .font(.subheadline) - .opacity(0.6) - // The following line is needed to not truncate the text when using xxl text size - .minimumScaleFactor(0.9) +// A TabView inside a Scrollview has no height. This hidden view stretches the TabView to have the size of the heighest page. + private func hiddenViewToStretchHeightInsideScrollView() -> some View { + return ZStack { + contentView() + } + .padding(UIMetrics.SettingsInfoView.layoutMargins) + .hidden() + } + + private func contentView() -> some View { + ForEach(viewModel.pages, id: \.self) { page in + VStack { + VStack(alignment: .leading, spacing: 16) { + Image(page.image) + .resizable() + .aspectRatio(contentMode: .fit) + Text(page.body) + .font(.subheadline) + .opacity(0.6) + } + Spacer() + } + .padding(.bottom, pageIndicatorSpacing) } } } @@ -105,3 +103,65 @@ struct SettingsInfoView: View { ] )) } + +#Preview("Single inside Scrollview") { + ScrollView { + SettingsInfoView(viewModel: SettingsInfoViewModel( + pages: [ + SettingsInfoViewModelPage( + body: """ + Multihop routes your traffic into one WireGuard server and out another, making it \ + harder to trace. This results in increased latency but increases anonymity online. + """, + image: .multihopIllustration + ), + ] + )) + } +} + +#Preview("Multiple inside Scrollview") { + ScrollView { + SettingsInfoView(viewModel: SettingsInfoViewModel( + pages: [ + SettingsInfoViewModelPage( + body: NSLocalizedString( + "SETTINGS_INFO_DAITA_PAGE_1", + tableName: "Settings", + value: """ + DAITA (Defense against AI-guided Traffic Analysis) hides patterns in \ + your encrypted VPN traffic. + + By using sophisticated AI it’s possible to analyze the traffic of data \ + packets going in and out of your device (even if the traffic is encrypted). + + If an observer monitors these data packets, DAITA makes it significantly \ + harder for them to identify which websites you are visiting or with whom \ + you are communicating. + """, + comment: "" + ), + image: .daitaOffIllustration + ), + SettingsInfoViewModelPage( + body: NSLocalizedString( + "SETTINGS_INFO_DAITA_PAGE_2", + tableName: "Settings", + value: """ + DAITA does this by carefully adding network noise and making all network \ + packets the same size. + + Not all our servers are DAITA-enabled. Therefore, we use multihop \ + automatically to enable DAITA with any server. + + Attention: Be cautious if you have a limited data plan as this feature \ + will increase your network traffic. + """, + comment: "" + ), + image: .daitaOnIllustration + ), + ] + )) + } +}