Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feat/#84-setting-api' into feature/
Browse files Browse the repository at this point in the history
#23-design-system
  • Loading branch information
ShapeKim98 committed Aug 10, 2024
2 parents 9beb262 + 60985a2 commit 8921a9e
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 28 deletions.
2 changes: 2 additions & 0 deletions Projects/App/Sources/MainTab/MainTabFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ public struct MainTabFeature {
public enum DelegateAction: Equatable {
case 링크추가하기
case 포킷추가하기
case 로그아웃
case 회원탈퇴
}
}
/// initiallizer
Expand Down
5 changes: 5 additions & 0 deletions Projects/App/Sources/MainTab/MainTabPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public extension MainTabFeature {
case .remind(.delegate(.링크목록_즐겨찾기)):
state.path.append(.링크목록(ContentListFeature.State(contentType: .favorite)))
return .none

case .path(.element(_, action: .설정(.delegate(.로그아웃)))):
return .send(.delegate(.로그아웃))
case .path(.element(_, action: .설정(.delegate(.회원탈퇴)))):
return .send(.delegate(.회원탈퇴))
default: return .none
}
}
Expand Down
10 changes: 10 additions & 0 deletions Projects/App/Sources/Root/RootFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ public struct RootFeature {
state.intro = nil
state.mainTab = MainTabFeature.State()
return .none

case .mainTab(.delegate(.로그아웃)):
state.intro = .login()
state.mainTab = nil
return .none
case .mainTab(.delegate(.회원탈퇴)):
state.intro = .login()
state.mainTab = nil
return .none

case .appDelegate, .intro, .mainTab:
return .none
}
Expand Down
9 changes: 7 additions & 2 deletions Projects/CoreKit/Sources/Data/DTO/Auth/WithdrawRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import Foundation
/// 회원탈퇴 API Request
/// 📌 회원탈퇴는 Response가 없음
public struct WithdrawRequest: Encodable {
let authorizationCode: String
let authPlatform: String
public let refreshToken: String
public let authPlatform: String

public init(refreshToken: String, authPlatform: String) {
self.refreshToken = refreshToken
self.authPlatform = authPlatform
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
import Foundation
/// 닉네임 수정 API Request
public struct NicknameEditRequest: Encodable {
let nickname: String
public let nickname: String

public init(nickname: String) {
self.nickname = nickname
}
}
6 changes: 3 additions & 3 deletions Projects/CoreKit/Sources/Data/Network/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension DependencyValues {
/// 유저정보에 관련한 API를 처리하는 Client
public struct AuthClient {
public var 로그인: @Sendable (SignInRequest) async throws -> TokenResponse
public var 회원탈퇴: @Sendable (WithdrawRequest) async throws -> EmptyResponse
public var 회원탈퇴: @Sendable (WithdrawRequest) async throws -> Void
public var 토큰재발급: @Sendable (ReissueRequest) async throws -> ReissueResponse
}

Expand All @@ -35,7 +35,7 @@ extension AuthClient: DependencyKey {
try await nonTokenProvider.request(.로그인(model))
},
회원탈퇴: { model in
try await provider.request(.회원탈퇴(model))
try await provider.requestNoBody(.회원탈퇴(model))
},
토큰재발급: { model in
try await nonTokenProvider.request(.토큰재발급(model))
Expand All @@ -46,7 +46,7 @@ extension AuthClient: DependencyKey {
public static let previewValue: Self = {
Self(
로그인: { _ in .mock },
회원탈퇴: { _ in .init() },
회원탈퇴: { _ in },
토큰재발급: { _ in .mock }
)
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,11 @@ private extension RegisterNicknameFeature {
return .run { send in
await send(.inner(.textChanged))
}
.throttle(id: CancelID.response, for: 3.0, scheduler: mainQueue, latest: true)
.debounce(
id: CancelID.response,
for: 3.0,
scheduler: mainQueue
)
case .binding:
return .none
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import Util
public struct NickNameSettingFeature {
/// - Dependency
@Dependency(\.dismiss) var dismiss
@Dependency(\.userClient) var userClient
@Dependency(\.mainQueue) var mainQueue
/// - State
@ObservableState
public struct State: Equatable {
Expand All @@ -22,6 +24,8 @@ public struct NickNameSettingFeature {
get { self.domain.nickname }
set { self.domain.nickname = newValue }
}

var textfieldState: PokitInputStyle.State = .default
var buttonState: PokitButtonStyle.State = .disable
var textInpuState: PokitInputStyle.State = .default

Expand All @@ -43,9 +47,14 @@ public struct NickNameSettingFeature {
case saveButtonTapped
}

public enum InnerAction: Equatable { case doNothing }
public enum InnerAction: Equatable {
case textChanged
case 닉네임_중복_체크_네트워크_결과(Bool)
}

public enum AsyncAction: Equatable { case doNothing }
public enum AsyncAction: Equatable {
case 닉네임_중복_체크_네트워크
}

public enum ScopeAction: Equatable { case doNothing }

Expand Down Expand Up @@ -79,7 +88,7 @@ public struct NickNameSettingFeature {
return handleDelegateAction(delegateAction, state: &state)
}
}

public enum CancelID { case response }
/// - Reducer body
public var body: some ReducerOf<Self> {
BindingReducer(action: \.view)
Expand All @@ -91,6 +100,15 @@ private extension NickNameSettingFeature {
/// - View Effect
func handleViewAction(_ action: Action.View, state: inout State) -> Effect<Action> {
switch action {
case .binding(\.text):
state.buttonState = .disable
return .run { send in
await send(.inner(.textChanged))
}
.debounce(
id: CancelID.response,
for: 3.0, scheduler: mainQueue
)
case .binding:
// - MARK: 목업 데이터 조회
state.domain.isDuplicate = NicknameCheckResponse.mock.toDomain()
Expand All @@ -100,18 +118,47 @@ private extension NickNameSettingFeature {
return .run { _ in await dismiss() }

case .saveButtonTapped:
return .none
return .run { [nickName = state.text] send in
let request = NicknameEditRequest(nickname: nickName)
let _ = try await userClient.닉네임_수정(request)
await dismiss()
}
}
}

/// - Inner Effect
func handleInnerAction(_ action: Action.InnerAction, state: inout State) -> Effect<Action> {
return .none
switch action {
case .textChanged:
if state.text.isEmpty || state.text.count > 10 {
state.buttonState = .disable
return .none
} else {
return .run { send in
await send(.async(.닉네임_중복_체크_네트워크))
}
}
case let .닉네임_중복_체크_네트워크_결과(isDuplicate):
if isDuplicate {
state.textfieldState = .error
state.buttonState = .disable
} else {
state.textfieldState = .active
state.buttonState = .filled(.primary)
}
return .none
}
}

/// - Async Effect
func handleAsyncAction(_ action: Action.AsyncAction, state: inout State) -> Effect<Action> {
return .none
switch action {
case .닉네임_중복_체크_네트워크:
return .run { [nickName = state.text] send in
let result = try await userClient.닉네임_중복_체크(nickName)
await send(.inner(.닉네임_중복_체크_네트워크_결과(result.isDuplicate)))
}
}
}

/// - Scope Effect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ public extension NickNameSettingView {
equals: true
)
Spacer()
}
.overlay(alignment: .bottom) {
PokitBottomButton(
"저장",
state: store.buttonState,
action: { send(.saveButtonTapped) }
)
.padding(.top, 16)
.setKeyboardHeight()
}
.padding(.top, 16)
.padding(.horizontal, 20)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ public struct PokitSettingFeature {
@Dependency(\.dismiss) var dismiss
@Dependency(\.openSettings) var openSetting
@Dependency(\.pasteboard) var pasteboard
@Dependency(\.keychain) var keychain
@Dependency(\.userDefaults) var userDefaults
@Dependency(\.authClient) var authClient
@Dependency(\.openURL) var openURL
/// - State
@ObservableState
public struct State: Equatable {
Expand Down Expand Up @@ -51,16 +55,24 @@ public struct PokitSettingFeature {
case onAppear
}

public enum InnerAction: Equatable { case doNothing }
public enum InnerAction: Equatable {
case 로그아웃_팝업(isPresented: Bool)
case 회원탈퇴_팝업(isPresented: Bool)
}

public enum AsyncAction: Equatable { case doNothing }
public enum AsyncAction: Equatable {
case 회원탈퇴_네트워크
case 키_제거
}

public enum ScopeAction: Equatable {
case doNothing
}

public enum DelegateAction: Equatable {
case linkCopyDetected(URL?)
case 로그아웃
case 회원탈퇴
}
}

Expand Down Expand Up @@ -120,30 +132,41 @@ private extension PokitSettingFeature {
return .run { _ in await openSetting() }

case .공지사항:
return .none
let url = Constants.공지사항_주소
return .run { _ in await openURL(url) }

case .서비스_이용약관:
return .none
let url = Constants.서비스_이용약관_주소
return .run { _ in await openURL(url) }

case .개인정보_처리방침:
return .none
let url = Constants.개인정보_처리방침_주소
return .run { _ in await openURL(url) }

case .고객문의:
return .none
let url = Constants.고객문의_주소
return .run { _ in await openURL(url) }

case .로그아웃:
state.isLogoutPresented.toggle()
return .none
return .send(.inner(.로그아웃_팝업(isPresented: true)))

case .로그아웃수행:
return .none
return .run { send in
await send(.async(.키_제거))
await send(.inner(.로그아웃_팝업(isPresented: false)))
await send(.delegate(.로그아웃))
}

case .회원탈퇴:
state.isWithdrawPresented.toggle()
return .none
return .send(.inner(.회원탈퇴_팝업(isPresented: true)))

case .회원탈퇴수행:
return .none
return .run { send in
await send(.async(.회원탈퇴_네트워크))
await send(.async(.키_제거))
await send(.inner(.회원탈퇴_팝업(isPresented: false)))
await send(.delegate(.회원탈퇴))
}

case .dismiss:
return .run { _ in await dismiss() }
Expand All @@ -160,12 +183,34 @@ private extension PokitSettingFeature {

/// - Inner Effect
func handleInnerAction(_ action: Action.InnerAction, state: inout State) -> Effect<Action> {
return .none
switch action {
case let .로그아웃_팝업(isPresented):
state.isLogoutPresented = isPresented
return .none

case let .회원탈퇴_팝업(isPresented):
state.isWithdrawPresented = isPresented
return .none
}
}

/// - Async Effect
func handleAsyncAction(_ action: Action.AsyncAction, state: inout State) -> Effect<Action> {
return .none
switch action {
case .회원탈퇴_네트워크:
return .run { _ in
guard let refreshToken = keychain.read(.refreshToken) else { return }
guard let platform = userDefaults.stringKey(.authPlatform) else { return }

let request = WithdrawRequest(refreshToken: refreshToken, authPlatform: platform)
try await authClient.회원탈퇴(request)
}

case .키_제거:
keychain.delete(.accessToken)
keychain.delete(.refreshToken)
return .run { _ in await userDefaults.removeString(.authPlatform) }
}
}

/// - Scope Effect
Expand Down
6 changes: 6 additions & 0 deletions Projects/Util/Sources/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@ public enum Constants {
public static let contentPath: String = "/api/v1/content"
public static let remindPath: String = "api/v1/remind"

public static let 공지사항_주소: URL = URL(string: "https://www.naver.com")!
public static let 서비스_이용약관_주소: URL = URL(string: "https://www.naver.com")!
public static let 개인정보_처리방침_주소: URL = URL(string: "https://www.naver.com")!
public static let 고객문의_주소: URL = URL(string: "https://www.naver.com")!


public static var mockImageUrl: String { "https://picsum.photos/\(Int.random(in: 150...250))" }
}

0 comments on commit 8921a9e

Please sign in to comment.