diff --git a/Projects/Core/Sources/Coordinator/Setp/AppStep.swift b/Projects/Core/Sources/Coordinator/Setp/AppStep.swift index ee941b26..0ed46887 100644 --- a/Projects/Core/Sources/Coordinator/Setp/AppStep.swift +++ b/Projects/Core/Sources/Coordinator/Setp/AppStep.swift @@ -7,6 +7,7 @@ public enum MGStep: Step { case TabBarIsRequired // Auth + case authSplashIsRequired case authIntroIsRequired case authAgreeIsRequired case authNickNameIsRequired diff --git a/Projects/Core/Sources/Coordinator/Stepper/AuthStepper.swift b/Projects/Core/Sources/Coordinator/Stepper/AuthStepper.swift index abe8b8f8..a9606a32 100644 --- a/Projects/Core/Sources/Coordinator/Stepper/AuthStepper.swift +++ b/Projects/Core/Sources/Coordinator/Stepper/AuthStepper.swift @@ -9,7 +9,7 @@ public class AuthStepper: Stepper { public var steps = PublishRelay() public var initialStep: Step { - return MGStep.authIntroIsRequired + return MGStep.authSplashIsRequired } public init() { diff --git a/Projects/Data/Sources/Repository/AuthRepository.swift b/Projects/Data/Sources/Repository/AuthRepository.swift index f182daed..ae6e149f 100644 --- a/Projects/Data/Sources/Repository/AuthRepository.swift +++ b/Projects/Data/Sources/Repository/AuthRepository.swift @@ -25,7 +25,11 @@ public class AuthRepository: AuthRepositoryInterface { public func oauthRecovery(accessToken: String, oauth: OauthType) -> Single { return networkService.oauthRecovery(accessToken: accessToken, oauth: oauth) } - + + public func tokenReIssue(refreshToken: String) -> Single { + return networkService.tokenReIssue(refreshToken: refreshToken) + } + public func nicknameCheck(nickname: String) -> Single { return networkService.nicknameCheck(nickname: nickname) } diff --git a/Projects/Domain/Sources/RepositoryInterface/AuthRepositoryInterface.swift b/Projects/Domain/Sources/RepositoryInterface/AuthRepositoryInterface.swift index e096e0e8..7940ae00 100644 --- a/Projects/Domain/Sources/RepositoryInterface/AuthRepositoryInterface.swift +++ b/Projects/Domain/Sources/RepositoryInterface/AuthRepositoryInterface.swift @@ -18,6 +18,7 @@ public protocol AuthRepositoryInterface { func oauthSignup(nickname: String, accessToken: String, oauth: OauthType) -> Single func oauthLogin(accessToken: String, oauth: OauthType) -> Single func oauthRecovery(accessToken: String, oauth: OauthType) -> Single + func tokenReIssue(refreshToken: String) -> Single func nicknameCheck(nickname: String) -> Single func getIntroData() -> Single } diff --git a/Projects/Domain/Sources/UseCase/AuthUseCase.swift b/Projects/Domain/Sources/UseCase/AuthUseCase.swift index 620a8414..7ca7bf2a 100644 --- a/Projects/Domain/Sources/UseCase/AuthUseCase.swift +++ b/Projects/Domain/Sources/UseCase/AuthUseCase.swift @@ -16,6 +16,7 @@ public protocol AuthUseCase { func appleButtonTap() func nextButtonTap() -> Bool func getIntroData() + func tokenReIssue() var appleSignupResult: PublishSubject { get } var introData: PublishSubject { get } } @@ -86,6 +87,44 @@ extension DefaultAuthUseCase: AuthUseCase { }) .disposed(by: disposeBag) } + + public func tokenReIssue() { + let refreshToken = TokenManagerImpl().get(key: .refreshToken) + guard let refreshToken = refreshToken else { + AuthStepper.shared.steps.accept(MGStep.authIntroIsRequired) + return + } + authRepository.tokenReIssue(refreshToken: refreshToken) + .flatMap { response -> Single in + switch response.statusCode { + case 200: + return Single.just(response) + case 401: + return Single.error(AuthErrorType.error401) + case 500: + return Single.error(AuthErrorType.error500) + default: + return Single.just(response) + } + } + .subscribe(onSuccess: { element in + MGLogger.debug("token ReIssue ✅ \(String(describing: element.response))") + if let headers = element.response?.headers { + let accessToken = headers.value(for: "Authorization")?.replacingOccurrences(of: "Bearer ", with: "") + let refreshToken = headers["Set-Cookie"]?.components(separatedBy: ";").first(where: { $0.contains("RF-TOKEN") })?.replacingOccurrences(of: "RF-TOKEN=", with: "") + if let accessToken = accessToken { + TokenManagerImpl().save(token: accessToken, with: .accessToken) + } + if let refreshToken = refreshToken { + TokenManagerImpl().save(token: refreshToken, with: .refreshToken) + } + } + AuthStepper.shared.steps.accept(MGStep.initialization) + }, onFailure: { error in + MGLogger.debug("token ReIssue ❌ \(error)") + AuthStepper.shared.steps.accept(MGStep.authIntroIsRequired) + }).disposed(by: disposeBag) + } } extension DefaultAuthUseCase { diff --git a/Projects/Features/AuthFeature/Demo/Sources/Application/AppDelegate.swift b/Projects/Features/AuthFeature/Demo/Sources/Application/AppDelegate.swift index 8f0e5e76..3ee96d86 100644 --- a/Projects/Features/AuthFeature/Demo/Sources/Application/AppDelegate.swift +++ b/Projects/Features/AuthFeature/Demo/Sources/Application/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // } // return false // } -// + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { KakaoSDK.initSDK(appKey: "dcfcd3ab4a997c5a53e2ab26a8ec2a63") return true diff --git a/Projects/Features/AuthFeature/Demo/Sources/Application/SceneDelegate.swift b/Projects/Features/AuthFeature/Demo/Sources/Application/SceneDelegate.swift index 66ae48b1..b17f05d3 100644 --- a/Projects/Features/AuthFeature/Demo/Sources/Application/SceneDelegate.swift +++ b/Projects/Features/AuthFeature/Demo/Sources/Application/SceneDelegate.swift @@ -38,7 +38,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { mainFlow = AuthFlow() - coordinator.coordinate(flow: mainFlow, with: OneStepper(withSingleStep: MGStep.authIntroIsRequired)) + coordinator.coordinate(flow: mainFlow, with: OneStepper(withSingleStep: MGStep.authSplashIsRequired)) Flows.use(mainFlow, when: .created) { root in self.window?.rootViewController = root self.window?.makeKey() diff --git a/Projects/Features/AuthFeature/Sources/IntroScene/VC/SplashViewController.swift b/Projects/Features/AuthFeature/Sources/IntroScene/VC/SplashViewController.swift index a7b7c35c..dfdfdb55 100644 --- a/Projects/Features/AuthFeature/Sources/IntroScene/VC/SplashViewController.swift +++ b/Projects/Features/AuthFeature/Sources/IntroScene/VC/SplashViewController.swift @@ -15,10 +15,19 @@ import Core public class SplashViewController: BaseViewController, Stepper { private let iconImageView = UIImageView().then { - $0.image = DSKitAsset.Assets.bodySplitSqt.image + $0.image = DSKitAsset.Assets.splashLogo.image + } + +// public override func viewDidAppear(_ animated: Bool) { +// AuthStepper.shared.steps.accept(MGStep.authIntroIsRequired) +// } + + public override func attribute() { + super.attribute() } public override func layout() { + super.layout() view.addSubviews([iconImageView]) iconImageView.snp.makeConstraints { diff --git a/Projects/Features/AuthFeature/Sources/IntroScene/ViewModel/SplashViewModel.swift b/Projects/Features/AuthFeature/Sources/IntroScene/ViewModel/SplashViewModel.swift index 86ccbe8b..8b9b0b44 100644 --- a/Projects/Features/AuthFeature/Sources/IntroScene/ViewModel/SplashViewModel.swift +++ b/Projects/Features/AuthFeature/Sources/IntroScene/ViewModel/SplashViewModel.swift @@ -25,10 +25,11 @@ public class SplashViewModel: AuthViewModelType { public struct Output {} - public init(authUseCase: AuthUseCase) { self.useCase = authUseCase self.disposeBag = DisposeBag() + + useCase.tokenReIssue() } public func transform(_ input: Input, action: (Output) -> Void) -> Output { @@ -36,8 +37,6 @@ public class SplashViewModel: AuthViewModelType { let ouput = Output() action(ouput) -// useCase.appleSignupResult() - return Output() } } diff --git a/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/Contents.json b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/Contents.json new file mode 100644 index 00000000..13d95569 --- /dev/null +++ b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "splashLogo.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "splashLogo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "splashLogo@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo.png b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo.png new file mode 100644 index 00000000..a4b03e25 Binary files /dev/null and b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo.png differ diff --git a/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@2x.png b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@2x.png new file mode 100644 index 00000000..7b889fcc Binary files /dev/null and b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@2x.png differ diff --git a/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@3x.png b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@3x.png new file mode 100644 index 00000000..ee94f41b Binary files /dev/null and b/Projects/Modules/DSKit/Resources/Assets.xcassets/Logo/splashLogo.imageset/splashLogo@3x.png differ diff --git a/Projects/Modules/MGFlow/Sources/Flow/AuthFlow.swift b/Projects/Modules/MGFlow/Sources/Flow/AuthFlow.swift index 6db48add..4d91ae79 100644 --- a/Projects/Modules/MGFlow/Sources/Flow/AuthFlow.swift +++ b/Projects/Modules/MGFlow/Sources/Flow/AuthFlow.swift @@ -18,8 +18,8 @@ public class AuthFlow: Flow { var authService: DefaultAuthService! var authRepository: AuthRepository! var useCase: DefaultAuthUseCase! - var viewModel: IntroViewModel! - var viewController: IntroViewController! + var viewModel: SplashViewModel! + var viewController: SplashViewController! public var root: Presentable { return self.rootViewController @@ -33,8 +33,10 @@ public class AuthFlow: Flow { public func navigate(to step: Step) -> FlowContributors { guard let step = step as? MGStep else { return .none } switch step { - case .authIntroIsRequired: + case .authSplashIsRequired: return setupAuthMainScreen() + case .authIntroIsRequired: + return navigateToIntroViewScreen() case .authAgreeIsRequired: return navigateToAgreeViewScreen() case .authNickNameIsRequired: @@ -54,11 +56,11 @@ public class AuthFlow: Flow { authService = DefaultAuthService() authRepository = AuthRepository(networkService: authService) useCase = DefaultAuthUseCase(authRepository: authRepository) - viewModel = IntroViewModel(authUseCase: useCase) + viewModel = SplashViewModel(authUseCase: useCase) } private func setupViewController() { - viewController = IntroViewController(viewModel) + viewController = SplashViewController(viewModel) rootViewController = UINavigationController(rootViewController: viewController) } @@ -67,6 +69,13 @@ public class AuthFlow: Flow { rootViewController.setViewControllers([viewController], animated: false) return .one(flowContributor: .contribute(withNextPresentable: self.root, withNextStepper: AuthStepper.shared)) } + + private func navigateToIntroViewScreen() -> FlowContributors { + let vc = IntroViewController(IntroViewModel(authUseCase: self.useCase)) + rootViewController.pushViewController(vc, animated: false) + vc.navigationItem.hidesBackButton = true + return .none + } private func navigateToAgreeViewScreen() -> FlowContributors { let vc = AgreeViewController(AgreeViewModel(useCase: self.useCase)) diff --git a/Projects/Modules/MGNetworks/Sources/Service/AuthService.swift b/Projects/Modules/MGNetworks/Sources/Service/AuthService.swift index 83bbf70b..ea0a27a2 100644 --- a/Projects/Modules/MGNetworks/Sources/Service/AuthService.swift +++ b/Projects/Modules/MGNetworks/Sources/Service/AuthService.swift @@ -21,6 +21,7 @@ public protocol AuthService { func oauthLogin(accessToken: String, oauth: OauthType) -> Single func oauthSingup(nickname: String, accessToken: String, oauth: OauthType) -> Single func oauthRecovery(accessToken: String, oauth: OauthType) -> Single + func tokenReIssue(refreshToken: String) -> Single func kakaoButtonTap() -> Single func requestToken() -> Single func requestIntroData() -> Single @@ -75,6 +76,10 @@ extension DefaultAuthService: AuthService { } } + public func tokenReIssue(refreshToken: String) -> Single { + return authProvider.rx.request(.reissuanceToken(refreshToken: refreshToken)) + } + public func kakaoButtonTap() -> Single { return Single.create { single in if UserApi.isKakaoTalkLoginAvailable() {