Skip to content

Commit

Permalink
Add UI for saving a custom list
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Petersson committed Feb 13, 2024
1 parent da4e1c2 commit 98ce0f7
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
16 changes: 16 additions & 0 deletions ios/MullvadVPN.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,8 @@
58FF9FF02B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FF9FEF2B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift */; };
58FF9FF42B07C61B00E4C97D /* AccessMethodValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FF9FF32B07C61B00E4C97D /* AccessMethodValidationError.swift */; };
7A02D4EB2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */; };
7A038FD82B75033200950251 /* CustomListSaveAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A038FD72B75033200950251 /* CustomListSaveAlert.swift */; };
7A038FDA2B7633A400950251 /* SUIAppButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A038FD92B7633A400950251 /* SUIAppButton.swift */; };
7A09C98129D99215000C2CAC /* String+FuzzyMatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A09C98029D99215000C2CAC /* String+FuzzyMatch.swift */; };
7A0B311E2B303A0D004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
7A0B311F2B303A11004B12E0 /* AccessbilityIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0B311D2B303A0D004B12E0 /* AccessbilityIdentifier.swift */; };
Expand Down Expand Up @@ -1660,6 +1662,8 @@
58FF9FEF2B07C4D300E4C97D /* PersistentAccessMethod+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PersistentAccessMethod+ViewModel.swift"; sourceTree = "<group>"; };
58FF9FF32B07C61B00E4C97D /* AccessMethodValidationError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessMethodValidationError.swift; sourceTree = "<group>"; };
7A02D4EA2A9CEC7A00C19E31 /* MullvadVPNScreenshots.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MullvadVPNScreenshots.xctestplan; sourceTree = "<group>"; };
7A038FD72B75033200950251 /* CustomListSaveAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomListSaveAlert.swift; sourceTree = "<group>"; };
7A038FD92B7633A400950251 /* SUIAppButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUIAppButton.swift; sourceTree = "<group>"; };
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>"; };
Expand Down Expand Up @@ -2282,6 +2286,7 @@
583FE01729C196F3006E85F9 /* SelectLocation */ = {
isa = PBXGroup;
children = (
7A038FD62B75031400950251 /* CustomLists */,
58435AC129CB2A350099C71B /* LocationCellFactory.swift */,
583DA21325FA4B5C00318683 /* LocationDataSource.swift */,
5888AD82227B11080051EB06 /* SelectLocationCell.swift */,
Expand Down Expand Up @@ -3306,6 +3311,15 @@
path = Edit;
sourceTree = "<group>";
};
7A038FD62B75031400950251 /* CustomLists */ = {
isa = PBXGroup;
children = (
7A038FD72B75033200950251 /* CustomListSaveAlert.swift */,
7A038FD92B7633A400950251 /* SUIAppButton.swift */,
);
path = CustomLists;
sourceTree = "<group>";
};
7A2960F72A964A3500389B82 /* Alert */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -5023,6 +5037,7 @@
5827B0B02B0F4CCD00CCBBA1 /* ListAccessMethodViewControllerDelegate.swift in Sources */,
588D7EE02AF3A595005DF40A /* ListAccessMethodInteractor.swift in Sources */,
58607A4D2947287800BC467D /* AccountExpiryInAppNotificationProvider.swift in Sources */,
7A038FDA2B7633A400950251 /* SUIAppButton.swift in Sources */,
58C8191829FAA2C400DEB1B4 /* NotificationConfiguration.swift in Sources */,
58FF9FE82B07650A00E4C97D /* ButtonCellContentConfiguration.swift in Sources */,
5827B0A82B0F49EF00CCBBA1 /* ProxyConfigurationInteractorProtocol.swift in Sources */,
Expand Down Expand Up @@ -5129,6 +5144,7 @@
58EFC76E2AFB3BDA00E9F4CB /* ListAccessMethodCoordinator.swift in Sources */,
5827B0B92B14A1C700CCBBA1 /* MethodTestingStatusCellContentConfiguration.swift in Sources */,
7A42DEC92A05164100B209BE /* SettingsInputCell.swift in Sources */,
7A038FD82B75033200950251 /* CustomListSaveAlert.swift in Sources */,
5803B4B22940A48700C23744 /* TunnelStore.swift in Sources */,
586A950F29012BEE007BAF2B /* AddressCacheTracker.swift in Sources */,
587B753D2666468F00DEF7E9 /* NotificationController.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// CustomListSaveAlert.swift
// MullvadVPN
//
// Created by Jon Petersson on 2024-02-08.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import SwiftUI

class CustomListSaveAlertViewModel: ObservableObject {
@Published var inputIsValid: Bool

init(inputIsValid: Bool = true) {
self.inputIsValid = inputIsValid
}
}

struct CustomListSaveAlert: View {
@State private var inputText = ""
@ObservedObject var viewModel: CustomListSaveAlertViewModel

var didTapSave: ((String) -> Void)?
var didTapCancel: (() -> Void)?

var body: some View {
GeometryReader(content: { geometry in
ZStack {
VStack(alignment: .leading, spacing: 8) {
Text("Edit list name")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(.white.opacity(0.8))
TextField("", text: $inputText)
.textFieldStyle(CustomTextFieldStyle())
ErrorLabel(inputIsValid: viewModel.inputIsValid)
VStack(spacing: 16) {
SUIAppButton(text: "Save", style: .success)
.frame(height: 42)
.onTapGesture { didTapSave?(inputText) }
SUIAppButton(text: "Cancel", style: .default)
.frame(height: 42)
.onTapGesture { didTapCancel?() }
}
}
.frame(
minWidth: 0,
maxWidth: geometry.size.width > UIMetrics.preferredFormSheetContentSize.width
? UIMetrics.preferredFormSheetContentSize.width
: .infinity
)
.padding(EdgeInsets(UIMetrics.CustomAlert.containerMargins))
.background(Color(.secondaryColor))
.cornerRadius(11)
}
.padding(EdgeInsets(UIMetrics.CustomAlert.containerMargins))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(Color.black.opacity(0.6))
.ignoresSafeArea()
})
}
}

struct CustomListSaveAlert_Previews: PreviewProvider {
static var previews: some View {
CustomListSaveAlert(viewModel: CustomListSaveAlertViewModel(inputIsValid: true))
CustomListSaveAlert(viewModel: CustomListSaveAlertViewModel(inputIsValid: false))
}
}

private struct CustomTextFieldStyle: TextFieldStyle {
func _body(configuration: TextField<Self._Label>) -> some View {
configuration
.padding(EdgeInsets(top: 6, leading: 8, bottom: 6, trailing: 8))
.background(Color.white)
.cornerRadius(4)
.font(.system(size: 15))
}
}

private struct ErrorLabel: View {
let inputIsValid: Bool

var body: some View {
Text("Name is already taken")
.font(.system(size: 12, weight: .semibold))
.foregroundColor(Color(.dangerColor))
.padding(.bottom, inputIsValid ? 0 : 4)
.opacity(inputIsValid ? 0 : 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// SUIAppButton.swift
// MullvadVPN
//
// Created by Jon Petersson on 2024-02-09.
// Copyright © 2024 Mullvad VPN AB. All rights reserved.
//

import MullvadTypes
import SwiftUI

/// SwiftUI wrapper for ``AppButton``.
struct SUIAppButton: UIViewRepresentable {
let text: String
let style: AppButton.Style

func makeUIView(context: Context) -> AppButton {
let button = AppButton(style: style)
button.setTitle(text, for: .normal)

return button
}

func updateUIView(_ appButton: AppButton, context: Context) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import MullvadLogging
import MullvadTypes
import UIKit

import SwiftUI

class TunnelViewController: UIViewController, RootContainment {
private let logger = Logger(label: "TunnelViewController")
private let interactor: TunnelViewControllerInteractor
Expand Down
2 changes: 2 additions & 0 deletions ios/build-wireguard-go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ if [ "$SOURCE_PACKAGES_PATH" == "" ]; then
# When archiving, Xcode sets the action to "install"
if [ "$ACTION" == "install" ]; then
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../SourcePackages"
elif [ "$ENABLE_PREVIEWS" == "YES" ]; then
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../../../../SourcePackages"
else
SOURCE_PACKAGES_PATH="$BUILD_DIR/../../SourcePackages"
fi
Expand Down

0 comments on commit 98ce0f7

Please sign in to comment.