-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
개인정보 등록 뷰
- Loading branch information
Showing
11 changed files
with
644 additions
and
75 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
Projects/Core/Sources/Utility/UI/Keyboard/DismissKeyboardOnTap.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// | ||
// DismissKeyboardOnTap.swift | ||
// Core | ||
// | ||
// Created by Young Bin on 2023/08/24. | ||
// Copyright © 2023 team.humanwave. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
|
||
public struct DismissKeyboardOnTap: ViewModifier { | ||
public init() {} | ||
|
||
public func body(content: Content) -> some View { | ||
content | ||
.gesture( | ||
TapGesture().onEnded { | ||
UIApplication.shared.sendAction( | ||
#selector(UIResponder.resignFirstResponder), | ||
to: nil, | ||
from: nil, | ||
for: nil | ||
) | ||
} | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// Modifiers.swift | ||
// Features | ||
// | ||
// Created by 고도현 on 2023/08/12. | ||
// Copyright © 2023 team.humanwave. All rights reserved. | ||
// | ||
|
||
import SwiftUI | ||
|
||
// 최대 글자 수를 넘기면 좌, 우로 떨리는 애니메이션 | ||
struct Shake: ViewModifier { | ||
@Binding var isShake: Bool | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.offset(x: isShake ? -10 : 0) // 좌측으로 이동 | ||
.animation( | ||
Animation | ||
.easeInOut(duration: 0.1) | ||
.repeatCount(3, autoreverses: true), | ||
value: isShake) | ||
.onChange(of: isShake) { newValue in | ||
if !newValue { | ||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { | ||
withAnimation { | ||
self.isShake = false | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
Projects/Features/Sources/Registration/RegisterFeature.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// | ||
// RegisterFeature.swift | ||
// Features | ||
// | ||
// Created by 이영빈 on 2023/08/23. | ||
// Copyright © 2023 team.humanwave. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import ComposableArchitecture | ||
import Network | ||
|
||
public struct RegistrationFeature: Reducer { | ||
@Dependency(\.keymeAPIManager) var network | ||
@Dependency(\.continuousClock) var clock | ||
|
||
enum CancelID { case debouncedNicknameUpdate } | ||
|
||
public init() {} | ||
|
||
public struct State: Equatable { | ||
var status: Status = .notDetermined | ||
var isNicknameAvailable: Bool? | ||
var canRegister: Bool { | ||
return isNicknameAvailable == true | ||
} | ||
|
||
var thumbnailURL: URL? | ||
var originalImageURL: URL? | ||
|
||
var nicknameTextFieldString: String = "" | ||
|
||
enum Status: Equatable { | ||
case notDetermined | ||
case needsRegister | ||
case complete | ||
} | ||
} | ||
|
||
public enum Action: Equatable { | ||
case debouncedNicknameUpdate(text: String) | ||
|
||
case checkDuplicatedNickname(String) | ||
case checkDuplicatedNicknameResponse(Bool) | ||
|
||
case registerProfileImage(Data) | ||
case registerProfileImageResponse(thumbnailURL: URL, originalImageURL: URL) | ||
|
||
case finishRegister(nickname: String, thumbnailURL: URL?, originalImageURL: URL?) | ||
case finishRegisterResponse(id: Int, friendCode: String) | ||
} | ||
|
||
public var body: some Reducer<State, Action> { | ||
Reduce { state, action in | ||
switch action { | ||
case .debouncedNicknameUpdate(let nicknameString): | ||
state.nicknameTextFieldString = nicknameString | ||
return .run { send in | ||
try await withTaskCancellation( | ||
id: CancelID.debouncedNicknameUpdate, | ||
cancelInFlight: true | ||
) { | ||
try await self.clock.sleep(for: .seconds(0.7)) | ||
|
||
await send(.checkDuplicatedNickname(nicknameString)) | ||
} | ||
} | ||
|
||
// MARK: checkDuplicatedNickname | ||
case .checkDuplicatedNickname(let nickname): | ||
return .run(priority: .userInitiated) { send in | ||
let result = try await network.request( | ||
.registration(.checkDuplicatedNickname(nickname)), | ||
object: VerifyNicknameDTO.self | ||
) | ||
|
||
await send(.checkDuplicatedNicknameResponse(result.data.valid)) | ||
} | ||
|
||
case .checkDuplicatedNicknameResponse(let isNicknameDuplicated): | ||
state.isNicknameAvailable = isNicknameDuplicated | ||
|
||
// MARK: registerProfileImage | ||
case .registerProfileImage(let imageData): | ||
return .run { send in | ||
let result = try await network.request( | ||
.registration(.uploadImage(imageData)), | ||
object: ImageUploadDTO.self) | ||
|
||
if | ||
let thumbnailURL = URL(string: result.data.thumbnailUrl), | ||
let originalImageURL = URL(string: result.data.originalUrl) | ||
{ | ||
await send( | ||
.registerProfileImageResponse( | ||
thumbnailURL: thumbnailURL, | ||
originalImageURL: originalImageURL)) | ||
} | ||
} | ||
|
||
case .registerProfileImageResponse(let thumnailURL, let originalImageURL): | ||
state.thumbnailURL = thumnailURL | ||
state.originalImageURL = originalImageURL | ||
|
||
// MARK: finishRegister | ||
case .finishRegister(let nickname, let thumbnailURL, let originalImageURL): | ||
return .run { send in | ||
let result = try await network.request( | ||
.registration(.updateMemberDetails( | ||
nickname: nickname, | ||
profileImage: thumbnailURL?.absoluteString, | ||
profileThumbnail: originalImageURL?.absoluteString)), | ||
object: MemberUpdateDTO.self) | ||
|
||
await send( | ||
.finishRegisterResponse( | ||
id: result.data.id, | ||
friendCode: result.data.friendCode ?? "")) // TODO: 나중에 non-null 값 필요 | ||
} | ||
|
||
case .finishRegisterResponse: | ||
state.status = .complete | ||
} | ||
|
||
return .none | ||
} | ||
} | ||
} |
Oops, something went wrong.