Skip to content

Commit a7e4fd6

Browse files
committed
Add foundation for new connection view
1 parent 8024c16 commit a7e4fd6

File tree

8 files changed

+306
-5
lines changed

8 files changed

+306
-5
lines changed

ios/MullvadVPN.xcodeproj/project.pbxproj

+42-4
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@
462462
7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */; };
463463
7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
464464
7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */; };
465+
7A0EAE9A2D01B41500D3EB8B /* MainButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */; };
466+
7A0EAE9E2D01BCBF00D3EB8B /* View+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */; };
465467
7A11DD0B2A9495D400098CD8 /* AppRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5802EBC42A8E44AC00E5CE4C /* AppRoutes.swift */; };
466468
7A12D0762B062D5C00E9602D /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */; };
467469
7A12D0772B062D6500E9602D /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */; };
@@ -563,7 +565,6 @@
563565
7A8A19052CE4E9A9000BCB5B /* SwitchRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19042CE4E9A5000BCB5B /* SwitchRowView.swift */; };
564566
7A8A19072CE4E9D3000BCB5B /* SettingsInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19062CE4E9CC000BCB5B /* SettingsInfoView.swift */; };
565567
7A8A190A2CE5FFE9000BCB5B /* SettingsDAITAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19092CE5FFDF000BCB5B /* SettingsDAITAView.swift */; };
566-
7A8A190C2CE618D3000BCB5B /* View+Size.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190B2CE618CE000BCB5B /* View+Size.swift */; };
567568
7A8A190E2CEB77C1000BCB5B /* SettingsRowViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190D2CEB77B7000BCB5B /* SettingsRowViewFooter.swift */; };
568569
7A8A19102CEE391B000BCB5B /* RowSeparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */; };
569570
7A8A19122CEF1E68000BCB5B /* SettingsInfoContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A19112CEF1E58000BCB5B /* SettingsInfoContainerView.swift */; };
@@ -605,6 +606,10 @@
605606
7A9F293D2CAD2FD5005F2089 /* InfoModalConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */; };
606607
7A9FA1422A2E3306000B728D /* CheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1412A2E3306000B728D /* CheckboxView.swift */; };
607608
7A9FA1442A2E3FE5000B728D /* CheckableSettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */; };
609+
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130982CFF365A00640DF9 /* ConnectionView.swift */; };
610+
7AA1309B2D0048D800640DF9 /* MainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA1309A2D0048D800640DF9 /* MainButton.swift */; };
611+
7AA1309F2D007B2500640DF9 /* VisualEffectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */; };
612+
7AA130A12D01B1E200640DF9 /* SplitMainButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */; };
608613
7AA513862BC91C6B00D081A4 /* LogRotationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */; };
609614
7AA7046A2C8EFE2B0045699D /* StoredRelays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA704682C8EFE050045699D /* StoredRelays.swift */; };
610615
7AB2B6702BA1EB8C00B03E3B /* ListCustomListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */; };
@@ -1834,6 +1839,8 @@
18341839
7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+FuzzyMatch.swift"; sourceTree = "<group>"; };
18351840
7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessbilityIdentifier.swift; sourceTree = "<group>"; };
18361841
7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Coordinator+Router.swift"; sourceTree = "<group>"; };
1842+
7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButtonStyle.swift; sourceTree = "<group>"; };
1843+
7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
18371844
7A12D0752B062D5C00E9602D /* URLSessionProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionProtocol.swift; sourceTree = "<group>"; };
18381845
7A1A26422A2612AE00B978AA /* PaymentAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentAlertPresenter.swift; sourceTree = "<group>"; };
18391846
7A1A26442A29CEF700B978AA /* RelayFilterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayFilterViewController.swift; sourceTree = "<group>"; };
@@ -1923,7 +1930,6 @@
19231930
7A8A19042CE4E9A5000BCB5B /* SwitchRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchRowView.swift; sourceTree = "<group>"; };
19241931
7A8A19062CE4E9CC000BCB5B /* SettingsInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInfoView.swift; sourceTree = "<group>"; };
19251932
7A8A19092CE5FFDF000BCB5B /* SettingsDAITAView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDAITAView.swift; sourceTree = "<group>"; };
1926-
7A8A190B2CE618CE000BCB5B /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
19271933
7A8A190D2CEB77B7000BCB5B /* SettingsRowViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRowViewFooter.swift; sourceTree = "<group>"; };
19281934
7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RowSeparator.swift; sourceTree = "<group>"; };
19291935
7A8A19112CEF1E58000BCB5B /* SettingsInfoContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInfoContainerView.swift; sourceTree = "<group>"; };
@@ -1962,6 +1968,11 @@
19621968
7A9F293C2CAD2FCF005F2089 /* InfoModalConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoModalConfig.swift; sourceTree = "<group>"; };
19631969
7A9FA1412A2E3306000B728D /* CheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxView.swift; sourceTree = "<group>"; };
19641970
7A9FA1432A2E3FE5000B728D /* CheckableSettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckableSettingsCell.swift; sourceTree = "<group>"; };
1971+
7AA130982CFF365A00640DF9 /* ConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionView.swift; sourceTree = "<group>"; };
1972+
7AA1309A2D0048D800640DF9 /* MainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainButton.swift; sourceTree = "<group>"; };
1973+
7AA1309C2D0072F900640DF9 /* View+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Size.swift"; sourceTree = "<group>"; };
1974+
7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisualEffectView.swift; sourceTree = "<group>"; };
1975+
7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitMainButton.swift; sourceTree = "<group>"; };
19651976
7AA513852BC91C6B00D081A4 /* LogRotationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotationTests.swift; sourceTree = "<group>"; };
19661977
7AA704682C8EFE050045699D /* StoredRelays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredRelays.swift; sourceTree = "<group>"; };
19671978
7AB2B66E2BA1EB8C00B03E3B /* ListCustomListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCustomListViewController.swift; sourceTree = "<group>"; };
@@ -2982,6 +2993,7 @@
29822993
583FE01E29C197D5006E85F9 /* Tunnel */ = {
29832994
isa = PBXGroup;
29842995
children = (
2996+
7AA130972CFF364F00640DF9 /* FeatureIndicators */,
29852997
58A1AA8B23F5584B009F7EA6 /* ConnectionPanelView.swift */,
29862998
5878A27A2909649A0096FC88 /* CustomOverlayRenderer.swift */,
29872999
58907D9424D17B4E00CFC3F5 /* DisconnectSplitButton.swift */,
@@ -3012,10 +3024,14 @@
30123024
F03580242A13842C00E5DAFD /* IncreasedHitButton.swift */,
30133025
7A9F29382CABFAEC005F2089 /* InfoHeaderView.swift */,
30143026
7A5869942B32E9C700640D27 /* LinkButton.swift */,
3027+
7AA1309A2D0048D800640DF9 /* MainButton.swift */,
3028+
7A0EAE992D01B41500D3EB8B /* MainButtonStyle.swift */,
30153029
7A8A190F2CEE3918000BCB5B /* RowSeparator.swift */,
30163030
58F19E34228C15BA00C7710B /* SpinnerActivityIndicatorView.swift */,
3031+
7AA130A02D01B1E200640DF9 /* SplitMainButton.swift */,
30173032
E1FD0DF428AA7CE400299DB4 /* StatusActivityView.swift */,
30183033
58EF581025D69DB400AEBA94 /* StatusImageView.swift */,
3034+
7AA1309E2D007B2500640DF9 /* VisualEffectView.swift */,
30193035
);
30203036
path = Views;
30213037
sourceTree = "<group>";
@@ -3091,7 +3107,7 @@
30913107
7A21DACE2A30AA3700A787A9 /* UITextField+Appearance.swift */,
30923108
5878F4FF29CDA742003D4BE2 /* UIView+AutoLayoutBuilder.swift */,
30933109
7A516C2D2B6D357500BBD33D /* URL+Scoping.swift */,
3094-
7A8A190B2CE618CE000BCB5B /* View+Size.swift */,
3110+
7A0EAE9D2D01BCBF00D3EB8B /* View+Size.swift */,
30953111
7A8A18FA2CE4B66C000BCB5B /* View+TapAreaSize.swift */,
30963112
);
30973113
path = Extensions;
@@ -3593,6 +3609,7 @@
35933609
A9D9A4C12C36D53C004088DD /* MullvadRustRuntimeTests */,
35943610
58CE5E61224146200008646E /* Products */,
35953611
584F991F2902CBDD001F858D /* Frameworks */,
3612+
7A0EAE982D01B29E00D3EB8B /* Recovered References */,
35963613
);
35973614
sourceTree = "<group>";
35983615
};
@@ -3893,6 +3910,14 @@
38933910
path = Edit;
38943911
sourceTree = "<group>";
38953912
};
3913+
7A0EAE982D01B29E00D3EB8B /* Recovered References */ = {
3914+
isa = PBXGroup;
3915+
children = (
3916+
7AA1309C2D0072F900640DF9 /* View+Size.swift */,
3917+
);
3918+
name = "Recovered References";
3919+
sourceTree = "<group>";
3920+
};
38963921
7A2960F72A964A3500389B82 /* Alert */ = {
38973922
isa = PBXGroup;
38983923
children = (
@@ -4024,6 +4049,14 @@
40244049
path = SelectLocation;
40254050
sourceTree = "<group>";
40264051
};
4052+
7AA130972CFF364F00640DF9 /* FeatureIndicators */ = {
4053+
isa = PBXGroup;
4054+
children = (
4055+
7AA130982CFF365A00640DF9 /* ConnectionView.swift */,
4056+
);
4057+
path = FeatureIndicators;
4058+
sourceTree = "<group>";
4059+
};
40274060
7AD63A422CDA661B00445268 /* Extensions */ = {
40284061
isa = PBXGroup;
40294062
children = (
@@ -5830,6 +5863,7 @@
58305863
7A8A19282CF603EB000BCB5B /* SettingsViewControllerFactory.swift in Sources */,
58315864
58B26E2A2943545A00D5980C /* NotificationManagerDelegate.swift in Sources */,
58325865
7A8A19072CE4E9D3000BCB5B /* SettingsInfoView.swift in Sources */,
5866+
7AA1309B2D0048D800640DF9 /* MainButton.swift in Sources */,
58335867
58A1AA8C23F5584C009F7EA6 /* ConnectionPanelView.swift in Sources */,
58345868
5878A27B2909649A0096FC88 /* CustomOverlayRenderer.swift in Sources */,
58355869
7A8A19052CE4E9A9000BCB5B /* SwitchRowView.swift in Sources */,
@@ -5900,6 +5934,7 @@
59005934
586C0D872B03D39600E7CDD7 /* AccessMethodCellReuseIdentifier.swift in Sources */,
59015935
7A9CCCBD2A96302800DD6A34 /* LoginCoordinator.swift in Sources */,
59025936
7A7B3AB62C6DE4DA00D4BCCE /* RestorePurchasesView.swift in Sources */,
5937+
7A0EAE9E2D01BCBF00D3EB8B /* View+Size.swift in Sources */,
59035938
58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */,
59045939
F09A29822A9F8AD200EA3B6F /* RedeemVoucherInteractor.swift in Sources */,
59055940
58138E61294871C600684F0C /* DeviceDataThrottling.swift in Sources */,
@@ -5924,7 +5959,10 @@
59245959
586A950E290125F3007BAF2B /* ProductsRequestOperation.swift in Sources */,
59255960
7AF9BE902A39F26000DBFEDB /* Collection+Sorting.swift in Sources */,
59265961
58F19E35228C15BA00C7710B /* SpinnerActivityIndicatorView.swift in Sources */,
5962+
7A0EAE9A2D01B41500D3EB8B /* MainButtonStyle.swift in Sources */,
59275963
58CEB3022AFD365600E6E088 /* SwitchCellContentConfiguration.swift in Sources */,
5964+
7AA130A12D01B1E200640DF9 /* SplitMainButton.swift in Sources */,
5965+
7AA1309F2D007B2500640DF9 /* VisualEffectView.swift in Sources */,
59285966
7A9CCCB52A96302800DD6A34 /* AddCreditSucceededCoordinator.swift in Sources */,
59295967
7A0C0F632A979C4A0058EFCE /* Coordinator+Router.swift in Sources */,
59305968
7A6F2FAB2AFD3097006D0856 /* CustomDNSCellFactory.swift in Sources */,
@@ -6038,7 +6076,6 @@
60386076
58B93A1326C3F13600A55733 /* TunnelState.swift in Sources */,
60396077
586C0D832B03D2FF00E7CDD7 /* ShadowsocksSectionHandler.swift in Sources */,
60406078
58B26E262943522400D5980C /* NotificationProvider.swift in Sources */,
6041-
7A8A190C2CE618D3000BCB5B /* View+Size.swift in Sources */,
60426079
58CE5E64224146200008646E /* AppDelegate.swift in Sources */,
60436080
F0DA87492A9CBA9F006044F1 /* AccountDeviceRow.swift in Sources */,
60446081
58FF9FE42B075BDD00E4C97D /* EditAccessMethodItemIdentifier.swift in Sources */,
@@ -6068,6 +6105,7 @@
60686105
58EFC7712AFB45E500E9F4CB /* SettingsChildCoordinator.swift in Sources */,
60696106
7A8A19102CEE391B000BCB5B /* RowSeparator.swift in Sources */,
60706107
58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */,
6108+
7AA130992CFF365D00640DF9 /* ConnectionView.swift in Sources */,
60716109
F0E8CC0A2A4EE127007ED3B4 /* SetupAccountCompletedContentView.swift in Sources */,
60726110
581DA2752A1E283E0046ED47 /* WgKeyRotation.swift in Sources */,
60736111
5827B0BB2B14A28300CCBBA1 /* MethodTestingStatusCellContentView.swift in Sources */,

ios/MullvadVPN/Extensions/UIColor+Helpers.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
// Copyright © 2019 Mullvad VPN AB. All rights reserved.
77
//
88

9-
import UIKit
9+
import SwiftUI
1010

1111
extension UIColor {
12+
var color: Color {
13+
Color(self)
14+
}
15+
1216
/// Returns the color lighter by the given percent (in range from 0..1)
1317
func lightened(by percent: CGFloat) -> UIColor? {
1418
darkened(by: -percent)

ios/MullvadVPN/UI appearance/UIMetrics.swift

+4
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ enum UIMetrics {
134134
static let inRowHeight: CGFloat = 22
135135
static let outRowHeight: CGFloat = 44
136136
}
137+
138+
enum MainButton {
139+
static let cornerRadius: CGFloat = 4
140+
}
137141
}
138142

139143
extension UIMetrics {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//
2+
// ConnectionView.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-12-03.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
// TODO: Replace all hardcoded values with real values dependent on tunnel state. To be addressed in upcoming PR.
12+
13+
struct ConnectionView: View {
14+
var body: some View {
15+
ZStack {
16+
BlurView()
17+
18+
VStack(alignment: .leading, spacing: 16) {
19+
ConnectionPanel()
20+
ButtonPanel()
21+
}
22+
.padding(16)
23+
}
24+
.cornerRadius(12)
25+
.padding(16)
26+
// Importing UIView in SwitftUI (see BlurView) has sizing limitations, so we need to help the view
27+
// understand its width constraints.
28+
.frame(maxWidth: UIScreen.main.bounds.width)
29+
}
30+
}
31+
32+
#Preview {
33+
ZStack {
34+
VStack {
35+
Spacer()
36+
ConnectionView()
37+
}
38+
}
39+
.background(UIColor.secondaryColor.color)
40+
.ignoresSafeArea()
41+
}
42+
43+
private struct BlurView: View {
44+
var body: some View {
45+
Spacer()
46+
.overlay {
47+
VisualEffectView(effect: UIBlurEffect(style: .dark))
48+
.opacity(0.8)
49+
}
50+
}
51+
}
52+
53+
private struct ConnectionPanel: View {
54+
var body: some View {
55+
VStack(alignment: .leading) {
56+
Text("Connected")
57+
.textCase(.uppercase)
58+
.font(.title3.weight(.semibold))
59+
.foregroundStyle(UIColor.successColor.color)
60+
.padding(.bottom, 4)
61+
Text("Country, City")
62+
.font(.title3.weight(.semibold))
63+
.foregroundStyle(UIColor.primaryTextColor.color)
64+
Text("Server")
65+
.font(.body)
66+
.foregroundStyle(UIColor.primaryTextColor.color.opacity(0.6))
67+
}
68+
}
69+
}
70+
71+
private struct ButtonPanel: View {
72+
var body: some View {
73+
VStack(spacing: 16) {
74+
SplitMainButton(
75+
text: "Switch location",
76+
image: .iconReload,
77+
style: .default,
78+
primaryAction: {
79+
print("Switch location tapped")
80+
}, secondaryAction: {
81+
print("Reload tapped")
82+
}
83+
)
84+
85+
MainButton(
86+
text: "Cancel",
87+
style: .danger
88+
) {
89+
print("Cancel tapped")
90+
}
91+
}
92+
}
93+
}

ios/MullvadVPN/Views/MainButton.swift

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// Untitled.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-12-04.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
struct MainButton: View {
12+
var text: String
13+
var style: MainButtonStyle.Style
14+
15+
var action: () -> Void
16+
17+
var body: some View {
18+
Button(action: action, label: {
19+
HStack {
20+
Spacer()
21+
Text(text)
22+
Spacer()
23+
}
24+
})
25+
.buttonStyle(MainButtonStyle(style))
26+
.cornerRadius(UIMetrics.MainButton.cornerRadius)
27+
}
28+
}
29+
30+
#Preview {
31+
MainButton(text: "Connect", style: .default) {
32+
print("Tapped")
33+
}
34+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// MainButtonStyle.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-12-05.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
struct MainButtonStyle: ButtonStyle {
12+
@State var style: Style
13+
14+
init(_ style: Style) {
15+
self.style = style
16+
}
17+
18+
func makeBody(configuration: Configuration) -> some View {
19+
configuration.label
20+
.padding(.horizontal, 8)
21+
.frame(height: 44)
22+
.foregroundColor(
23+
configuration.isPressed
24+
? UIColor.secondaryTextColor.color
25+
: UIColor.primaryTextColor.color
26+
)
27+
.background(style.color)
28+
.font(.body.weight(.semibold))
29+
}
30+
}
31+
32+
extension MainButtonStyle {
33+
enum Style {
34+
case `default`
35+
case danger
36+
case success
37+
38+
var color: Color {
39+
switch self {
40+
case .default:
41+
Color(UIColor.primaryColor)
42+
case .danger:
43+
Color(UIColor.dangerColor)
44+
case .success:
45+
Color(UIColor.successColor)
46+
}
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)