Skip to content

Commit

Permalink
Merge pull request #208 from Nexters/release/1.0.3
Browse files Browse the repository at this point in the history
v1.0.3 Release -> Main
  • Loading branch information
leemhyungyu authored Aug 25, 2024
2 parents d321de7 + 77211d3 commit 9d9b5f8
Show file tree
Hide file tree
Showing 40 changed files with 1,021 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public extension ModulePath {
// MARK: - FeatureModule
public extension ModulePath {
enum Feature: String, CaseIterable {
case Guide
case TabBar
case Report
case BottleArrival
Expand Down
2 changes: 1 addition & 1 deletion Projects/App/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
Log.debug("fcm token: \(fcmToken ?? "NO TOKEN")")
if let fcmToken {
// TODO: user defaults 설정 방법 변경
UserDefaults.standard.set(fcmToken, forKey: "fcmToken")
store.send(.appDelegate(.didReceivedFcmToken(fcmToken: fcmToken)))
}
}

Expand Down
14 changes: 9 additions & 5 deletions Projects/Domain/Auth/Sources/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import Foundation

import DomainAuthInterface
import DomainUser

import CoreNetwork
import CoreLoggerInterface

Expand All @@ -19,12 +21,13 @@ extension AuthClient: DependencyKey {
private static func live() -> AuthClient {
@Dependency(\.network) var networkManager
@Dependency(\.loginManager) var loginManager

@Dependency(\.userClient) var userClient
return .init(
signInWithKakao: {
let signInResult = try await loginManager.signIn(loginType: .kakao)
let accessToken = signInResult.accessToken
guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken")
let fcmToken = userClient.fetchFcmToken()
guard let fcmToken = fcmToken
else {
Log.fault("no fcm token")
fatalError()
Expand All @@ -40,8 +43,8 @@ extension AuthClient: DependencyKey {
let signInResult = try await loginManager.signIn(loginType: .apple)
let accessToken = signInResult.accessToken
let userName = signInResult.userName

guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken")
let fcmToken = userClient.fetchFcmToken()
guard let fcmToken = fcmToken
else {
Log.fault("no fcm token")
fatalError()
Expand All @@ -62,7 +65,8 @@ extension AuthClient: DependencyKey {
try await networkManager.reqeust(api: .apiType(AuthAPI.withdraw))
},
logout: {
guard let fcmToken = UserDefaults.standard.string(forKey: "fcmToken")
let fcmToken = userClient.fetchFcmToken()
guard let fcmToken = fcmToken
else {
Log.fault("no fcm token")
return
Expand Down
16 changes: 15 additions & 1 deletion Projects/Domain/User/Interface/Sources/UserClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ import Foundation
public struct UserClient {
private let _isLoggedIn: () -> Bool
private let _isAppDeleted: () -> Bool
private let _fetchFcmToken: () -> String?
private let updateLoginState: (Bool) -> Void
private let updateDeleteState: (Bool) -> Void
private let updateFcmToken: (String) -> Void

public init(
isLoggedIn: @escaping () -> Bool,
isAppDeleted: @escaping () -> Bool,
fetchFcmToken: @escaping () -> String?,
updateLoginState: @escaping (Bool) -> Void,
updateDeleteState: @escaping (Bool) -> Void
updateDeleteState: @escaping (Bool) -> Void,
updateFcmToken: @escaping (String) -> Void
) {
self._isLoggedIn = isLoggedIn
self._isAppDeleted = isAppDeleted
self._fetchFcmToken = fetchFcmToken
self.updateLoginState = updateLoginState
self.updateDeleteState = updateDeleteState
self.updateFcmToken = updateFcmToken
}

public func isLoggedIn() -> Bool {
Expand All @@ -33,11 +39,19 @@ public struct UserClient {
_isAppDeleted()
}

public func fetchFcmToken() -> String? {
_fetchFcmToken()
}

public func updateLoginState(isLoggedIn: Bool) {
updateLoginState(isLoggedIn)
}

public func updateDeleteState(isDelete: Bool) {
updateDeleteState(isDelete)
}

public func updateFcmToken(fcmToken: String) {
updateFcmToken(fcmToken)
}
}
8 changes: 8 additions & 0 deletions Projects/Domain/User/Sources/UserClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,20 @@ extension UserClient: DependencyKey {
return !UserDefaults.standard.bool(forKey: "deleteState")
},

fetchFcmToken: {
return UserDefaults.standard.string(forKey: "fcmToken")
},

updateLoginState: { isLoggedIn in
UserDefaults.standard.set(isLoggedIn, forKey: "loginState")
},

updateDeleteState: { isDelete in
UserDefaults.standard.set(!isDelete, forKey: "deleteState")
},

updateFcmToken: { fcmToken in
UserDefaults.standard.set(fcmToken, forKey: "fcmToken")
}
)
}
Expand Down
6 changes: 0 additions & 6 deletions Projects/Feature/BottleStorage/Example/Sources/AppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ struct AppView: App {
initialState: BottleStorageFeature.State(),
reducer: { BottleStorageFeature() }
))
.onAppear {
AuthClient.liveValue.saveToken(token: .init(
accessToken: "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzIzMTE3ODk1LCJleHAiOjE3MjMxNTM4OTV9.HjjnS1onaAUA6nJGOV-f6FE55eAihUGTFNYGmmyETQc",
refershToken: "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzIzMTE3ODk1LCJleHAiOjE3Mzc2MzMwOTV9.Af-L2h_5pBQWrZCc1OQI3tm1DGwowqCAId-rK5vAPaQ"
))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ extension PingPongDetailFeature {
return fetchPingPong(state: &state)
case .popToRootDidRequired:
return .send(.delegate(.popToRootDidRequired))
case .refreshPingPong:
return fetchPingPong(state: &state)
}

case let .matching(.delegate(delegate)):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import ComposableArchitecture

public struct MatchingView: View {
@Perception.Bindable private var store: StoreOf<MatchingFeature>
@Environment(\.openURL) var openURL

public init(store: StoreOf<MatchingFeature>) {
self.store = store
Expand Down Expand Up @@ -175,7 +176,13 @@ private extension MatchingView {
case .waiting:
EmptyView()
case .success:
EmptyView()
SolidButton(
title: "카카오톡 바로가기",
sizeType: .large,
buttonType: .throttle,
action: { openKakaoTalk() }
)

case .failure:
SolidButton(
title: "다른 보틀 열어보기",
Expand Down Expand Up @@ -242,3 +249,12 @@ private extension MatchingView {
.padding(.bottom, 32.0)
}
}

private extension MatchingView {
// TODO: 추후 구조 변경 필요
func openKakaoTalk() {
let kakaoTalk = "kakaotalk://"
guard let kakaoTalkURL = NSURL(string: kakaoTalk) as? URL else { return }
openURL(kakaoTalkURL)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension QuestionAndAnswerFeature {
}
}

case .stopTalkButtonTapped:
case .stopTalkButtonDidTapped:
state.destination = .alert(.init(
title: { TextState("중단하기") },
actions: {
Expand All @@ -94,6 +94,9 @@ extension QuestionAndAnswerFeature {
message: { TextState("중단 시 모든 핑퐁 내용이 사라져요. 정말 중단하시겠어요?") }
))
return .none

case .refreshDidPulled:
return .send(.delegate(.refreshPingPong))

case let .destination(.presented(.alert(alert))):
switch alert {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ public struct QuestionAndAnswerFeature {
case finalSelectButtonDidTapped(willMatch: Bool)
case refreshPingPongDidRequired
case configureShowLoadingIndicatorRequired(isShow: Bool)
case stopTalkButtonTapped
case stopTalkButtonDidTapped
case refreshDidPulled

// ETC.
case binding(BindingAction<State>)
Expand All @@ -220,6 +221,7 @@ public struct QuestionAndAnswerFeature {
public enum Delegate {
case reloadPingPongRequired
case popToRootDidRequired
case refreshPingPong
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public struct QuestionAndAnswerView: View {
color: .enableSecondary
)
.asThrottleButton {
store.send(.stopTalkButtonTapped)
store.send(.stopTalkButtonDidTapped)
}
.padding(.top, 12.0)
.disabled(store.isStopped == true)
Expand All @@ -122,6 +122,10 @@ public struct QuestionAndAnswerView: View {
isTextFieldFocused = textFieldState == .active || textFieldState == .enabled ? false : true
}
}
.refreshable {
try? await Task.sleep(nanoseconds: 300_000_000)
await store.send(.refreshDidPulled).finish()
}
.scrollIndicators(.hidden)
.overlay {
if store.isShowLoadingIndicator {
Expand Down
35 changes: 35 additions & 0 deletions Projects/Feature/Guide/Example/Sources/AppView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SwiftUI

import FeatureGuideInterface

import ComposableArchitecture

@main
struct AppView: App {
let mainGuideStore = Store(
initialState: MainGuideFeature.State(),
reducer: { MainGuideFeature() })

let pingpongGuideStore = Store(
initialState: PingPongGuideFeature.State(),
reducer: { PingPongGuideFeature() })

let photoShareGuideStore = Store(
initialState: PhotoShareGuideFeature.State(),
reducer: { PhotoShareGuideFeature() })

let startGuideStore = Store(
initialState: StartGuideFeature.State(),
reducer: { StartGuideFeature() })

var body: some Scene {

WindowGroup {
// MainGuideView(store: mainGuideStore)
// PingPongGuideView(store: pingpongGuideStore)
// PhotoShareGuideView(store: photoShareGuideStore)
StartGuideView(store: startGuideStore)
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// MainGuideFeature.swift
// FeatureGuideInterface
//
// Created by 임현규 on 8/22/24.
//

import Foundation

import ComposableArchitecture

@Reducer
public struct MainGuideFeature {
private let reducer: Reduce<State, Action>

init(reducer: Reduce<State, Action>) {
self.reducer = reducer
}

public struct State: Equatable {
public init() {}
}

public enum Action {

// User Action
case nextButtonDidTapped
case backButtonDidTapped

// Delegate
case delegate(Delegate)

public enum Delegate {
case nextButtonDidTapped
}
}

public var body: some ReducerOf<Self> {
reducer
}
}

extension MainGuideFeature {
public init() {
@Dependency(\.dismiss) var dismiss
let reducer = Reduce<State, Action> { state, action in
switch action {
case .nextButtonDidTapped:
return .send(.delegate(.nextButtonDidTapped))

case .backButtonDidTapped:
return .run { send in
await dismiss()
}

default:
return .none
}
}

self.init(reducer: reducer)
}
}
Loading

0 comments on commit 9d9b5f8

Please sign in to comment.