Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat [#104] 코디네이터 구현 #110

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions HMH_Tuist_iOS/Projects/App/Sources/AppView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// AppView.swift
// HMH-iOS
//
// Created by 이지희 on 11/15/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

import KakaoSDKAuth

import DSKit
import Core

struct AppView: View {
@EnvironmentObject var appDIContainer: AppDIContainer
@StateObject var coordinator = AppCoordinator(navigationPath: .init())

var body: some View {
ZStack {
Color(DSKitAsset.blackground.swiftUIColor)
.ignoresSafeArea(.all)
coordinator.start()
}
.onOpenURL { url in
if AuthApi.isKakaoTalkLoginUrl(url) {
_ = AuthController.handleOpenUrl(url: url)
}
}
}
}
91 changes: 0 additions & 91 deletions HMH_Tuist_iOS/Projects/App/Sources/Common/Custom/ContentView.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import SwiftUI

import Lottie

import LoginFeature
import DSKit
import Core

import Lottie

struct SplashView: View {
@ObservedObject var viewModel: LoginViewModel
@ObservedObject var coordinator: AppCoordinator

var body: some View {
ZStack {
Expand All @@ -29,9 +29,9 @@ struct SplashView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(DSKitAsset.blackground.swiftUIColor, ignoresSafeAreaEdges: .all)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.5, execute: {
// viewModel.handleSplashScreen()
})
DispatchQueue.main.asyncAfter(deadline: .now() + 3.5) {
coordinator.appState = .login // Splash에서 홈뷰 통신하면서 상태 판단 필요
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// AppCoordinator.swift
// Coordinator
//
// Created by 이지희 on 11/7/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

import Core
import LoginFeature
import OnboardingFeature
import MyPageFeature


final class AppCoordinator: ObservableObject, CoordinatorType {
@Published var currentView: AnyView = AnyView(EmptyView())
@Published var appState: AppState = .login


var navigationPath: NavigationPath = NavigationPath()
private let diContainer: AppDIContainer

init(diContainer: AppDIContainer) {
self.diContainer = diContainer
}

func start() -> AnyView {
// 초기 상태에 따라 적절한 뷰를 설정합니다.
showSplashScreen()
return currentView
}

private func showSplashScreen() {
currentView = AnyView(SplashView(coordinator: self)) // 코디네이터 주입

/// 스플래쉬에서 토큰 검사 과정 (혹은 홈뷰 API 호출) 로 로그인 필요 여부 확인
}
Comment on lines +35 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분의 토큰 절차를 어디서 처리할지 애매하네요..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아니면 스플래시에서 별도의 체킹 없이
토큰 인터셉터에서 리프레쉬 만료 관련 에러가 뜨면 로그인으로 가게 하면 될까요.?


func transitionToNextView() {
switch UserManager.shared.appState {
case .onboarding:
currentView = AnyView(OnboardingContentView())
case .onboardingComplete:
currentView = AnyView(OnboardingCompleteView())
case .servicePrepare:
currentView = AnyView(ServicePrepareView())
case .home:
startTabBar()
case .login:
startLogin()
}
}

func startLogin() {
let authDIContainer = diContainer.injectAuthDIContainer()
let authCoordinator = AuthCoordinator(navigationPath: navigationPath, diContainer: authDIContainer)
currentView = authCoordinator.start()
}

func startTabBar() {
let tabBarCoordinator = TabBarCoordinator(parentCoordinator: self, navigationPath: self.navigationPath)
currentView = tabBarCoordinator.start()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// LoginCoordinator.swift
// Coordinator
//
// Created by 이지희 on 11/15/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

import LoginFeature

final class AuthCoordinator: ObservableObject, CoordinatorType {
var navigationPath: NavigationPath
private let diContainer: AuthDIContainer

init(
navigationPath: NavigationPath,
diContainer: AuthDIContainer
) {
self.navigationPath = navigationPath
self.diContainer = diContainer
}

func start() -> AnyView {
let viewModel = diContainer.injectLoginViewModel()
let view = LoginView(viewModel: viewModel)
return AnyView(view)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// BaseCoordinator.swift
// Coordinator
//
// Created by 이지희 on 11/7/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//
import SwiftUI
import Combine

import Core

// MARK: - BaseCoordinator

/// NavigationStack을 사용할 경우 이전에 대한 정보를 모두 갖고 있기 때문에 부모 - 자식 코디네이터 불필요
public protocol CoordinatorType: AnyObject {
associatedtype View: SwiftUI.View

var navigationPath: NavigationPath { get set }

func start() -> View

func push(to view: any Hashable)
func pop()
func popToRoot()
}

extension CoordinatorType {
func push(to view: any Hashable) {
navigationPath.append(view)
}

func pop() {
navigationPath.removeLast()
}

func popToRoot() {
navigationPath.removeLast(navigationPath.count)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// OnboardingCoordinator.swift
// Coordinator
//
// Created by 이지희 on 11/15/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

import OnboardingFeature

final class OnboardingCoordinator: ObservableObject, CoordinatorType {
var parentCoordinator: (any CoordinatorType)?

var navigationPath: NavigationPath

init(
parentCoordinator: (any CoordinatorType)? = nil,
navigationPath: NavigationPath
) {
self.parentCoordinator = parentCoordinator
self.navigationPath = navigationPath
}

func start() -> AnyView {
return AnyView(OnboardingContentView())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// TabBarCoordinator.swift
// Coordinator
//
// Created by 이지희 on 11/15/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

class TabBarCoordinator: ObservableObject, CoordinatorType {
var navigationPath: NavigationPath

var parentCoordinator: (any CoordinatorType)?

@Published var selectedTab: Tab = .home

init(
parentCoordinator: CoordinatorType,
navigationPath: NavigationPath
) {
self.parentCoordinator = parentCoordinator
self.navigationPath = navigationPath
}

func start() -> AnyView {
AnyView(TabBarView())
}

enum Tab {
case home
case challenge
case myPage
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// AppDIConatiner.swift
// HMH-iOS
//
// Created by 이지희 on 11/27/24.
// Copyright © 2024 HMH-iOS. All rights reserved.
//

import SwiftUI

import Networks
import Data
import Domain

final class AppDIContainer: ObservableObject {

// Auth DI
func injectAuthDIContainer() -> AuthDIContainer {
let service = injectAuthService()
let serviceFactory = injectOAuthFactory()
return AuthDIContainer(services: service, oAuthServiceFactory: serviceFactory)
}

private func injectAuthService() -> AuthService {
return AuthService()
}

private func injectOAuthFactory() -> OAuthServiceFactory {
return OAuthServiceFactory()
}
}
Loading