Skip to content

Commit 98ce0f7

Browse files
author
Jon Petersson
committedFeb 13, 2024
Add UI for saving a custom list
1 parent da4e1c2 commit 98ce0f7

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed
 

‎ios/MullvadVPN.xcodeproj/project.pbxproj

+16
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,8 @@
464464
58FF9FF02B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FF9FEF2B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift */; };
465465
58FF9FF42B07C61B00E4C97D /* AccessMethodValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FF9FF32B07C61B00E4C97D /* AccessMethodValidationError.swift */; };
466466
7A02D4EB2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */; };
467+
7A038FD82B75033200950251 /* CustomListSaveAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A038FD72B75033200950251 /* CustomListSaveAlert.swift */; };
468+
7A038FDA2B7633A400950251 /* SUIAppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A038FD92B7633A400950251 /* SUIAppButton.swift */; };
467469
7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */; };
468470
7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
469471
7A0B311F2B303A11004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
@@ -1660,6 +1662,8 @@
16601662
58FF9FEF2B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PersistentAccessMethod+ViewModel.swift"; sourceTree = "<group>"; };
16611663
58FF9FF32B07C61B00E4C97D /* AccessMethodValidationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodValidationError.swift; sourceTree = "<group>"; };
16621664
7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MullvadVPNScreenshots.xctestplan; sourceTree = "<group>"; };
1665+
7A038FD72B75033200950251 /* CustomListSaveAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomListSaveAlert.swift; sourceTree = "<group>"; };
1666+
7A038FD92B7633A400950251 /* SUIAppButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUIAppButton.swift; sourceTree = "<group>"; };
16631667
7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+FuzzyMatch.swift"; sourceTree = "<group>"; };
16641668
7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessbilityIdentifier.swift; sourceTree = "<group>"; };
16651669
7A0C0F622A979C4A0058EFCE /* Coordinator+Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Coordinator+Router.swift"; sourceTree = "<group>"; };
@@ -2282,6 +2286,7 @@
22822286
583FE01729C196F3006E85F9 /* SelectLocation */ = {
22832287
isa = PBXGroup;
22842288
children = (
2289+
7A038FD62B75031400950251 /* CustomLists */,
22852290
58435AC129CB2A350099C71B /* LocationCellFactory.swift */,
22862291
583DA21325FA4B5C00318683 /* LocationDataSource.swift */,
22872292
5888AD82227B11080051EB06 /* SelectLocationCell.swift */,
@@ -3306,6 +3311,15 @@
33063311
path = Edit;
33073312
sourceTree = "<group>";
33083313
};
3314+
7A038FD62B75031400950251 /* CustomLists */ = {
3315+
isa = PBXGroup;
3316+
children = (
3317+
7A038FD72B75033200950251 /* CustomListSaveAlert.swift */,
3318+
7A038FD92B7633A400950251 /* SUIAppButton.swift */,
3319+
);
3320+
path = CustomLists;
3321+
sourceTree = "<group>";
3322+
};
33093323
7A2960F72A964A3500389B82 /* Alert */ = {
33103324
isa = PBXGroup;
33113325
children = (
@@ -5023,6 +5037,7 @@
50235037
5827B0B02B0F4CCD00CCBBA1 /* ListAccessMethodViewControllerDelegate.swift in Sources */,
50245038
588D7EE02AF3A595005DF40A /* ListAccessMethodInteractor.swift in Sources */,
50255039
58607A4D2947287800BC467D /* AccountExpiryInAppNotificationProvider.swift in Sources */,
5040+
7A038FDA2B7633A400950251 /* SUIAppButton.swift in Sources */,
50265041
58C8191829FAA2C400DEB1B4 /* NotificationConfiguration.swift in Sources */,
50275042
58FF9FE82B07650A00E4C97D /* ButtonCellContentConfiguration.swift in Sources */,
50285043
5827B0A82B0F49EF00CCBBA1 /* ProxyConfigurationInteractorProtocol.swift in Sources */,
@@ -5129,6 +5144,7 @@
51295144
58EFC76E2AFB3BDA00E9F4CB /* ListAccessMethodCoordinator.swift in Sources */,
51305145
5827B0B92B14A1C700CCBBA1 /* MethodTestingStatusCellContentConfiguration.swift in Sources */,
51315146
7A42DEC92A05164100B209BE /* SettingsInputCell.swift in Sources */,
5147+
7A038FD82B75033200950251 /* CustomListSaveAlert.swift in Sources */,
51325148
5803B4B22940A48700C23744 /* TunnelStore.swift in Sources */,
51335149
586A950F29012BEE007BAF2B /* AddressCacheTracker.swift in Sources */,
51345150
587B753D2666468F00DEF7E9 /* NotificationController.swift in Sources */,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// CustomListSaveAlert.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-02-08.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import SwiftUI
10+
11+
class CustomListSaveAlertViewModel: ObservableObject {
12+
@Published var inputIsValid: Bool
13+
14+
init(inputIsValid: Bool = true) {
15+
self.inputIsValid = inputIsValid
16+
}
17+
}
18+
19+
struct CustomListSaveAlert: View {
20+
@State private var inputText = ""
21+
@ObservedObject var viewModel: CustomListSaveAlertViewModel
22+
23+
var didTapSave: ((String) -> Void)?
24+
var didTapCancel: (() -> Void)?
25+
26+
var body: some View {
27+
GeometryReader(content: { geometry in
28+
ZStack {
29+
VStack(alignment: .leading, spacing: 8) {
30+
Text("Edit list name")
31+
.font(.system(size: 12, weight: .semibold))
32+
.foregroundColor(.white.opacity(0.8))
33+
TextField("", text: $inputText)
34+
.textFieldStyle(CustomTextFieldStyle())
35+
ErrorLabel(inputIsValid: viewModel.inputIsValid)
36+
VStack(spacing: 16) {
37+
SUIAppButton(text: "Save", style: .success)
38+
.frame(height: 42)
39+
.onTapGesture { didTapSave?(inputText) }
40+
SUIAppButton(text: "Cancel", style: .default)
41+
.frame(height: 42)
42+
.onTapGesture { didTapCancel?() }
43+
}
44+
}
45+
.frame(
46+
minWidth: 0,
47+
maxWidth: geometry.size.width > UIMetrics.preferredFormSheetContentSize.width
48+
? UIMetrics.preferredFormSheetContentSize.width
49+
: .infinity
50+
)
51+
.padding(EdgeInsets(UIMetrics.CustomAlert.containerMargins))
52+
.background(Color(.secondaryColor))
53+
.cornerRadius(11)
54+
}
55+
.padding(EdgeInsets(UIMetrics.CustomAlert.containerMargins))
56+
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
57+
.background(Color.black.opacity(0.6))
58+
.ignoresSafeArea()
59+
})
60+
}
61+
}
62+
63+
struct CustomListSaveAlert_Previews: PreviewProvider {
64+
static var previews: some View {
65+
CustomListSaveAlert(viewModel: CustomListSaveAlertViewModel(inputIsValid: true))
66+
CustomListSaveAlert(viewModel: CustomListSaveAlertViewModel(inputIsValid: false))
67+
}
68+
}
69+
70+
private struct CustomTextFieldStyle: TextFieldStyle {
71+
func _body(configuration: TextField<Self._Label>) -> some View {
72+
configuration
73+
.padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
74+
.background(Color.white)
75+
.cornerRadius(4)
76+
.font(.system(size: 15))
77+
}
78+
}
79+
80+
private struct ErrorLabel: View {
81+
let inputIsValid: Bool
82+
83+
var body: some View {
84+
Text("Name is already taken")
85+
.font(.system(size: 12, weight: .semibold))
86+
.foregroundColor(Color(.dangerColor))
87+
.padding(.bottom, inputIsValid ? 0 : 4)
88+
.opacity(inputIsValid ? 0 : 1)
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// SUIAppButton.swift
3+
// MullvadVPN
4+
//
5+
// Created by Jon Petersson on 2024-02-09.
6+
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
7+
//
8+
9+
import MullvadTypes
10+
import SwiftUI
11+
12+
/// SwiftUI wrapper for ``AppButton``.
13+
struct SUIAppButton: UIViewRepresentable {
14+
let text: String
15+
let style: AppButton.Style
16+
17+
func makeUIView(context: Context) -> AppButton {
18+
let button = AppButton(style: style)
19+
button.setTitle(text, for: .normal)
20+
21+
return button
22+
}
23+
24+
func updateUIView(_ appButton: AppButton, context: Context) {}
25+
}

‎ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import MullvadLogging
1111
import MullvadTypes
1212
import UIKit
1313

14+
import SwiftUI
15+
1416
class TunnelViewController: UIViewController, RootContainment {
1517
private let logger = Logger(label: "TunnelViewController")
1618
private let interactor: TunnelViewControllerInteractor

‎ios/build-wireguard-go.sh

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ if [ "$SOURCE_PACKAGES_PATH" == "" ]; then
2121
# When archiving, Xcode sets the action to "install"
2222
if [ "$ACTION" == "install" ]; then
2323
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../SourcePackages"
24+
elif [ "$ENABLE_PREVIEWS" == "YES" ]; then
25+
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../SourcePackages"
2426
else
2527
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../SourcePackages"
2628
fi

0 commit comments

Comments
 (0)
Failed to load comments.