Skip to content

Commit

Permalink
Add foundation for new connection view
Browse files Browse the repository at this point in the history
  • Loading branch information
rablador committed Dec 5, 2024
1 parent 6f2af48 commit c12da24
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 5 deletions.
46 changes: 42 additions & 4 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,8 @@
7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */; };
7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */; };
7A0EAE9A2D01B41500D3EB8B /* MainButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */; };
7A0EAE9E2D01BCBF00D3EB8B /* View+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */; };
7A11DD0B2A9495D400098CD8 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5802EBC42A8E44AC00E5CE4C /* AppRoutes.swift */; };
7A12D0762B062D5C00E9602D /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */; };
7A12D0772B062D6500E9602D /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */; };
Expand Down Expand Up @@ -563,7 +565,6 @@
7A8A19052CE4E9A9000BCB5B /* SwitchRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19042CE4E9A5000BCB5B /* SwitchRowView.swift */; };
7A8A19072CE4E9D3000BCB5B /* SettingsInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19062CE4E9CC000BCB5B /* SettingsInfoView.swift */; };
7A8A190A2CE5FFE9000BCB5B /* SettingsDAITAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19092CE5FFDF000BCB5B /* SettingsDAITAView.swift */; };
7A8A190C2CE618D3000BCB5B /* View+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190B2CE618CE000BCB5B /* View+Size.swift */; };
7A8A190E2CEB77C1000BCB5B /* SettingsRowViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190D2CEB77B7000BCB5B /* SettingsRowViewFooter.swift */; };
7A8A19102CEE391B000BCB5B /* RowSeparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */; };
7A8A19122CEF1E68000BCB5B /* SettingsInfoContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19112CEF1E58000BCB5B /* SettingsInfoContainerView.swift */; };
Expand Down Expand Up @@ -605,6 +606,10 @@
7A9F293D2CAD2FD5005F2089 /* InfoModalConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */; };
7A9FA1422A2E3306000B728D /* CheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1412A2E3306000B728D /* CheckboxView.swift */; };
7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */; };
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130982CFF365A00640DF9 /* ConnectionView.swift */; };
7AA1309B2D0048D800640DF9 /* MainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA1309A2D0048D800640DF9 /* MainButton.swift */; };
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 */; };
7AA7046A2C8EFE2B0045699D /* StoredRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA704682C8EFE050045699D /* StoredRelays.swift */; };
7AB2B6702BA1EB8C00B03E3B /* ListCustomListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */; };
Expand Down Expand Up @@ -1834,6 +1839,8 @@
7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+FuzzyMatch.swift"; sourceTree = "<group>"; };
7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessbilityIdentifier.swift; sourceTree = "<group>"; };
7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Coordinator+Router.swift"; sourceTree = "<group>"; };
7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButtonStyle.swift; sourceTree = "<group>"; };
7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionProtocol.swift; sourceTree = "<group>"; };
7A1A26422A2612AE00B978AA /* PaymentAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentAlertPresenter.swift; sourceTree = "<group>"; };
7A1A26442A29CEF700B978AA /* RelayFilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1923,7 +1930,6 @@
7A8A19042CE4E9A5000BCB5B /* SwitchRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchRowView.swift; sourceTree = "<group>"; };
7A8A19062CE4E9CC000BCB5B /* SettingsInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInfoView.swift; sourceTree = "<group>"; };
7A8A19092CE5FFDF000BCB5B /* SettingsDAITAView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDAITAView.swift; sourceTree = "<group>"; };
7A8A190B2CE618CE000BCB5B /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
7A8A190D2CEB77B7000BCB5B /* SettingsRowViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRowViewFooter.swift; sourceTree = "<group>"; };
7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RowSeparator.swift; sourceTree = "<group>"; };
7A8A19112CEF1E58000BCB5B /* SettingsInfoContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInfoContainerView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1962,6 +1968,11 @@
7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoModalConfig.swift; sourceTree = "<group>"; };
7A9FA1412A2E3306000B728D /* CheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxView.swift; sourceTree = "<group>"; };
7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckableSettingsCell.swift; sourceTree = "<group>"; };
7AA130982CFF365A00640DF9 /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; };
7AA1309A2D0048D800640DF9 /* MainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButton.swift; sourceTree = "<group>"; };
7AA1309C2D0072F900640DF9 /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
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>"; };
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>"; };
Expand Down Expand Up @@ -2982,6 +2993,7 @@
583FE01E29C197D5006E85F9 /* Tunnel */ = {
isa = PBXGroup;
children = (
7AA130972CFF364F00640DF9 /* FeatureIndicators */,
58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */,
5878A27A2909649A0096FC88 /* CustomOverlayRenderer.swift */,
58907D9424D17B4E00CFC3F5 /* DisconnectSplitButton.swift */,
Expand Down Expand Up @@ -3012,10 +3024,14 @@
F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */,
7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */,
7A5869942B32E9C700640D27 /* LinkButton.swift */,
7AA1309A2D0048D800640DF9 /* MainButton.swift */,
7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */,
7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */,
58F19E34228C15BA00C7710B /* SpinnerActivityIndicatorView.swift */,
7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */,
E1FD0DF428AA7CE400299DB4 /* StatusActivityView.swift */,
58EF581025D69DB400AEBA94 /* StatusImageView.swift */,
7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -3091,7 +3107,7 @@
7A21DACE2A30AA3700A787A9 /* UITextField+Appearance.swift */,
5878F4FF29CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift */,
7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */,
7A8A190B2CE618CE000BCB5B /* View+Size.swift */,
7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */,
7A8A18FA2CE4B66C000BCB5B /* View+TapAreaSize.swift */,
);
path = Extensions;
Expand Down Expand Up @@ -3593,6 +3609,7 @@
A9D9A4C12C36D53C004088DD /* MullvadRustRuntimeTests */,
58CE5E61224146200008646E /* Products */,
584F991F2902CBDD001F858D /* Frameworks */,
7A0EAE982D01B29E00D3EB8B /* Recovered References */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -3893,6 +3910,14 @@
path = Edit;
sourceTree = "<group>";
};
7A0EAE982D01B29E00D3EB8B /* Recovered References */ = {
isa = PBXGroup;
children = (
7AA1309C2D0072F900640DF9 /* View+Size.swift */,
);
name = "Recovered References";
sourceTree = "<group>";
};
7A2960F72A964A3500389B82 /* Alert */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -4024,6 +4049,14 @@
path = SelectLocation;
sourceTree = "<group>";
};
7AA130972CFF364F00640DF9 /* FeatureIndicators */ = {
isa = PBXGroup;
children = (
7AA130982CFF365A00640DF9 /* ConnectionView.swift */,
);
path = FeatureIndicators;
sourceTree = "<group>";
};
7AD63A422CDA661B00445268 /* Extensions */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -5830,6 +5863,7 @@
7A8A19282CF603EB000BCB5B /* SettingsViewControllerFactory.swift in Sources */,
58B26E2A2943545A00D5980C /* NotificationManagerDelegate.swift in Sources */,
7A8A19072CE4E9D3000BCB5B /* SettingsInfoView.swift in Sources */,
7AA1309B2D0048D800640DF9 /* MainButton.swift in Sources */,
58A1AA8C23F5584C009F7EA6 /* ConnectionPanelView.swift in Sources */,
5878A27B2909649A0096FC88 /* CustomOverlayRenderer.swift in Sources */,
7A8A19052CE4E9A9000BCB5B /* SwitchRowView.swift in Sources */,
Expand Down Expand Up @@ -5900,6 +5934,7 @@
586C0D872B03D39600E7CDD7 /* AccessMethodCellReuseIdentifier.swift in Sources */,
7A9CCCBD2A96302800DD6A34 /* LoginCoordinator.swift in Sources */,
7A7B3AB62C6DE4DA00D4BCCE /* RestorePurchasesView.swift in Sources */,
7A0EAE9E2D01BCBF00D3EB8B /* View+Size.swift in Sources */,
58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */,
F09A29822A9F8AD200EA3B6F /* RedeemVoucherInteractor.swift in Sources */,
58138E61294871C600684F0C /* DeviceDataThrottling.swift in Sources */,
Expand All @@ -5924,7 +5959,10 @@
586A950E290125F3007BAF2B /* ProductsRequestOperation.swift in Sources */,
7AF9BE902A39F26000DBFEDB /* Collection+Sorting.swift in Sources */,
58F19E35228C15BA00C7710B /* SpinnerActivityIndicatorView.swift in Sources */,
7A0EAE9A2D01B41500D3EB8B /* MainButtonStyle.swift in Sources */,
58CEB3022AFD365600E6E088 /* SwitchCellContentConfiguration.swift in Sources */,
7AA130A12D01B1E200640DF9 /* SplitMainButton.swift in Sources */,
7AA1309F2D007B2500640DF9 /* VisualEffectView.swift in Sources */,
7A9CCCB52A96302800DD6A34 /* AddCreditSucceededCoordinator.swift in Sources */,
7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */,
7A6F2FAB2AFD3097006D0856 /* CustomDNSCellFactory.swift in Sources */,
Expand Down Expand Up @@ -6038,7 +6076,6 @@
58B93A1326C3F13600A55733 /* TunnelState.swift in Sources */,
586C0D832B03D2FF00E7CDD7 /* ShadowsocksSectionHandler.swift in Sources */,
58B26E262943522400D5980C /* NotificationProvider.swift in Sources */,
7A8A190C2CE618D3000BCB5B /* View+Size.swift in Sources */,
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
F0DA87492A9CBA9F006044F1 /* AccountDeviceRow.swift in Sources */,
58FF9FE42B075BDD00E4C97D /* EditAccessMethodItemIdentifier.swift in Sources */,
Expand Down Expand Up @@ -6068,6 +6105,7 @@
58EFC7712AFB45E500E9F4CB /* SettingsChildCoordinator.swift in Sources */,
7A8A19102CEE391B000BCB5B /* RowSeparator.swift in Sources */,
58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */,
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */,
F0E8CC0A2A4EE127007ED3B4 /* SetupAccountCompletedContentView.swift in Sources */,
581DA2752A1E283E0046ED47 /* WgKeyRotation.swift in Sources */,
5827B0BB2B14A28300CCBBA1 /* MethodTestingStatusCellContentView.swift in Sources */,
Expand Down
6 changes: 5 additions & 1 deletion ios/MullvadVPN/Extensions/UIColor+Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
// Copyright © 2019 Mullvad VPN AB. All rights reserved.
//

import UIKit
import SwiftUI

extension UIColor {
var color: Color {
Color(self)
}

/// Returns the color lighter by the given percent (in range from 0..1)
func lightened(by percent: CGFloat) -> UIColor? {
darkened(by: -percent)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "MapPNG.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions ios/MullvadVPN/UI appearance/UIMetrics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ enum UIMetrics {
static let inRowHeight: CGFloat = 22
static let outRowHeight: CGFloat = 44
}

enum MainButton {
static let cornerRadius: CGFloat = 4
}
}

extension UIMetrics {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//
// ConnectionView.swift
// MullvadVPN
//
// Created by Jon Petersson on 2024-12-03.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

// TODO: Replace all hardcoded values with real values dependent on tunnel state. To be addressed in upcoming PR.

struct ConnectionView: View {
var body: some View {
ZStack {
BlurView()

VStack(alignment: .leading, spacing: 16) {
ConnectionPanel()
ButtonPanel()
}
.padding(16)
}
.cornerRadius(12)
.padding(16)
// Importing UIView in SwitftUI (see BlurView) has sizing limitations, so we need to help the view
// understand its width constraints.
.frame(maxWidth: UIScreen.main.bounds.width)
}
}

#Preview {
ZStack {
VStack {
Spacer()
ConnectionView()
}
}
.background(UIColor.secondaryColor.color)
.ignoresSafeArea()
}

private struct BlurView: View {
var body: some View {
Spacer()
.overlay {
VisualEffectView(effect: UIBlurEffect(style: .dark))
.opacity(0.8)
}
}
}

private struct ConnectionPanel: View {
var body: some View {
VStack(alignment: .leading) {
Text("Connected")
.textCase(.uppercase)
.font(.title3.weight(.semibold))
.foregroundStyle(UIColor.successColor.color)
.padding(.bottom, 4)
Text("Country, City")
.font(.title3.weight(.semibold))
.foregroundStyle(UIColor.primaryTextColor.color)
Text("Server")
.font(.body)
.foregroundStyle(UIColor.primaryTextColor.color.opacity(0.6))
}
}
}

private struct ButtonPanel: View {
var body: some View {
VStack(spacing: 16) {
SplitMainButton(
text: "Switch location",
image: .iconReload,
style: .default,
primaryAction: {
print("Switch location tapped")
}, secondaryAction: {
print("Reload tapped")
}
)

MainButton(
text: "Cancel",
style: .danger
) {
print("Cancel tapped")
}
}
}
}
34 changes: 34 additions & 0 deletions ios/MullvadVPN/Views/MainButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Untitled.swift
// MullvadVPN
//
// Created by Jon Petersson on 2024-12-04.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

struct MainButton: View {
var text: String
var style: MainButtonStyle.Style

var action: () -> Void

var body: some View {
Button(action: action, label: {
HStack {
Spacer()
Text(text)
Spacer()
}
})
.buttonStyle(MainButtonStyle(style))
.cornerRadius(UIMetrics.MainButton.cornerRadius)
}
}

#Preview {
MainButton(text: "Connect", style: .default) {
print("Tapped")
}
}
49 changes: 49 additions & 0 deletions ios/MullvadVPN/Views/MainButtonStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// MainButtonStyle.swift
// MullvadVPN
//
// Created by Jon Petersson on 2024-12-05.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

struct MainButtonStyle: ButtonStyle {
@State var style: Style

init(_ style: Style) {
self.style = style
}

func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 8)
.frame(height: 44)
.foregroundColor(
configuration.isPressed
? UIColor.secondaryTextColor.color
: UIColor.primaryTextColor.color
)
.background(style.color)
.font(.body.weight(.semibold))
}
}

extension MainButtonStyle {
enum Style {
case `default`
case danger
case success

var color: Color {
switch self {
case .default:
Color(UIColor.primaryColor)
case .danger:
Color(UIColor.dangerColor)
case .success:
Color(UIColor.successColor)
}
}
}
}
Loading

0 comments on commit c12da24

Please sign in to comment.