diff --git a/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureImplement.swift b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureImplement.swift new file mode 100644 index 00000000..e6bb104b --- /dev/null +++ b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureImplement.swift @@ -0,0 +1,36 @@ +// +// FeatureImplement.swift +// EnvironmentPlugin +// +// Created by gnksbm on 7/12/25. +// + +// TODO: Featuer 객체가 필요하지 않을 때 Feature로 네이밍 변경될 예정 +public struct FeatureImplement: ImplementTarget { + public let name: String + public let hasResource: Bool + public let dependencies: [TargetDependency] + + public let product: Product = .staticFramework + public let infoPlist: InfoPlist? + public let settings: Settings = .frameworkDebug + public let scripts: [TargetScript] + public var sources: SourceFilesList? { ["Implement/Sources/**"] } + public var resources: ResourceFileElements? { hasResource ? ["Implement/Resources/**"] : nil } + public var targetDependencyPath: Path { + .relativeToRoot("Projects/Feature/\(name)") + } + + public init( + name: String, + hasResource: Bool = false, + @TargetComponentBuilder dependencies builder: () -> TargetComponentBuilder = { .init() } + ) { + let builder = builder() + self.name = name + self.hasResource = hasResource + self.dependencies = builder.buildTargetDependency() + self.scripts = builder.buildTargetScript() + self.infoPlist = builder.buildInfoPlist() + } +} diff --git a/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureInterface.swift b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureInterface.swift new file mode 100644 index 00000000..c70de0e5 --- /dev/null +++ b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureInterface.swift @@ -0,0 +1,31 @@ +// +// FeatureInterface.swift +// EnvironmentPlugin +// +// Created by gnksbm on 7/12/25. +// + +public struct FeatureInterface: BundleIDSuffixTarget, LocalDependency { + public var projectName: String + public let dependencies: [TargetDependency] + public let infoPlist: InfoPlist? + public let scripts: [TargetScript] + + public var name: String { projectName + "Interface" } + public var product: Product { .framework } + public var sources: SourceFilesList? { ["Interface/Sources/**"] } + public var targetDependencyPath: Path { + .relativeToRoot("Projects/Feature/\(projectName)") + } + + public init( + name: String, + @TargetComponentBuilder dependencies builder: () -> TargetComponentBuilder = { .init() } + ) { + let builder = builder() + self.projectName = name + self.dependencies = builder.buildTargetDependency() + self.scripts = builder.buildTargetScript() + self.infoPlist = builder.buildInfoPlist() + } +} diff --git a/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureTesting.swift b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureTesting.swift new file mode 100644 index 00000000..cf3730ed --- /dev/null +++ b/Plugins/EnvironmentPlugin/ProjectDescriptionHelpers/Buildable/TargetBuildable/Target/Feature/FeatureTesting.swift @@ -0,0 +1,33 @@ +// +// FeatureTesting.swift +// EnvironmentPlugin +// +// Created by gnksbm on 7/19/25. +// + +import Foundation + +public struct FeatureTesting: BundleIDSuffixTarget, LocalDependency { + public var projectName: String + public let dependencies: [TargetDependency] + public let infoPlist: InfoPlist? + public let scripts: [TargetScript] + + public var name: String { projectName + "Testing" } + public var product: Product { .framework } + public var sources: SourceFilesList? { ["Testing/Sources/**"] } + public var targetDependencyPath: Path { + .relativeToRoot("Projects/Feature/\(projectName)") + } + + public init( + name: String, + @TargetComponentBuilder dependencies builder: () -> TargetComponentBuilder = { .init() } + ) { + let builder = builder() + self.projectName = name + self.dependencies = builder.buildTargetDependency() + self.scripts = builder.buildTargetScript() + self.infoPlist = builder.buildInfoPlist() + } +} diff --git a/Projects/App/Sources/Coordinator/AppCoordinator.swift b/Projects/App/Sources/Coordinator/AppCoordinator.swift index fb2496bd..d39776fa 100644 --- a/Projects/App/Sources/Coordinator/AppCoordinator.swift +++ b/Projects/App/Sources/Coordinator/AppCoordinator.swift @@ -23,7 +23,7 @@ final class AppCoordinator: Coordinator { var parent: Coordinator? var childs: [Coordinator] = [] var navigationController: UINavigationController - public var coordinatorType: CoordinatorType = .app + private let coordinatorProvider = DefaultCoordinatorProvider() private let dependency: AppCoordinatorDependency @@ -40,6 +40,7 @@ final class AppCoordinator: Coordinator { parent: self, navigationController: navigationController, coordinatorProvider: coordinatorProvider, + homeCoordinatorBuilder: coordinatorProvider, viewModelDependency: dependency ) childs.append(splashCoordinator) @@ -52,7 +53,10 @@ final class AppCoordinator: Coordinator { navigationController: navigationController, busStopId: busStopId, coordinatorProvider: coordinatorProvider, - flow: .fromHome + flow: .fromHome, + nearMapCoordinatorBuilder: coordinatorProvider, + addRegularAlarmCoordinatorBuilder: coordinatorProvider, + delegate: nil ) childs.append(busStopCoordinator) busStopCoordinator.start() diff --git a/Projects/App/Sources/Coordinator/Splash/SplashCoordinator.swift b/Projects/App/Sources/Coordinator/Splash/SplashCoordinator.swift index a24517f6..750f0880 100644 --- a/Projects/App/Sources/Coordinator/Splash/SplashCoordinator.swift +++ b/Projects/App/Sources/Coordinator/Splash/SplashCoordinator.swift @@ -10,29 +10,32 @@ import UIKit import MainFeature import FeatureDependency +import HomeFeatureInterface protocol SplashCoordinator: Coordinator { func startTabFlow() - func openURL(_ url: URL) } final class SplashCoordinatorImpl: SplashCoordinator { var parent: Coordinator? var childs: [Coordinator] = [] var navigationController: UINavigationController - public var coordinatorType: CoordinatorType = .splash + private let coordinatorProvider: CoordinatorProvider + private let homeCoordinatorBuilder: HomeCoordinatorBuilder private let viewModelDependency: SplashViewModelDependency init( parent: Coordinator, navigationController: UINavigationController, coordinatorProvider: CoordinatorProvider, + homeCoordinatorBuilder: HomeCoordinatorBuilder, viewModelDependency: SplashViewModelDependency ) { self.parent = parent self.navigationController = navigationController self.coordinatorProvider = coordinatorProvider + self.homeCoordinatorBuilder = homeCoordinatorBuilder self.viewModelDependency = viewModelDependency } @@ -46,7 +49,8 @@ final class SplashCoordinatorImpl: SplashCoordinator { func startTabFlow() { let tabBarCoordinator = TabBarCoordinator( navigationController: navigationController, - coordinatorProvider: coordinatorProvider + coordinatorProvider: coordinatorProvider, + homeCoordinatorBuilder: homeCoordinatorBuilder ) childs.append(tabBarCoordinator) tabBarCoordinator.start() diff --git a/Projects/App/Sources/Coordinator/Splash/SplashViewController.swift b/Projects/App/Sources/Coordinator/Splash/SplashViewController.swift index 82b9ddfb..4e97e456 100644 --- a/Projects/App/Sources/Coordinator/Splash/SplashViewController.swift +++ b/Projects/App/Sources/Coordinator/Splash/SplashViewController.swift @@ -40,6 +40,7 @@ final class SplashViewController: UIViewController { output.alert .observe(on: MainScheduler.instance) .bind(with: self) { owner, alert in + guard !alert.actions.isEmpty else { return } let alertController = UIAlertController( title: alert.title, message: alert.message, diff --git a/Projects/App/Sources/DefaultCoordinatorProvider.swift b/Projects/App/Sources/DefaultCoordinatorProvider.swift index 95ebe22e..153e630a 100644 --- a/Projects/App/Sources/DefaultCoordinatorProvider.swift +++ b/Projects/App/Sources/DefaultCoordinatorProvider.swift @@ -14,44 +14,43 @@ import SearchFeature import AlarmFeature import BusStopFeature import NearMapFeature +import NearMapFeatureInterface +import HomeFeatureInterface +import AlarmFeatureInterface import Domain final class DefaultCoordinatorProvider: CoordinatorProvider { - func makeHomeCoordinator( - parent: Coordinator, - navigationController: UINavigationController - ) -> HomeCoordinator { - DefaultHomeCoordinator( - parent: parent, - navigationController: navigationController, - coordinatorProvider: self - ) - } - func makeBusStopCoordinator( parent: Coordinator, navigationController: UINavigationController, busStopId: String, - flow: FlowState + flow: FlowState, + delegate: BusStopCoordinatorDelegate? ) -> BusStopCoordinator { DefaultBusStopCoordinator( parent: parent, navigationController: navigationController, busStopId: busStopId, coordinatorProvider: self, - flow: flow + flow: flow, + nearMapCoordinatorBuilder: self, + addRegularAlarmCoordinatorBuilder: self, + delegate: delegate ) } func makeSearchCoordinator( parent: Coordinator, navigationController: UINavigationController, - flow: FlowState + flow: FlowState, + busStopCoordinatorDelegate: BusStopCoordinatorDelegate? ) -> SearchCoordinator { DefaultSearchCoordinator( parent: parent, navigationController: navigationController, coordinatorProvider: self, + nearMapCoordinatorBuilder: self, + busStopCoordinatorDelegate: busStopCoordinatorDelegate, flow: flow ) } @@ -68,18 +67,41 @@ final class DefaultCoordinatorProvider: CoordinatorProvider { flow: .fromAlarm ) } - - func makeNearMapCoordinator( - parent: Coordinator, +} + +extension DefaultCoordinatorProvider: AddRegularAlarmCoordinatorBuilder { + func build(parent: any Coordinator, navigationController: UINavigationController, flow: FlowState) -> any AddRegularAlarmCoordinator { + DefaultAddRegularAlarmCoordinator( + parent: parent, + navigationController: navigationController, + coordinatorProvider: self, + flow: flow + ) + } +} + +extension DefaultCoordinatorProvider: HomeCoordinatorBuilder { + func build(parent: any Coordinator, navigationController: UINavigationController) -> HomeCoordinator { + DefaultHomeCoordinator( + parent: parent, + navigationController: navigationController, + coordinatorProvider: self + ) + } +} + +extension DefaultCoordinatorProvider: NearMapCoordinatorBuilder { + func build( + parent: any Coordinator, navigationController: UINavigationController, flow: FlowState, busStopId: String? ) -> NearMapCoordinator { DefaultNearMapCoordinator( parent: parent, - navigationController: navigationController, + navigationController: navigationController, coordinatorProvider: self, - flow: flow, + flow: flow, busStopId: busStopId ) } diff --git a/Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift b/Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift similarity index 86% rename from Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift index 59de2018..7ea485c2 100644 --- a/Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift +++ b/Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultAddRegularAlarmCoordinator.swift @@ -17,9 +17,9 @@ public final class DefaultAddRegularAlarmCoordinator { public var navigationController: UINavigationController public let coordinatorProvider: CoordinatorProvider private let flow: FlowState - public var coordinatorType: CoordinatorType = .addAlarm private var vcForFinishFlow: UIViewController? + private weak var viewModel: AddRegularAlarmViewModel? public init( parent: Coordinator, @@ -34,11 +34,7 @@ public final class DefaultAddRegularAlarmCoordinator { } public func start() { - let addRegularAlarmViewController = AddRegularAlarmViewController( - viewModel: .init( - coordinator: self - ) - ) + let addRegularAlarmViewController = AddRegularAlarmViewController(viewModel: .init(coordinator: self)) vcForFinishFlow = addRegularAlarmViewController navigationController.pushViewController( addRegularAlarmViewController, @@ -49,12 +45,9 @@ public final class DefaultAddRegularAlarmCoordinator { extension DefaultAddRegularAlarmCoordinator: AddRegularAlarmCoordinator { public func start(with: RegularAlarmResponse) { - let addRegularAlarmViewController = AddRegularAlarmViewController( - viewModel: .init( - alarmToEdit: with, - coordinator: self - ) - ) + let viewModel = AddRegularAlarmViewModel(alarmToEdit: with, coordinator: self) + let addRegularAlarmViewController = AddRegularAlarmViewController(viewModel: viewModel) + self.viewModel = viewModel vcForFinishFlow = addRegularAlarmViewController navigationController.pushViewController( addRegularAlarmViewController, @@ -66,7 +59,8 @@ extension DefaultAddRegularAlarmCoordinator: AddRegularAlarmCoordinator { let searchCoordinator = coordinatorProvider.makeSearchCoordinator( parent: self, navigationController: navigationController, - flow: .fromAlarm + flow: .fromAlarm, + busStopCoordinatorDelegate: viewModel ) childs.append(searchCoordinator) searchCoordinator.start() diff --git a/Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift b/Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift similarity index 96% rename from Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift index f8676fd8..8f82e05d 100644 --- a/Projects/Feature/AlarmFeature/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift +++ b/Projects/Feature/AlarmFeature/Implement/Sources/Coordinator/DefaultRegularAlarmCoordinator.swift @@ -8,7 +8,6 @@ public final class DefaultRegularAlarmCoordinator: RegularAlarmCoordinator { public var childs: [Coordinator] = [] public var navigationController: UINavigationController public var coordinatorProvider: CoordinatorProvider - public var coordinatorType: CoordinatorType = .regularAlarm public init( navigationController: UINavigationController, diff --git a/Projects/Feature/AlarmFeature/Implement/Sources/Dependencies.swift b/Projects/Feature/AlarmFeature/Implement/Sources/Dependencies.swift new file mode 100644 index 00000000..18a6c225 --- /dev/null +++ b/Projects/Feature/AlarmFeature/Implement/Sources/Dependencies.swift @@ -0,0 +1,9 @@ +// +// Dependencies.swift +// AlarmFeatureInterface +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +@_exported import AlarmFeatureInterface diff --git a/Projects/Feature/AlarmFeature/Sources/View/EmptyRegularAlarmView.swift b/Projects/Feature/AlarmFeature/Implement/Sources/View/EmptyRegularAlarmView.swift similarity index 100% rename from Projects/Feature/AlarmFeature/Sources/View/EmptyRegularAlarmView.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/View/EmptyRegularAlarmView.swift diff --git a/Projects/Feature/AlarmFeature/Sources/View/RegularAlarmTVCell.swift b/Projects/Feature/AlarmFeature/Implement/Sources/View/RegularAlarmTVCell.swift similarity index 100% rename from Projects/Feature/AlarmFeature/Sources/View/RegularAlarmTVCell.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/View/RegularAlarmTVCell.swift diff --git a/Projects/Feature/AlarmFeature/Sources/ViewController/AddRegularAlarmViewController.swift b/Projects/Feature/AlarmFeature/Implement/Sources/ViewController/AddRegularAlarmViewController.swift similarity index 100% rename from Projects/Feature/AlarmFeature/Sources/ViewController/AddRegularAlarmViewController.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/ViewController/AddRegularAlarmViewController.swift diff --git a/Projects/Feature/AlarmFeature/Sources/ViewController/RegularAlarmViewController.swift b/Projects/Feature/AlarmFeature/Implement/Sources/ViewController/RegularAlarmViewController.swift similarity index 100% rename from Projects/Feature/AlarmFeature/Sources/ViewController/RegularAlarmViewController.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/ViewController/RegularAlarmViewController.swift diff --git a/Projects/Feature/AlarmFeature/Sources/ViewModel/AddRegularAlarmViewModel.swift b/Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/AddRegularAlarmViewModel.swift similarity index 90% rename from Projects/Feature/AlarmFeature/Sources/ViewModel/AddRegularAlarmViewModel.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/AddRegularAlarmViewModel.swift index ad75e1d8..37ac4cde 100644 --- a/Projects/Feature/AlarmFeature/Sources/ViewModel/AddRegularAlarmViewModel.swift +++ b/Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/AddRegularAlarmViewModel.swift @@ -139,3 +139,16 @@ extension AddRegularAlarmViewModel { let regularAlarm: BehaviorRelay } } + +extension AddRegularAlarmViewModel: BusStopCoordinatorDelegate { + func didSelect(busStopInfo: BusStopArrivalInfoResponse, busInfo: BusArrivalInfoResponse) { + regularAlarmEditingService.update( + busStopId: busStopInfo.busStopId, + busStopName: busStopInfo.busStopName, + busId: busInfo.busId, + busName: busInfo.busName, + adirection: busInfo.adirection + ) + coordinator.removeChildViewController() + } +} diff --git a/Projects/Feature/AlarmFeature/Sources/ViewModel/RegularAlarmViewModel.swift b/Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/RegularAlarmViewModel.swift similarity index 98% rename from Projects/Feature/AlarmFeature/Sources/ViewModel/RegularAlarmViewModel.swift rename to Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/RegularAlarmViewModel.swift index 1241ad3e..9019d9ad 100644 --- a/Projects/Feature/AlarmFeature/Sources/ViewModel/RegularAlarmViewModel.swift +++ b/Projects/Feature/AlarmFeature/Implement/Sources/ViewModel/RegularAlarmViewModel.swift @@ -3,6 +3,7 @@ import Foundation import Core import Domain import FeatureDependency +import AlarmFeatureInterface import RxSwift diff --git a/Projects/Feature/AlarmFeature/Interface/Sources/AddRegularAlarmCoordinator.swift b/Projects/Feature/AlarmFeature/Interface/Sources/AddRegularAlarmCoordinator.swift new file mode 100644 index 00000000..9274df26 --- /dev/null +++ b/Projects/Feature/AlarmFeature/Interface/Sources/AddRegularAlarmCoordinator.swift @@ -0,0 +1,23 @@ +// +// AddRegularAlarmCoordinator.swift +// AlarmFeatureInterface +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +import UIKit + +public protocol AddRegularAlarmCoordinator: Coordinator { + func start(with: RegularAlarmResponse) + func startSearchFlow() + func removeChildViewController() +} + +public protocol AddRegularAlarmCoordinatorBuilder { + func build( + parent: Coordinator, + navigationController: UINavigationController, + flow: FlowState + ) -> AddRegularAlarmCoordinator +} diff --git a/Projects/Feature/AlarmFeature/Interface/Sources/Dependencies.swift b/Projects/Feature/AlarmFeature/Interface/Sources/Dependencies.swift new file mode 100644 index 00000000..fe416f61 --- /dev/null +++ b/Projects/Feature/AlarmFeature/Interface/Sources/Dependencies.swift @@ -0,0 +1,10 @@ +// +// Dependencies.swift +// AlarmFeatureInterface +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +@_exported import FeatureDependency +@_exported import Domain diff --git a/Projects/FeatureDependency/Sources/Coordinator/RegularAlarmCoordinator.swift b/Projects/Feature/AlarmFeature/Interface/Sources/RegularAlarmCoordinator.swift similarity index 54% rename from Projects/FeatureDependency/Sources/Coordinator/RegularAlarmCoordinator.swift rename to Projects/Feature/AlarmFeature/Interface/Sources/RegularAlarmCoordinator.swift index a56e2aea..fed39e8f 100644 --- a/Projects/FeatureDependency/Sources/Coordinator/RegularAlarmCoordinator.swift +++ b/Projects/Feature/AlarmFeature/Interface/Sources/RegularAlarmCoordinator.swift @@ -1,6 +1,12 @@ -import Foundation +// +// RegularAlarmCoordinator.swift +// AlarmFeature +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// -import Domain +import Foundation public protocol RegularAlarmCoordinator: Coordinator { func startAddRegularAlarmFlow() diff --git a/Projects/Feature/AlarmFeature/Project.swift b/Projects/Feature/AlarmFeature/Project.swift index 5e825c74..bf6b3be6 100644 --- a/Projects/Feature/AlarmFeature/Project.swift +++ b/Projects/Feature/AlarmFeature/Project.swift @@ -5,10 +5,20 @@ let project = Project( name: "AlarmFeature", options: .options(automaticSchemesOptions: .disabled) ) { - Feature(name: "AlarmFeature") { + FeatureInterface(name: "AlarmFeature") { FeatureDependency() FeatureSwiftLintScript() FrameworkInfoPlist(marketingVersion: .marketingVersion) + } + FeatureImplement(name: "AlarmFeature") { + FeatureInterface(name: "AlarmFeature") + FeatureSwiftLintScript() + FrameworkInfoPlist(marketingVersion: .marketingVersion) + } + FeatureTesting(name: "AlarmFeature") { + FeatureImplement(name: "AlarmFeature") + FeatureSwiftLintScript() + FrameworkInfoPlist(marketingVersion: .marketingVersion) SecretInfoPlist() } SampleApp(name: "AlarmFeature") { diff --git a/Projects/Feature/AlarmFeature/Testing/Sources/Dependencies.swift b/Projects/Feature/AlarmFeature/Testing/Sources/Dependencies.swift new file mode 100644 index 00000000..54696bdf --- /dev/null +++ b/Projects/Feature/AlarmFeature/Testing/Sources/Dependencies.swift @@ -0,0 +1,10 @@ +// +// Dependencies.swift +// AlarmFeatureTesting +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +@_exported import AlarmFeature +@_exported import AlarmFeatureInterface diff --git a/Projects/Feature/AlarmFeature/Testing/Sources/MockAddRegularAlarmCoordinatorBuilder.swift b/Projects/Feature/AlarmFeature/Testing/Sources/MockAddRegularAlarmCoordinatorBuilder.swift new file mode 100644 index 00000000..18e36c00 --- /dev/null +++ b/Projects/Feature/AlarmFeature/Testing/Sources/MockAddRegularAlarmCoordinatorBuilder.swift @@ -0,0 +1,25 @@ +// +// MockAddRegularAlarmCoordinatorBuilder.swift +// AlarmFeatureTesting +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +import UIKit + +public final class MockAddRegularAlarmCoordinatorBuilder: AddRegularAlarmCoordinatorBuilder { + public init() { } + public func build( + parent: Coordinator, + navigationController: UINavigationController, + flow: FlowState + ) -> AddRegularAlarmCoordinator { + DefaultAddRegularAlarmCoordinator( + parent: parent, + navigationController: navigationController, + coordinatorProvider: MockCoordinatorProvider(), + flow: flow + ) + } +} diff --git a/Projects/Feature/BusStopFeature/Demo/SceneDelegate.swift b/Projects/Feature/BusStopFeature/Demo/SceneDelegate.swift index 1868c0f0..c4348855 100644 --- a/Projects/Feature/BusStopFeature/Demo/SceneDelegate.swift +++ b/Projects/Feature/BusStopFeature/Demo/SceneDelegate.swift @@ -3,6 +3,8 @@ import UIKit import FeatureDependency import Domain import BusStopFeature +import NearMapFeature +import AlarmFeatureTesting final class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? @@ -17,13 +19,16 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate { let navigationController = UINavigationController() window?.rootViewController = navigationController window?.makeKeyAndVisible() - + let coordinatorProvider = MockCoordinatorProvider() let busstopCoordinator = DefaultBusStopCoordinator( parent: nil, navigationController: navigationController, busStopId: "", coordinatorProvider: MockCoordinatorProvider(), - flow: .fromHome + flow: .fromHome, + nearMapCoordinatorBuilder: MockNearMapCoordinatorBuilder(), + addRegularAlarmCoordinatorBuilder: MockAddRegularAlarmCoordinatorBuilder(), + delegate: nil ) busstopCoordinator.start() } diff --git a/Projects/Feature/BusStopFeature/Project.swift b/Projects/Feature/BusStopFeature/Project.swift index 05731516..1b72b079 100644 --- a/Projects/Feature/BusStopFeature/Project.swift +++ b/Projects/Feature/BusStopFeature/Project.swift @@ -6,6 +6,8 @@ let project = Project( options: .options(automaticSchemesOptions: .disabled) ) { Feature(name: "BusStopFeature") { + FeatureInterface(name: "NearMapFeature") + FeatureInterface(name: "AlarmFeature") FeatureDependency() FeatureSwiftLintScript() FrameworkInfoPlist(marketingVersion: .marketingVersion) @@ -13,6 +15,8 @@ let project = Project( } SampleApp(name: "BusStopFeature") { Feature(name: "BusStopFeature") + Feature(name: "NearMapFeature") + FeatureTesting(name: "AlarmFeature") UIKitInfoPlist() AppInfoPlist( displayName: "BusStopFeatureSampleApp", diff --git a/Projects/Feature/BusStopFeature/Sources/Coordinator/DafaultBusStopCoordinator.swift b/Projects/Feature/BusStopFeature/Sources/Coordinator/DafaultBusStopCoordinator.swift index 5bce0a8f..b36bc8bc 100644 --- a/Projects/Feature/BusStopFeature/Sources/Coordinator/DafaultBusStopCoordinator.swift +++ b/Projects/Feature/BusStopFeature/Sources/Coordinator/DafaultBusStopCoordinator.swift @@ -2,28 +2,39 @@ import UIKit import Domain import FeatureDependency +import NearMapFeatureInterface +import AlarmFeatureInterface public final class DefaultBusStopCoordinator: BusStopCoordinator { public var parent: Coordinator? public var childs: [Coordinator] = [] public var navigationController: UINavigationController - public var coordinatorProvider: CoordinatorProvider - private var busStopId: String + public weak var delegate: BusStopCoordinatorDelegate? + + private let coordinatorProvider: CoordinatorProvider + private let busStopId: String private let flow: FlowState - public var coordinatorType: CoordinatorType = .busStop + private let nearMapCoordinatorBuilder: NearMapCoordinatorBuilder + private let addRegularAlarmCoordinatorBuilder: AddRegularAlarmCoordinatorBuilder public init( parent: Coordinator?, navigationController: UINavigationController, busStopId: String, coordinatorProvider: CoordinatorProvider, - flow: FlowState + flow: FlowState, + nearMapCoordinatorBuilder: NearMapCoordinatorBuilder, + addRegularAlarmCoordinatorBuilder: AddRegularAlarmCoordinatorBuilder, + delegate: BusStopCoordinatorDelegate? ) { self.parent = parent self.navigationController = navigationController self.busStopId = busStopId self.coordinatorProvider = coordinatorProvider self.flow = flow + self.nearMapCoordinatorBuilder = nearMapCoordinatorBuilder + self.addRegularAlarmCoordinatorBuilder = addRegularAlarmCoordinatorBuilder + self.delegate = delegate } public func start() { @@ -45,7 +56,7 @@ public final class DefaultBusStopCoordinator: BusStopCoordinator { extension DefaultBusStopCoordinator { // 정류장 위치뷰로 이동하기 위한 public func busStopMapLocation(busStopId: String) { - let nearMapCoordinator = coordinatorProvider.makeNearMapCoordinator( + let nearMapCoordinator = nearMapCoordinatorBuilder.build( parent: self, navigationController: navigationController, flow: flow, @@ -56,14 +67,12 @@ extension DefaultBusStopCoordinator { } public func moveToRegualrAlarm() { - let alarmCoordinator = coordinatorProvider - .makeAddRegularAlarmCoordinator( - parent: self, - navigationController: navigationController, - flow: .fromAlarm - ) + let alarmCoordinator = addRegularAlarmCoordinatorBuilder.build( + parent: self, + navigationController: navigationController, + flow: .fromAlarm + ) childs.append(alarmCoordinator) alarmCoordinator.start() } - } diff --git a/Projects/Feature/BusStopFeature/Sources/ViewModel/BusStopViewModel.swift b/Projects/Feature/BusStopFeature/Sources/ViewModel/BusStopViewModel.swift index c5882d44..3577018b 100644 --- a/Projects/Feature/BusStopFeature/Sources/ViewModel/BusStopViewModel.swift +++ b/Projects/Feature/BusStopFeature/Sources/ViewModel/BusStopViewModel.swift @@ -152,11 +152,7 @@ public final class BusStopViewModel: ViewModel { .withUnretained(self) .subscribe(onNext: { viewModel, arg1 in let (busInfo, busStopInfo) = arg1 - viewModel.useCase.update( - busStopInfo: busStopInfo, - busInfo: busInfo - ) - viewModel.coordinator.finishFlow(upTo: .addAlarm) + viewModel.coordinator.delegate?.didSelect(busStopInfo: busStopInfo, busInfo: busInfo) }) .disposed(by: disposeBag) diff --git a/Projects/Feature/HomeFeature/Sources/Coordinator/DefaultHomeCoordinator.swift b/Projects/Feature/HomeFeature/Implement/Sources/Coordinator/DefaultHomeCoordinator.swift similarity index 90% rename from Projects/Feature/HomeFeature/Sources/Coordinator/DefaultHomeCoordinator.swift rename to Projects/Feature/HomeFeature/Implement/Sources/Coordinator/DefaultHomeCoordinator.swift index 148bade3..600fbef9 100644 --- a/Projects/Feature/HomeFeature/Sources/Coordinator/DefaultHomeCoordinator.swift +++ b/Projects/Feature/HomeFeature/Implement/Sources/Coordinator/DefaultHomeCoordinator.swift @@ -10,7 +10,6 @@ public final class DefaultHomeCoordinator { public var childs: [Coordinator] = [] public var navigationController: UINavigationController public let coordinatorProvider: CoordinatorProvider - public var coordinatorType: CoordinatorType = .home private let favoritesStatus = PublishSubject() private let disposeBag = DisposeBag() @@ -49,15 +48,12 @@ public final class DefaultHomeCoordinator { } extension DefaultHomeCoordinator: HomeCoordinator { - public func updateFavoritesState(isEmpty: Bool) { - favoritesStatus.onNext(isEmpty ? .empty : .nonEmpty) - } - public func startSearchFlow() { let searchCoordinator = coordinatorProvider.makeSearchCoordinator( parent: self, navigationController: navigationController, - flow: .fromHome + flow: .fromHome, + busStopCoordinatorDelegate: nil ) childs.append(searchCoordinator) searchCoordinator.start() @@ -69,7 +65,8 @@ extension DefaultHomeCoordinator: HomeCoordinator { parent: self, navigationController: navigationController, busStopId: stationId, - flow: .fromHome + flow: .fromHome, + delegate: nil ) childs.append(busStopCoordinator) busStopCoordinator.start() diff --git a/Projects/Feature/HomeFeature/Implement/Sources/Dependencies.swift b/Projects/Feature/HomeFeature/Implement/Sources/Dependencies.swift new file mode 100644 index 00000000..2d5f5a14 --- /dev/null +++ b/Projects/Feature/HomeFeature/Implement/Sources/Dependencies.swift @@ -0,0 +1,9 @@ +// +// Dependencies.swift +// HomeFeatureInterface +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +@_exported import HomeFeatureInterface diff --git a/Projects/Feature/HomeFeature/Sources/View/EmptyFavoritesView.swift b/Projects/Feature/HomeFeature/Implement/Sources/View/EmptyFavoritesView.swift similarity index 100% rename from Projects/Feature/HomeFeature/Sources/View/EmptyFavoritesView.swift rename to Projects/Feature/HomeFeature/Implement/Sources/View/EmptyFavoritesView.swift diff --git a/Projects/Feature/HomeFeature/Sources/View/FavoritesHeaderView.swift b/Projects/Feature/HomeFeature/Implement/Sources/View/FavoritesHeaderView.swift similarity index 100% rename from Projects/Feature/HomeFeature/Sources/View/FavoritesHeaderView.swift rename to Projects/Feature/HomeFeature/Implement/Sources/View/FavoritesHeaderView.swift diff --git a/Projects/Feature/HomeFeature/Sources/View/FavoritesTVCell.swift b/Projects/Feature/HomeFeature/Implement/Sources/View/FavoritesTVCell.swift similarity index 100% rename from Projects/Feature/HomeFeature/Sources/View/FavoritesTVCell.swift rename to Projects/Feature/HomeFeature/Implement/Sources/View/FavoritesTVCell.swift diff --git a/Projects/Feature/HomeFeature/Sources/ViewController/FavoritesViewController.swift b/Projects/Feature/HomeFeature/Implement/Sources/ViewController/FavoritesViewController.swift similarity index 100% rename from Projects/Feature/HomeFeature/Sources/ViewController/FavoritesViewController.swift rename to Projects/Feature/HomeFeature/Implement/Sources/ViewController/FavoritesViewController.swift diff --git a/Projects/Feature/HomeFeature/Sources/ViewModel/FavoritesViewModel.swift b/Projects/Feature/HomeFeature/Implement/Sources/ViewModel/FavoritesViewModel.swift similarity index 100% rename from Projects/Feature/HomeFeature/Sources/ViewModel/FavoritesViewModel.swift rename to Projects/Feature/HomeFeature/Implement/Sources/ViewModel/FavoritesViewModel.swift diff --git a/Projects/Feature/HomeFeature/Interface/Sources/HomeCoordinator.swift b/Projects/Feature/HomeFeature/Interface/Sources/HomeCoordinator.swift new file mode 100644 index 00000000..c13eec21 --- /dev/null +++ b/Projects/Feature/HomeFeature/Interface/Sources/HomeCoordinator.swift @@ -0,0 +1,23 @@ +// +// HomeCoordinator.swift +// HomeFeatureInterface +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +import UIKit + +import FeatureDependency + +public protocol HomeCoordinator: Coordinator { + func startSearchFlow() + func startBusStopFlow(stationId: String) +} + +public protocol HomeCoordinatorBuilder { + func build( + parent: Coordinator, + navigationController: UINavigationController + ) -> HomeCoordinator +} diff --git a/Projects/Feature/HomeFeature/Project.swift b/Projects/Feature/HomeFeature/Project.swift index fa28c993..2572562f 100644 --- a/Projects/Feature/HomeFeature/Project.swift +++ b/Projects/Feature/HomeFeature/Project.swift @@ -5,10 +5,15 @@ let project = Project( name: "HomeFeature", options: .options(automaticSchemesOptions: .disabled) ) { - Feature(name: "HomeFeature") { + FeatureInterface(name: "HomeFeature") { FeatureDependency() FeatureSwiftLintScript() FrameworkInfoPlist(marketingVersion: .marketingVersion) + } + FeatureImplement(name: "HomeFeature") { + FeatureInterface(name: "HomeFeature") + FeatureSwiftLintScript() + FrameworkInfoPlist(marketingVersion: .marketingVersion) SecretInfoPlist() } SampleApp(name: "HomeFeature") { diff --git a/Projects/Feature/NearMapFeature/Sources/Coordinator/DafaultNearMapCoordinator.swift b/Projects/Feature/NearMapFeature/Implement/Sources/Coordinator/DafaultNearMapCoordinator.swift similarity index 93% rename from Projects/Feature/NearMapFeature/Sources/Coordinator/DafaultNearMapCoordinator.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/Coordinator/DafaultNearMapCoordinator.swift index 2b363d56..8e237fcb 100644 --- a/Projects/Feature/NearMapFeature/Sources/Coordinator/DafaultNearMapCoordinator.swift +++ b/Projects/Feature/NearMapFeature/Implement/Sources/Coordinator/DafaultNearMapCoordinator.swift @@ -1,6 +1,6 @@ import UIKit -import FeatureDependency +import NearMapFeatureInterface import RxSwift @@ -11,7 +11,6 @@ public final class DefaultNearMapCoordinator: NearMapCoordinator { public var coordinatorProvider: CoordinatorProvider public let flow: FlowState public let busStopId: String? - public var coordinatorType: CoordinatorType = .nearMap public init( parent: Coordinator?, @@ -49,7 +48,8 @@ extension DefaultNearMapCoordinator { parent: self, navigationController: navigationController, busStopId: busStopId, - flow: flow + flow: flow, + delegate: nil ) childs.append(busStopCoordinator) busStopCoordinator.start() diff --git a/Projects/Feature/NearMapFeature/Sources/NMapsClustreing/BusStopClusteringKey.swift b/Projects/Feature/NearMapFeature/Implement/Sources/NMapsClustreing/BusStopClusteringKey.swift similarity index 100% rename from Projects/Feature/NearMapFeature/Sources/NMapsClustreing/BusStopClusteringKey.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/NMapsClustreing/BusStopClusteringKey.swift diff --git a/Projects/Feature/NearMapFeature/Sources/NMapsClustreing/LeafMarkerUpdater.swift b/Projects/Feature/NearMapFeature/Implement/Sources/NMapsClustreing/LeafMarkerUpdater.swift similarity index 100% rename from Projects/Feature/NearMapFeature/Sources/NMapsClustreing/LeafMarkerUpdater.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/NMapsClustreing/LeafMarkerUpdater.swift diff --git a/Projects/Feature/NearMapFeature/Sources/View/BusStopInformationView.swift b/Projects/Feature/NearMapFeature/Implement/Sources/View/BusStopInformationView.swift similarity index 100% rename from Projects/Feature/NearMapFeature/Sources/View/BusStopInformationView.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/View/BusStopInformationView.swift diff --git a/Projects/Feature/NearMapFeature/Sources/ViewController/NearMapViewController.swift b/Projects/Feature/NearMapFeature/Implement/Sources/ViewController/NearMapViewController.swift similarity index 100% rename from Projects/Feature/NearMapFeature/Sources/ViewController/NearMapViewController.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/ViewController/NearMapViewController.swift diff --git a/Projects/Feature/NearMapFeature/Sources/ViewModel/NearMapViewModel.swift b/Projects/Feature/NearMapFeature/Implement/Sources/ViewModel/NearMapViewModel.swift similarity index 99% rename from Projects/Feature/NearMapFeature/Sources/ViewModel/NearMapViewModel.swift rename to Projects/Feature/NearMapFeature/Implement/Sources/ViewModel/NearMapViewModel.swift index e2db0097..4ccdbd4e 100644 --- a/Projects/Feature/NearMapFeature/Sources/ViewModel/NearMapViewModel.swift +++ b/Projects/Feature/NearMapFeature/Implement/Sources/ViewModel/NearMapViewModel.swift @@ -3,7 +3,7 @@ import UIKit import Core import DesignSystem import Domain -import FeatureDependency +import NearMapFeatureInterface import RxSwift import RxRelay diff --git a/Projects/Feature/NearMapFeature/Interface/Sources/NearMapCoordinator.swift b/Projects/Feature/NearMapFeature/Interface/Sources/NearMapCoordinator.swift new file mode 100644 index 00000000..ee82b08d --- /dev/null +++ b/Projects/Feature/NearMapFeature/Interface/Sources/NearMapCoordinator.swift @@ -0,0 +1,24 @@ +// +// NearMapCoordinator.swift +// NearMapFeature +// +// Created by gnksbm on 7/12/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +import UIKit + +@_exported import FeatureDependency + +public protocol NearMapCoordinator: Coordinator { + func startBusStopFlow(busStopId: String) +} + +public protocol NearMapCoordinatorBuilder { + func build( + parent: Coordinator, + navigationController: UINavigationController, + flow: FlowState, + busStopId: String? + ) -> NearMapCoordinator +} diff --git a/Projects/Feature/NearMapFeature/Project.swift b/Projects/Feature/NearMapFeature/Project.swift index 986a04dc..f0f6dfbd 100644 --- a/Projects/Feature/NearMapFeature/Project.swift +++ b/Projects/Feature/NearMapFeature/Project.swift @@ -5,10 +5,21 @@ let project = Project( name: "NearMapFeature", options: .options(automaticSchemesOptions: .disabled) ) { - Feature(name: "NearMapFeature") { + FeatureInterface(name: "NearMapFeature") { FeatureDependency() FeatureSwiftLintScript() FrameworkInfoPlist(marketingVersion: .marketingVersion) + } + FeatureImplement(name: "NearMapFeature") { + FeatureInterface(name: "NearMapFeature") + FeatureSwiftLintScript() + FrameworkInfoPlist(marketingVersion: .marketingVersion) + SecretInfoPlist() + } + FeatureTesting(name: "NearMapFeature") { + FeatureImplement(name: "NearMapFeature") + FeatureSwiftLintScript() + FrameworkInfoPlist(marketingVersion: .marketingVersion) SecretInfoPlist() } SampleApp(name: "NearMapFeature") { diff --git a/Projects/Feature/NearMapFeature/Testing/Sources/Dependencies.swift b/Projects/Feature/NearMapFeature/Testing/Sources/Dependencies.swift new file mode 100644 index 00000000..2a3c46c0 --- /dev/null +++ b/Projects/Feature/NearMapFeature/Testing/Sources/Dependencies.swift @@ -0,0 +1,10 @@ +// +// Dependencies.swift +// NearMapFeature +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +@_exported import NearMapFeature +@_exported import NearMapFeatureInterface diff --git a/Projects/Feature/NearMapFeature/Testing/Sources/MockNearMapCoordinatorBuilder.swift b/Projects/Feature/NearMapFeature/Testing/Sources/MockNearMapCoordinatorBuilder.swift new file mode 100644 index 00000000..64eaf6c3 --- /dev/null +++ b/Projects/Feature/NearMapFeature/Testing/Sources/MockNearMapCoordinatorBuilder.swift @@ -0,0 +1,29 @@ +// +// MockNearMapCoordinatorBuilder.swift +// NearMapFeature +// +// Created by gnksbm on 7/19/25. +// Copyright © 2025 Pepsi-Club. All rights reserved. +// + +import UIKit + +public final class MockNearMapCoordinatorBuilder: NearMapCoordinatorBuilder { + public init() { } + + public func build( + parent: Coordinator, + navigationController: UINavigationController, + flow: FlowState, + busStopId: String? + ) -> NearMapCoordinator { + DefaultNearMapCoordinator( + parent: parent, + navigationController: navigationController, + coordinatorProvider: MockCoordinatorProvider(), + flow: flow, + busStopId: busStopId + ) + } +} + diff --git a/Projects/Feature/SearchFeature/Project.swift b/Projects/Feature/SearchFeature/Project.swift index 3cbaa1df..a3ef724e 100644 --- a/Projects/Feature/SearchFeature/Project.swift +++ b/Projects/Feature/SearchFeature/Project.swift @@ -6,6 +6,7 @@ let project = Project( options: .options(automaticSchemesOptions: .disabled) ) { Feature(name: "SearchFeature") { + FeatureInterface(name: "NearMapFeature") FeatureDependency() FeatureSwiftLintScript() FrameworkInfoPlist(marketingVersion: .marketingVersion) diff --git a/Projects/Feature/SearchFeature/Sources/Coordinator/DafaultSearchCoordinator.swift b/Projects/Feature/SearchFeature/Sources/Coordinator/DafaultSearchCoordinator.swift index d0e12e05..8993f435 100644 --- a/Projects/Feature/SearchFeature/Sources/Coordinator/DafaultSearchCoordinator.swift +++ b/Projects/Feature/SearchFeature/Sources/Coordinator/DafaultSearchCoordinator.swift @@ -2,24 +2,31 @@ import UIKit import Domain import FeatureDependency +import NearMapFeatureInterface public final class DefaultSearchCoordinator: SearchCoordinator { public var parent: Coordinator? public var childs: [Coordinator] = [] public let navigationController: UINavigationController - public let coordinatorProvider: CoordinatorProvider + public weak var busStopCoordinatorDelegate: BusStopCoordinatorDelegate? + + private let coordinatorProvider: CoordinatorProvider + private let nearMapCoordinatorBuilder: NearMapCoordinatorBuilder private let flow: FlowState - public var coordinatorType: CoordinatorType = .search public init( parent: Coordinator?, navigationController: UINavigationController, coordinatorProvider: CoordinatorProvider, + nearMapCoordinatorBuilder: NearMapCoordinatorBuilder, + busStopCoordinatorDelegate: BusStopCoordinatorDelegate?, flow: FlowState ) { self.parent = parent self.navigationController = navigationController self.coordinatorProvider = coordinatorProvider + self.nearMapCoordinatorBuilder = nearMapCoordinatorBuilder + self.busStopCoordinatorDelegate = busStopCoordinatorDelegate self.flow = flow } @@ -35,19 +42,20 @@ public final class DefaultSearchCoordinator: SearchCoordinator { } extension DefaultSearchCoordinator { - public func startBusStopFlow(stationId: String) { + public func startBusStopFlow(busStopID: String) { let busStopCoordinator = coordinatorProvider.makeBusStopCoordinator( parent: self, navigationController: navigationController, - busStopId: stationId, - flow: flow + busStopId: busStopID, + flow: flow, + delegate: busStopCoordinatorDelegate ) childs.append(busStopCoordinator) busStopCoordinator.start() } public func startNearMapFlow() { - let nearMapCoordinator = coordinatorProvider.makeNearMapCoordinator( + let nearMapCoordinator = nearMapCoordinatorBuilder.build( parent: self, navigationController: navigationController, flow: flow, @@ -57,12 +65,12 @@ extension DefaultSearchCoordinator { nearMapCoordinator.start() } - public func startNearMapFlow(busStopId: String) { - let nearMapCoordinator = coordinatorProvider.makeNearMapCoordinator( + public func startNearMapFlow(busStopID: String) { + let nearMapCoordinator = nearMapCoordinatorBuilder.build( parent: self, navigationController: navigationController, flow: flow, - busStopId: busStopId + busStopId: busStopID ) childs.append(nearMapCoordinator) nearMapCoordinator.start() diff --git a/Projects/Feature/SearchFeature/Sources/ViewModel/SearchViewModel.swift b/Projects/Feature/SearchFeature/Sources/ViewModel/SearchViewModel.swift index c7519a0c..26d1a219 100644 --- a/Projects/Feature/SearchFeature/Sources/ViewModel/SearchViewModel.swift +++ b/Projects/Feature/SearchFeature/Sources/ViewModel/SearchViewModel.swift @@ -65,7 +65,7 @@ public final class SearchViewModel: ViewModel { onNext: { viewModel, response in viewModel.useCase.saveRecentSearch(response: response) viewModel.coordinator.startBusStopFlow( - stationId: response.busStopId + busStopID: response.busStopId ) } ) @@ -90,7 +90,7 @@ public final class SearchViewModel: ViewModel { .withUnretained(self) .subscribe( onNext: { vm, busStopId in - vm.coordinator.startNearMapFlow(busStopId: busStopId) + vm.coordinator.startNearMapFlow(busStopID: busStopId) } ) .disposed(by: disposeBag) diff --git a/Projects/Feature/SettingsFeature/Sources/Coordinator/DefaultSettingsCoordinator.swift b/Projects/Feature/SettingsFeature/Sources/Coordinator/DefaultSettingsCoordinator.swift index e6a75f64..e80f6b8a 100644 --- a/Projects/Feature/SettingsFeature/Sources/Coordinator/DefaultSettingsCoordinator.swift +++ b/Projects/Feature/SettingsFeature/Sources/Coordinator/DefaultSettingsCoordinator.swift @@ -6,7 +6,6 @@ public final class DefaultSettingsCoordinator { public var parent: Coordinator? public var childs: [Coordinator] = [] public var navigationController: UINavigationController - public var coordinatorType: CoordinatorType = .setting public init(navigationController: UINavigationController) { self.navigationController = navigationController diff --git a/Projects/FeatureDependency/Sources/Coordinator/AddRegularAlarmCoordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/AddRegularAlarmCoordinator.swift deleted file mode 100644 index 6491a1b2..00000000 --- a/Projects/FeatureDependency/Sources/Coordinator/AddRegularAlarmCoordinator.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// AddRegularAlarmCoordinator.swift -// AlarmFeature -// -// Created by gnksbm on 2/2/24. -// Copyright © 2024 Pepsi-Club. All rights reserved. -// - -import Foundation - -import Domain - -public protocol AddRegularAlarmCoordinator: Coordinator { - func start(with: RegularAlarmResponse) - func startSearchFlow() - func removeChildViewController() -} diff --git a/Projects/FeatureDependency/Sources/Coordinator/BusStopCoordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/BusStopCoordinator.swift index 1cbe8ff5..b2ba9a10 100644 --- a/Projects/FeatureDependency/Sources/Coordinator/BusStopCoordinator.swift +++ b/Projects/FeatureDependency/Sources/Coordinator/BusStopCoordinator.swift @@ -6,9 +6,15 @@ // Copyright © 2024 Pepsi-Club. All rights reserved. // -import Foundation +import Domain public protocol BusStopCoordinator: Coordinator { + var delegate: BusStopCoordinatorDelegate? { get } + func busStopMapLocation(busStopId: String) func moveToRegualrAlarm() } + +public protocol BusStopCoordinatorDelegate: AnyObject { + func didSelect(busStopInfo: BusStopArrivalInfoResponse, busInfo: BusArrivalInfoResponse) +} diff --git a/Projects/FeatureDependency/Sources/Coordinator/Coordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/Coordinator.swift index cb2fd62c..c6aee168 100644 --- a/Projects/FeatureDependency/Sources/Coordinator/Coordinator.swift +++ b/Projects/FeatureDependency/Sources/Coordinator/Coordinator.swift @@ -14,7 +14,6 @@ public protocol Coordinator: AnyObject { var parent: Coordinator? { get set } var childs: [Coordinator] { get set } var navigationController: UINavigationController { get } - var coordinatorType: CoordinatorType { get } func start() func finish() @@ -35,22 +34,6 @@ public extension Coordinator { parent?.childDidFinish(self) } - func finishFlow( - upTo coordinatorKind: CoordinatorType - ) { - var currentCoordinator: Coordinator = self - var isRoot = false - while !isRoot { - guard let nextCoordinator = currentCoordinator.parent else { break } - currentCoordinator.finish() - currentCoordinator = nextCoordinator - isRoot = currentCoordinator.coordinatorType == coordinatorKind - } - // TODO: 재사용 로직으로 수정 - (currentCoordinator as? AddRegularAlarmCoordinator)? - .removeChildViewController() - } - func openURL(_ url: URL) { parent?.openURL(url) } diff --git a/Projects/FeatureDependency/Sources/Coordinator/CoordinatorProvider.swift b/Projects/FeatureDependency/Sources/Coordinator/CoordinatorProvider.swift index fd9787f9..8362f63d 100644 --- a/Projects/FeatureDependency/Sources/Coordinator/CoordinatorProvider.swift +++ b/Projects/FeatureDependency/Sources/Coordinator/CoordinatorProvider.swift @@ -14,26 +14,15 @@ public protocol CoordinatorProvider { func makeSearchCoordinator( parent: Coordinator, navigationController: UINavigationController, - flow: FlowState + flow: FlowState, + busStopCoordinatorDelegate: BusStopCoordinatorDelegate? ) -> SearchCoordinator func makeBusStopCoordinator( parent: Coordinator, navigationController: UINavigationController, busStopId: String, - flow: FlowState - ) -> BusStopCoordinator - - func makeAddRegularAlarmCoordinator( - parent: Coordinator, - navigationController: UINavigationController, - flow: FlowState - ) -> AddRegularAlarmCoordinator - - func makeNearMapCoordinator( - parent: Coordinator, - navigationController: UINavigationController, flow: FlowState, - busStopId: String? - ) -> NearMapCoordinator + delegate: BusStopCoordinatorDelegate? + ) -> BusStopCoordinator } diff --git a/Projects/FeatureDependency/Sources/Coordinator/CoordinatorType.swift b/Projects/FeatureDependency/Sources/Coordinator/CoordinatorType.swift deleted file mode 100644 index 38097bea..00000000 --- a/Projects/FeatureDependency/Sources/Coordinator/CoordinatorType.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// CoordinatorType.swift -// FeatureDependency -// -// Created by Jisoo HAM on 3/18/24. -// Copyright © 2024 Pepsi-Club. All rights reserved. -// - -import UIKit - -public enum CoordinatorType { - case app - case splash - case tab - case addAlarm - case home - case search - case nearMap - case busStop - case setting - case regularAlarm -} diff --git a/Projects/FeatureDependency/Sources/Coordinator/HomeCoordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/HomeCoordinator.swift deleted file mode 100644 index 01e4bbc1..00000000 --- a/Projects/FeatureDependency/Sources/Coordinator/HomeCoordinator.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// HomeCoordinator.swift -// FeatureDependency -// -// Created by gnksbm on 1/26/24. -// Copyright © 2024 Pepsi-Club. All rights reserved. -// - -import Foundation - -public protocol HomeCoordinator: Coordinator { - func updateFavoritesState(isEmpty: Bool) - func startSearchFlow() - func startBusStopFlow(stationId: String) -} diff --git a/Projects/FeatureDependency/Sources/Coordinator/NearMapCoordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/NearMapCoordinator.swift deleted file mode 100644 index f0f67008..00000000 --- a/Projects/FeatureDependency/Sources/Coordinator/NearMapCoordinator.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// NearMapCoordinator.swift -// FeatureDependency -// -// Created by Muker on 2/2/24. -// Copyright © 2024 Pepsi-Club. All rights reserved. -// - -import Foundation - -public protocol NearMapCoordinator: Coordinator { - func startBusStopFlow(busStopId: String) -} diff --git a/Projects/FeatureDependency/Sources/Coordinator/SearchCoordinator.swift b/Projects/FeatureDependency/Sources/Coordinator/SearchCoordinator.swift index 08f6bc9e..bc311ee5 100644 --- a/Projects/FeatureDependency/Sources/Coordinator/SearchCoordinator.swift +++ b/Projects/FeatureDependency/Sources/Coordinator/SearchCoordinator.swift @@ -10,7 +10,7 @@ import Foundation import Domain public protocol SearchCoordinator: Coordinator { - func startBusStopFlow(stationId: String) + func startBusStopFlow(busStopID: String) func startNearMapFlow() - func startNearMapFlow(busStopId: String) + func startNearMapFlow(busStopID: String) } diff --git a/Projects/FeatureDependency/Sources/Mock/MockCoordinator.swift b/Projects/FeatureDependency/Sources/Mock/MockCoordinator.swift index 58e2513a..2f0c2678 100644 --- a/Projects/FeatureDependency/Sources/Mock/MockCoordinator.swift +++ b/Projects/FeatureDependency/Sources/Mock/MockCoordinator.swift @@ -14,7 +14,8 @@ import Domain public final class MockCoordinator: Coordinator { public var parent: Coordinator? public var childs: [Coordinator] = [] - public var coordinatorType: CoordinatorType = .home + + public var busStopCoordinatorDelegate: BusStopCoordinatorDelegate? private let testMessage: String public var navigationController: UINavigationController @@ -51,23 +52,17 @@ public final class MockCoordinator: Coordinator { } } -extension MockCoordinator: HomeCoordinator { - public func updateFavoritesState(isEmpty: Bool) { - - } - - public func startBusStopFlow(stationId: String) { +extension MockCoordinator: SearchCoordinator { + public func startNearMapFlow(busStopID: String) { let coordinator = MockCoordinator( - testMessage: "BusStopFlow - busStopId: \(stationId)", + testMessage: "\(#function)", navigationController: navigationController ) coordinator.start() childs.append(coordinator) } -} - -extension MockCoordinator: SearchCoordinator { - public func startNearMapFlow(busStopId: String) { + + public func startNearMapFlow() { let coordinator = MockCoordinator( testMessage: "\(#function)", navigationController: navigationController @@ -76,7 +71,7 @@ extension MockCoordinator: SearchCoordinator { childs.append(coordinator) } - public func startNearMapFlow() { + public func startBusStopFlow(busStopID: String) { let coordinator = MockCoordinator( testMessage: "\(#function)", navigationController: navigationController @@ -93,6 +88,8 @@ extension MockCoordinator: SearchCoordinator { extension MockCoordinator: BusStopCoordinator { + public var delegate: BusStopCoordinatorDelegate? { busStopCoordinatorDelegate } + public func example() { } @@ -116,28 +113,4 @@ extension MockCoordinator: BusStopCoordinator { } } -extension MockCoordinator: AddRegularAlarmCoordinator { - public func start(with: RegularAlarmResponse) { - - } - - public func startSearchFlow() { - - } - - public func removeChildViewController() { - - } -} - -extension MockCoordinator: NearMapCoordinator { - public func startBusStopFlow(busStopId: String) { - let coordinator = MockCoordinator( - testMessage: "BusStopFlow - busStopId: \(busStopId)", - navigationController: navigationController - ) - coordinator.start() - childs.append(coordinator) - } -} #endif diff --git a/Projects/FeatureDependency/Sources/Mock/MockCoordinatorProvider.swift b/Projects/FeatureDependency/Sources/Mock/MockCoordinatorProvider.swift index bbf746ab..8f560dac 100644 --- a/Projects/FeatureDependency/Sources/Mock/MockCoordinatorProvider.swift +++ b/Projects/FeatureDependency/Sources/Mock/MockCoordinatorProvider.swift @@ -17,7 +17,8 @@ public final class MockCoordinatorProvider: CoordinatorProvider { public func makeSearchCoordinator( parent: Coordinator, navigationController: UINavigationController, - flow: FlowState + flow: FlowState, + busStopCoordinatorDelegate: BusStopCoordinatorDelegate? ) -> SearchCoordinator { MockCoordinator( testMessage: "Search", @@ -29,35 +30,14 @@ public final class MockCoordinatorProvider: CoordinatorProvider { parent: Coordinator, navigationController: UINavigationController, busStopId: String, - flow: FlowState + flow: FlowState, + delegate: BusStopCoordinatorDelegate? ) -> BusStopCoordinator { MockCoordinator( testMessage: "BusStop - busStopId: \(busStopId)", navigationController: navigationController ) } - - public func makeAddRegularAlarmCoordinator( - parent: Coordinator, - navigationController: UINavigationController, - flow: FlowState - ) -> AddRegularAlarmCoordinator { - MockCoordinator( - testMessage: "AddRegularAlarm", - navigationController: navigationController - ) - } - - public func makeNearMapCoordinator( - parent: Coordinator, - navigationController: UINavigationController, - flow: FlowState, - busStopId: String? = nil - ) -> NearMapCoordinator { - MockCoordinator( - testMessage: "NearMap - busStopId: \(busStopId ?? "nil")", - navigationController: navigationController - ) - } } + #endif diff --git a/Projects/MainFeature/Sources/TabBarCoordinator.swift b/Projects/MainFeature/Sources/TabBarCoordinator.swift index 497983bc..afe75bcd 100644 --- a/Projects/MainFeature/Sources/TabBarCoordinator.swift +++ b/Projects/MainFeature/Sources/TabBarCoordinator.swift @@ -11,7 +11,7 @@ import UIKit import DesignSystem import FeatureDependency -import HomeFeature +import HomeFeatureInterface import AlarmFeature import SettingsFeature @@ -20,14 +20,16 @@ public final class TabBarCoordinator: Coordinator { public var childs: [Coordinator] = [] public var navigationController: UINavigationController public let coordinatorProvider: CoordinatorProvider - public var coordinatorType: CoordinatorType = .tab + public let homeCoordinatorBuilder: HomeCoordinatorBuilder public init( navigationController: UINavigationController, - coordinatorProvider: CoordinatorProvider + coordinatorProvider: CoordinatorProvider, + homeCoordinatorBuilder: HomeCoordinatorBuilder ) { self.navigationController = navigationController self.coordinatorProvider = coordinatorProvider + self.homeCoordinatorBuilder = homeCoordinatorBuilder } public func start() { @@ -69,10 +71,9 @@ public final class TabBarCoordinator: Coordinator { var coordinator: Coordinator switch tabKind { case .home: - coordinator = DefaultHomeCoordinator( - parent: self, - navigationController: navigationController, - coordinatorProvider: coordinatorProvider + coordinator = homeCoordinatorBuilder.build( + parent: self, + navigationController: navigationController ) case .settings: coordinator = DefaultSettingsCoordinator(