From f4eef85175f6df937413b892a6813c4a905e5864 Mon Sep 17 00:00:00 2001 From: talksik Date: Fri, 17 Dec 2021 17:18:10 -0800 Subject: [PATCH] basic ui for both phone auth screens --- nirvana-ios.xcodeproj/project.pbxproj | 21 ++++ .../xcshareddata/swiftpm/Package.resolved | 9 ++ .../PhoneVerificationView.swift | 99 ++++++++++++++++++- .../PhoneVerificationViewModel.swift | 26 +++++ 4 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 nirvana-ios/Views/PhoneVerification/PhoneVerificationViewModel.swift diff --git a/nirvana-ios.xcodeproj/project.pbxproj b/nirvana-ios.xcodeproj/project.pbxproj index 462b74e..3125fc3 100644 --- a/nirvana-ios.xcodeproj/project.pbxproj +++ b/nirvana-ios.xcodeproj/project.pbxproj @@ -29,12 +29,14 @@ 89288EC7276756DF00E962C4 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = 89288EC6276756DF00E962C4 /* FirebaseDatabase */; }; 89288EC9276756DF00E962C4 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = 89288EC8276756DF00E962C4 /* FirebaseStorage */; }; 89288ECB27675B9F00E962C4 /* OnboardingTemplateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89288ECA27675B9F00E962C4 /* OnboardingTemplateView.swift */; }; + 89AD556F276D63E4001658E0 /* PopupView in Frameworks */ = {isa = PBXBuildFile; productRef = 89AD556E276D63E4001658E0 /* PopupView */; }; 89B46E71276893E200B74255 /* AuthSessionStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89B46E70276893E200B74255 /* AuthSessionStore.swift */; }; 89BCABE2276B3CB0009E9B10 /* NavigationStack in Frameworks */ = {isa = PBXBuildFile; productRef = 89BCABE1276B3CB0009E9B10 /* NavigationStack */; }; 89BCABE5276B3D58009E9B10 /* InnerCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BCABE4276B3D58009E9B10 /* InnerCircleView.swift */; }; 89BCABE7276B3D64009E9B10 /* InnerCircleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BCABE6276B3D64009E9B10 /* InnerCircleViewModel.swift */; }; 89BCABEB276D2A09009E9B10 /* PhoneVerificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BCABEA276D2A07009E9B10 /* PhoneVerificationView.swift */; }; 89BCABED276D2B05009E9B10 /* WavesGlassBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BCABEC276D2B05009E9B10 /* WavesGlassBackgroundView.swift */; }; + 89BCABF0276D53C4009E9B10 /* PhoneVerificationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BCABEF276D53C3009E9B10 /* PhoneVerificationViewModel.swift */; }; 89BDCDE527695DB900577829 /* NirvanaImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BDCDE427695DB900577829 /* NirvanaImage.swift */; }; 89BDCDE72769616600577829 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BDCDE62769616600577829 /* UIImage+Extension.swift */; }; 89BDCDEA27697F9C00577829 /* UserMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BDCDE927697F9C00577829 /* UserMenu.swift */; }; @@ -75,6 +77,7 @@ 89BCABE6276B3D64009E9B10 /* InnerCircleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InnerCircleViewModel.swift; sourceTree = ""; }; 89BCABEA276D2A07009E9B10 /* PhoneVerificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneVerificationView.swift; sourceTree = ""; }; 89BCABEC276D2B05009E9B10 /* WavesGlassBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WavesGlassBackgroundView.swift; sourceTree = ""; }; + 89BCABEF276D53C3009E9B10 /* PhoneVerificationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneVerificationViewModel.swift; sourceTree = ""; }; 89BDCDE427695DB900577829 /* NirvanaImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NirvanaImage.swift; sourceTree = ""; }; 89BDCDE62769616600577829 /* UIImage+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; 89BDCDE927697F9C00577829 /* UserMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserMenu.swift; sourceTree = ""; }; @@ -94,6 +97,7 @@ buildActionMask = 2147483647; files = ( 89288EC3276756DF00E962C4 /* FirebaseAnalytics in Frameworks */, + 89AD556F276D63E4001658E0 /* PopupView in Frameworks */, 89BCABE2276B3CB0009E9B10 /* NavigationStack in Frameworks */, 89288EC5276756DF00E962C4 /* FirebaseAuth in Frameworks */, 89288EC7276756DF00E962C4 /* FirebaseDatabase in Frameworks */, @@ -252,6 +256,7 @@ isa = PBXGroup; children = ( 89BCABEA276D2A07009E9B10 /* PhoneVerificationView.swift */, + 89BCABEF276D53C3009E9B10 /* PhoneVerificationViewModel.swift */, ); path = PhoneVerification; sourceTree = ""; @@ -314,6 +319,7 @@ 89288EC8276756DF00E962C4 /* FirebaseStorage */, 89F1386F2767F55F006680ED /* GoogleSignIn */, 89BCABE1276B3CB0009E9B10 /* NavigationStack */, + 89AD556E276D63E4001658E0 /* PopupView */, ); productName = "nirvana-ios"; productReference = 891A15DD27653A7000B26659 /* nirvana-ios.app */; @@ -347,6 +353,7 @@ 89288EC1276756DF00E962C4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 89F1386E2767F55F006680ED /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */, 89BCABE0276B3CB0009E9B10 /* XCRemoteSwiftPackageReference "swiftui-navigation-stack" */, + 89AD556D276D63E4001658E0 /* XCRemoteSwiftPackageReference "PopupView" */, ); productRefGroup = 891A15DE27653A7000B26659 /* Products */; projectDirPath = ""; @@ -402,6 +409,7 @@ 892179E42765FEB8001E6C60 /* FooterControlsView.swift in Sources */, 891A15FD276566B800B26659 /* constants.swift in Sources */, 89BCABE5276B3D58009E9B10 /* InnerCircleView.swift in Sources */, + 89BCABF0276D53C4009E9B10 /* PhoneVerificationViewModel.swift in Sources */, 89BDCDE72769616600577829 /* UIImage+Extension.swift in Sources */, 89F1386D2767EB19006680ED /* SignInView.swift in Sources */, 89BDCDF12769E64200577829 /* Firestore.swift in Sources */, @@ -626,6 +634,14 @@ minimumVersion = 8.0.0; }; }; + 89AD556D276D63E4001658E0 /* XCRemoteSwiftPackageReference "PopupView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/exyte/PopupView"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; 89BCABE0276B3CB0009E9B10 /* XCRemoteSwiftPackageReference "swiftui-navigation-stack" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/matteopuc/swiftui-navigation-stack.git"; @@ -665,6 +681,11 @@ package = 89288EC1276756DF00E962C4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; productName = FirebaseStorage; }; + 89AD556E276D63E4001658E0 /* PopupView */ = { + isa = XCSwiftPackageProductDependency; + package = 89AD556D276D63E4001658E0 /* XCRemoteSwiftPackageReference "PopupView" */; + productName = PopupView; + }; 89BCABE1276B3CB0009E9B10 /* NavigationStack */ = { isa = XCSwiftPackageProductDependency; package = 89BCABE0276B3CB0009E9B10 /* XCRemoteSwiftPackageReference "swiftui-navigation-stack" */; diff --git a/nirvana-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/nirvana-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9d5cafb..26076d0 100644 --- a/nirvana-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/nirvana-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -118,6 +118,15 @@ "version": "2.30908.0" } }, + { + "package": "PopupView", + "repositoryURL": "https://github.com/exyte/PopupView", + "state": { + "branch": null, + "revision": "4cf8c01473282b3711e6780bd78ef81add97f6e2", + "version": "1.0.3" + } + }, { "package": "Promises", "repositoryURL": "https://github.com/google/promises.git", diff --git a/nirvana-ios/Views/PhoneVerification/PhoneVerificationView.swift b/nirvana-ios/Views/PhoneVerification/PhoneVerificationView.swift index 2939c72..9be26dc 100644 --- a/nirvana-ios/Views/PhoneVerification/PhoneVerificationView.swift +++ b/nirvana-ios/Views/PhoneVerification/PhoneVerificationView.swift @@ -7,6 +7,9 @@ import SwiftUI import NavigationStack +import Combine +// TODO: maybe this is useless and just do my own toasts and alerts +import PopupView // user can type in a phone number and then receive a text struct PhoneVerificationView: View { @@ -14,6 +17,11 @@ struct PhoneVerificationView: View { @State var ccode = "+1" @EnvironmentObject private var navigationStack: NavigationStack + // Alert settings + @State var showToast = false + @State var toastText = "🇺🇸 Only U.S. supported, more countries coming soon!" + + // TODO: format the input so that it shows the parentheses and stuff (949)923-0445 var body: some View { ZStack(alignment: .topLeading) { Color.clear @@ -26,15 +34,27 @@ struct PhoneVerificationView: View { .background(.ultraThinMaterial) .clipShape(Circle()) .shadow(color: Color.black.opacity(0.3), radius: 20, x: 0, y: 20) + .font(.subheadline) + .onTapGesture { + // tell people that we only support the United States + self.showToast.toggle() + } - TextField("enter phone number", text: $phoneNumber) + TextField("(949) 292 - 2192", text: $phoneNumber) .padding() .background(.ultraThinMaterial) .clipShape(Capsule()) .keyboardType(.decimalPad) - .frame(maxWidth: .infinity) .shadow(color: Color.black.opacity(0.3), radius: 20, x: 0, y: 20) - .font(.caption) + .font(.subheadline) + .onReceive(Just(self.phoneNumber)) {newValue in + let filtered = newValue.filter { + "0123456789".contains($0) + } + if filtered != newValue { + self.phoneNumber = filtered + } + } Spacer() } @@ -72,6 +92,17 @@ struct PhoneVerificationView: View { .padding() } } + .popup(isPresented: self.$showToast, type: .toast, position: .bottom, autohideIn: 2) { + VStack { + Text(self.toastText) + .padding() + .background(.ultraThinMaterial) + .cornerRadius(30) + .font(.caption) + .foregroundColor(Color.red) + } + .padding() + } } } @@ -83,13 +114,71 @@ struct PhoneVerificationView_Previews: PreviewProvider { // another view for user to type in the sms code struct PhoneVerificationCodeView: View { + @EnvironmentObject private var navigationStack: NavigationStack + + @State var verificationCode = "" + var body: some View { - Text("Verification View") + ZStack(alignment: .topLeading) { + Color.clear + + OnboardingTemplateView(hdrText: "Let's get you verified", imgName: "undraw_my_password_d-6-kg", bottomActArea: AnyView( + VStack { + TextField("Code", text: self.$verificationCode) + .padding() + .background(.ultraThinMaterial) + .clipShape(Capsule()) + .keyboardType(.decimalPad) + .shadow(color: Color.black.opacity(0.3), radius: 20, x: 0, y: 20) + .font(.subheadline) + .multilineTextAlignment(.center) + .padding(.vertical) +// .onReceive(Just(self.$verificationCode)) {newValue in +// let filtered = newValue.filter { +// "0123456789".contains($0) +// } +// if filtered != newValue { +// self.$verificationCode = filtered +// } +// } + + Button { + print("Verify") + + // do auth stuff + // then async send to next page + self.navigationStack.push(PhoneVerificationCodeView()) // verify code page + + } label: { + Text("Send Verification") + .bold() + .foregroundColor(NirvanaColor.white) + .frame(maxWidth: .infinity) + .padding(.vertical, 20) + .background(NirvanaColor.teal) + .clipShape(Capsule()) + .shadow(radius:10) + } + } + )) + + //back button to home + Button { + print("going back to last page") + + self.navigationStack.pop() // goes back to welcome screen + } label: { + Label("Back", systemImage: "chevron.left") + .labelStyle(.iconOnly) + .foregroundColor(NirvanaColor.teal) + .padding() + } + } } } struct PhoneVerificationCodeView_Previews: PreviewProvider { static var previews: some View { - PhoneVerificationCodeView() + PhoneVerificationCodeView().environmentObject(AuthSessionStore()) } } diff --git a/nirvana-ios/Views/PhoneVerification/PhoneVerificationViewModel.swift b/nirvana-ios/Views/PhoneVerification/PhoneVerificationViewModel.swift new file mode 100644 index 0000000..bb93add --- /dev/null +++ b/nirvana-ios/Views/PhoneVerification/PhoneVerificationViewModel.swift @@ -0,0 +1,26 @@ +// +// PhoneVerificationViewModel.swift +// nirvana-ios +// +// Created by Arjun Patel on 12/17/21. +// + +import Foundation + +final class PhoneVerificationViewModel : ObservableObject { + +} + +extension String { + func applyPatternOnNumbers(pattern: String, replacementCharacter: Character) -> String { + var pureNumber = self.replacingOccurrences( of: "[^0-9]", with: "", options: .regularExpression) + for index in 0 ..< pattern.count { + guard index < pureNumber.count else { return pureNumber } + let stringIndex = String.Index(utf16Offset: index, in: pattern) + let patternCharacter = pattern[stringIndex] + guard patternCharacter != replacementCharacter else { continue } + pureNumber.insert(patternCharacter, at: stringIndex) + } + return pureNumber + } +}