Skip to content

Commit

Permalink
refac #114: SignupEmail Model 내 Stage 추가된 형태로 리펙토링
Browse files Browse the repository at this point in the history
  • Loading branch information
minsangKang committed Nov 5, 2023
1 parent 59b8064 commit 83b215c
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 96 deletions.
6 changes: 3 additions & 3 deletions Project_Timer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2188,7 +2188,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Project_Timer/Project_Timer.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = 2C96RNDN63;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
INFOPLIST_FILE = Project_Timer/Info.plist;
Expand Down Expand Up @@ -2427,7 +2427,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Project_Timer/Project_Timer.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = 2C96RNDN63;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
INFOPLIST_FILE = Project_Timer/Info.plist;
Expand All @@ -2454,7 +2454,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Project_Timer/Project_Timer.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
CURRENT_PROJECT_VERSION = 4;
DEVELOPMENT_TEAM = 2C96RNDN63;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
INFOPLIST_FILE = Project_Timer/Info.plist;
Expand Down
10 changes: 10 additions & 0 deletions Project_Timer/Global/Extension/SwiftUI/View+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,13 @@ extension View {
}
}
}

// MARK: Functions
extension View {
func scroll(_ scrollViewProxy: ScrollViewProxy, to: any Hashable) {
#if targetEnvironment(macCatalyst)
#else
scrollViewProxy.scrollTo(to, anchor: .bottom)
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import SwiftUI
struct SignupTextFieldView: View {
enum type: Equatable {
case email
case authCode
case verificationCode
case password
case password2
case nickname
Expand Down Expand Up @@ -50,7 +50,7 @@ struct SignupTextFieldView: View {
switch self.type {
case .email:
return "email".localized()
case .authCode:
case .verificationCode:
return "verification code".localized()
case .nickname:
return "nickname".localized()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,46 @@ typealias SignupSelectInfos = (type: SignupInfo.type, venderInfo: SignupVenderIn

// MARK: State
class SignupEmailModel: ObservableObject {
enum Stage {
case email
case verificationCode
}

let infos: SignupSelectInfos
@Published var contentWidth: CGFloat = .zero
@Published var focus: SignupTextFieldView.type?
@Published var authCode: String = ""
@Published var wrongEmail: Bool?
@Published var wrongAuthCode: Bool?
@Published var validEmail: Bool?
@Published var validVerificationCode: Bool?
@Published var getVerificationSuccess: Bool = false
@Published var stage: Stage = .email

@Published var email: String = ""
@Published var verificationCode: String = ""
private var verificationKey = ""

init(infos: SignupSelectInfos) {
self.infos = infos

// vender email 정보를 기본값으로 설정
if let email = infos.venderInfo?.email {
self.email = email
}
}

// emailTextField underline 컬러
var emailTintColor: Color {
if wrongEmail == true {
if validEmail == false {
return TiTiColor.wrongTextField.toColor
} else if focus == .email {
return Color.blue
} else {
return UIColor.placeholderText.toColor
return focus == .email ? Color.blue : UIColor.placeholderText.toColor
}
}

// authCodeTextField underline 컬러
// verificationCodeTextField underline 컬러
var authCodeTintColor: Color {
if wrongAuthCode == true {
if validVerificationCode == false && verificationCode.isEmpty {
return TiTiColor.wrongTextField.toColor
} else if focus == .authCode {
return Color.blue
} else {
return UIColor.placeholderText.toColor
return focus == .verificationCode ? Color.blue : UIColor.placeholderText.toColor
}
}

Expand All @@ -73,26 +75,50 @@ extension SignupEmailModel {
}
}

// focusState 값변화 수신
// @FocusState 값변화 -> stage 반영
func updateFocus(to focus: SignupTextFieldView.type?) {
self.focus = focus
switch focus {
case .email:
resetEmail()
case .verificationCode:
resetVerificationCode()
default:
return
}
}

// 이메일 done 액션
// email done 액션
func checkEmail() {
let emailValid = PredicateChecker.isValidEmail(email)
wrongEmail = !emailValid
validEmail = PredicateChecker.isValidEmail(email)
// stage 변화 -> @FocusState 반영
if validEmail == true {
resetVerificationCode()
} else {
resetEmail()
}
}

// 인증코드 done 액션
func checkAuthCode() {
let authCodeValid = authCode.count > 7
wrongAuthCode = !authCodeValid

if authCodeValid {
func checkVerificationCode() {
validVerificationCode = verificationCode.count > 7
// stage 변화 -> @StateFocus 반영
if validVerificationCode == true {
// verificationKey 수신 필요
verificationKey = "abcd1234"
getVerificationSuccess = true
} else {
resetVerificationCode()
}
}

private func resetEmail() {
validVerificationCode = nil
stage = .email
}

private func resetVerificationCode() {
verificationCode = ""
stage = .verificationCode
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct SignupEmailView: View {
.ignoresSafeArea()

ContentView(model: model)
.padding(.bottom, keyboard.keyboardHeight)
.padding(.bottom, keyboard.keyboardHeight+16)
}
.onChange(of: geometry.size, perform: { value in
model.updateContentWidth(size: value)
Expand All @@ -49,39 +49,49 @@ struct SignupEmailView: View {
ZStack {
ScrollViewReader { scrollViewProxy in
ScrollView {
VStack(alignment: .leading, spacing: 0) {
SignupTitleView(title: "Enter your email address", subTitle: "Please enter your email address for verification")

SignupTextFieldView(type: .email, keyboardType: .emailAddress, text: $model.email, focus: $focus) {
model.checkEmail()
checkFocusAfterEmail()
HStack {
Spacer()
VStack(alignment: .leading, spacing: 0) {
SignupTitleView(title: "Enter your email address", subTitle: "Please enter your email address for verification")

SignupTextFieldView(type: .email, keyboardType: .emailAddress, text: $model.email, focus: $focus) {
model.checkEmail()
}
.onChange(of: model.email) { newValue in
model.validEmail = nil
}
SignupTextFieldUnderlineView(color: model.emailTintColor)
SignupTextFieldWarning(warning: "The format is incorrect. Please enter in the correct format", visible: model.validEmail == false)
.id(SignupTextFieldView.type.email)

if model.stage == .verificationCode {
NextContentView(model: model, focus: $focus)
}
}
.onChange(of: model.email) { newValue in
model.wrongEmail = nil
.onAppear {
if model.stage == .email {
focus = .email
}
}
SignupTextFieldUnderlineView(color: model.emailTintColor)
.id(SignupTextFieldView.type.email)
SignupTextFieldWarning(warning: "The format is incorrect. Please enter in the correct format", visible: model.wrongEmail == true)

if model.wrongEmail == false {
NextContentView(model: model, focus: $focus, focusCheckAfterAuthCode: checkFocusAfterAuthCode)
.onChange(of: focus) { newValue in // @FocusState 변화 -> stage 반영
model.updateFocus(to: newValue)
scroll(scrollViewProxy, to: newValue)
}
}
.onAppear {
if model.wrongAuthCode == nil {
focus = .email
.onReceive(model.$stage, perform: { stage in // stage 변화 -> @FocusState 반영
switch stage {
case .email:
focus = .email
case .verificationCode:
focus = .verificationCode
}
scroll(scrollViewProxy, to: focus)
})
.onReceive(model.$getVerificationSuccess) { success in
guard success else { return }
environment.navigationPath.append(SignupEmailRoute.signupPassword)
}
}
.onChange(of: focus) { newValue in
model.updateFocus(to: focus)
#if targetEnvironment(macCatalyst)
#else
scrollViewProxy.scrollTo(newValue, anchor: .top)
#endif
}
.onReceive(model.$getVerificationSuccess) { success in
guard success else { return }
environment.navigationPath.append(SignupEmailRoute.signupPassword)
.frame(width: model.contentWidth)
Spacer()
}
}
.scrollIndicators(.hidden)
Expand All @@ -108,48 +118,29 @@ struct SignupEmailView: View {
Spacer()
.frame(height: 45)
}
.frame(width: model.contentWidth, alignment: .leading)
#endif
}
.frame(width: model.contentWidth, alignment: .leading)
}

func checkFocusAfterEmail() {
if model.wrongEmail == true {
focus = .email
}
}

func checkFocusAfterAuthCode() {
if model.wrongAuthCode == true {
focus = .authCode
}
}
}

struct NextContentView: View {
@ObservedObject var model: SignupEmailModel
@FocusState.Binding var focus: SignupTextFieldView.type?
var focusCheckAfterAuthCode: () -> Void

var body: some View {
VStack(spacing: 0) {
Spacer()
.frame(height: 35)

HStack(alignment: .center, spacing: 16) {
SignupTextFieldView(type: .authCode, keyboardType: .alphabet, text: $model.authCode, focus: $focus) {
model.checkAuthCode()
focusCheckAfterAuthCode()
}
.onChange(of: model.authCode) { newValue in
model.wrongAuthCode = nil
SignupTextFieldView(type: .verificationCode, keyboardType: .alphabet, text: $model.verificationCode, focus: $focus) {
model.checkVerificationCode()
}
.frame(maxWidth: .infinity)

// MARK: Timer 구현 필요
Text("4 : 59")
.font(TiTiFont.HGGGothicssiP40g(size: 18))

// MARK: 재전송 구현 필요
Button {
// MARK: ViewModel 내에서 네트워킹이 필요한 부분
Expand All @@ -159,15 +150,10 @@ struct SignupEmailView: View {
.font(TiTiFont.HGGGothicssiP40g(size: 18))
}
}
.onAppear {
if model.wrongAuthCode != false {
focus = .authCode
}
}

SignupTextFieldUnderlineView(color: model.authCodeTintColor)
.id(SignupTextFieldView.type.authCode)
SignupTextFieldWarning(warning: "The verification code is not valid. Please try again", visible: model.wrongAuthCode == true)
SignupTextFieldWarning(warning: "The verification code is not valid. Please try again", visible: model.validVerificationCode == false && model.verificationCode.isEmpty)
.id(SignupTextFieldView.type.verificationCode)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Combine

typealias SignupEmailInfos = (prevInfos: SignupSelectInfos, emailInfo: SignupEmailInfo)

// MARK: State
class SignupPasswordModel: ObservableObject {
enum Stage {
case password
Expand Down Expand Up @@ -81,6 +82,7 @@ extension SignupPasswordModel {
}
}

// password done 액션
func checkPassword() {
validPassword = PredicateChecker.isValidPassword(password)
// stage 변화 -> @StateFocus 반영
Expand All @@ -91,6 +93,7 @@ extension SignupPasswordModel {
}
}

// password2 done 액션
func checkPassword2() {
let passwordValid = PredicateChecker.isValidPassword(password2)
let samePassword = password == password2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct SignupPasswordView: View {
.id(SignupTextFieldView.type.password)

if model.stage == .password2 {
NextContentView(focus: $focus, model: model, scrollViewProxy: scrollViewProxy)
NextContentView(model: model, focus: $focus)
}
}
.onAppear {
Expand Down Expand Up @@ -94,19 +94,11 @@ struct SignupPasswordView: View {
}
}
}

func scroll(_ scrollViewProxy: ScrollViewProxy, to: any Hashable) {
#if targetEnvironment(macCatalyst)
#else
scrollViewProxy.scrollTo(to, anchor: .bottom)
#endif
}
}

struct NextContentView: View {
@FocusState.Binding var focus: SignupTextFieldView.type?
@ObservedObject var model: SignupPasswordModel
let scrollViewProxy: ScrollViewProxy
@FocusState.Binding var focus: SignupTextFieldView.type?

var body: some View {
VStack(alignment: .leading, spacing: 0) {
Expand Down

0 comments on commit 83b215c

Please sign in to comment.