diff --git a/DependencyGraph/mohanyang_dev_graph.png b/DependencyGraph/mohanyang_dev_graph.png
index 6925cd5..a6a9607 100644
Binary files a/DependencyGraph/mohanyang_dev_graph.png and b/DependencyGraph/mohanyang_dev_graph.png differ
diff --git a/DependencyGraph/mohanyang_prod_graph.png b/DependencyGraph/mohanyang_prod_graph.png
index f11940b..ba40e0a 100644
Binary files a/DependencyGraph/mohanyang_prod_graph.png and b/DependencyGraph/mohanyang_prod_graph.png differ
diff --git a/Makefile b/Makefile
index 01c3f48..ba34001 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ dev:
.PHONY: prod
prod:
- make generate config=prod
+ make generate config=prod target=Mohanyang
### Script ###
diff --git a/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Domain.swift b/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Domain.swift
index 1decdde..f341b7c 100644
--- a/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Domain.swift
+++ b/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Domain.swift
@@ -10,4 +10,5 @@ import Foundation
@_spi(Domain)
public enum Domain: String, Modulable {
case AppService
+ case PushService
}
diff --git a/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Feature.swift b/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Feature.swift
index 57c5720..fc7a525 100644
--- a/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Feature.swift
+++ b/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Module/Feature.swift
@@ -9,5 +9,6 @@ import Foundation
@_spi(Feature)
public enum Feature: String, Modulable {
- case AppFeature
+ case HomeFeature
+ case OnboardingFeature
}
diff --git a/Projects/App/Sources/AppDelegate.swift b/Projects/App/Sources/AppDelegate.swift
index 1a4186d..a93c652 100644
--- a/Projects/App/Sources/AppDelegate.swift
+++ b/Projects/App/Sources/AppDelegate.swift
@@ -9,56 +9,56 @@
import SwiftUI
import UserNotifications
-import AppFeature
+import Feature
import DesignSystem
-//import FirebaseMessaging
+import ComposableArchitecture
-//final class AppDelegate: UIResponder, UIApplicationDelegate {
-// let store = Store(
-// initialState: AppCore.State()
-// ) {
-// AppCore()
-// }
-//
-// func application(
-// _ application: UIApplication,
-// didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
-// ) -> Bool {
-// self.store.send(.appDelegate(.didFinishLaunching))
-// return true
-// }
-//
-// func application(
-// _ application: UIApplication,
-// didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
-// ) {
-// self.store.send(.appDelegate(.didRegisterForRemoteNotifications(.success(deviceToken))))
-// }
-//
-// func application(
-// _ application: UIApplication,
-// didFailToRegisterForRemoteNotificationsWithError error: Error
-// ) {
-// self.store.send(.appDelegate(.didRegisterForRemoteNotifications(.failure(error))))
-// }
-//}
-//
-//@main
-//struct KimcaddieOwnerApp: App {
-// @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
-// @Environment(\.scenePhase) private var scenePhase
-//
-// init() {
-// DesignSystemFontFamily.registerAllCustomFonts()
-// }
-//
-// var body: some Scene {
-// WindowGroup {
-// AppView(store: self.appDelegate.store)
-// }
-// .onChange(of: self.scenePhase) { value in
-// self.appDelegate.store.send(.didChangeScenePhase(value))
-// }
-// }
-//}
+final class AppDelegate: UIResponder, UIApplicationDelegate {
+ let store = Store(
+ initialState: AppCore.State()
+ ) {
+ AppCore()
+ }
+
+ func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ self.store.send(.appDelegate(.didFinishLaunching))
+ return true
+ }
+
+ func application(
+ _ application: UIApplication,
+ didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
+ ) {
+ self.store.send(.appDelegate(.didRegisterForRemoteNotifications(.success(deviceToken))))
+ }
+
+ func application(
+ _ application: UIApplication,
+ didFailToRegisterForRemoteNotificationsWithError error: Error
+ ) {
+ self.store.send(.appDelegate(.didRegisterForRemoteNotifications(.failure(error))))
+ }
+}
+
+@main
+struct MohanyangApp: App {
+ @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
+ @Environment(\.scenePhase) private var scenePhase
+
+ init() {
+ DesignSystemFontFamily.registerAllCustomFonts()
+ }
+
+ var body: some Scene {
+ WindowGroup {
+ AppView(store: self.appDelegate.store)
+ }
+ .onChange(of: self.scenePhase) { oldValue, newValue in
+ self.appDelegate.store.send(.didChangeScenePhase(newValue))
+ }
+ }
+}
diff --git a/Projects/Core/Core/Project.swift b/Projects/Core/Core/Project.swift
index b97882b..6317c5a 100644
--- a/Projects/Core/Core/Project.swift
+++ b/Projects/Core/Core/Project.swift
@@ -7,5 +7,5 @@ import DependencyPlugin
let project: Project = .makeRootProject(
rootModule: Core.self,
scripts: [],
- product: .framework
+ product: .staticLibrary
)
diff --git a/Projects/Domain/Domain/Project.swift b/Projects/Domain/Domain/Project.swift
index e5275e6..11f801e 100644
--- a/Projects/Domain/Domain/Project.swift
+++ b/Projects/Domain/Domain/Project.swift
@@ -7,5 +7,5 @@ import DependencyPlugin
let project: Project = .makeRootProject(
rootModule: Domain.self,
scripts: [],
- product: .framework
+ product: .staticLibrary
)
diff --git a/Projects/Domain/PushService/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Projects/Domain/PushService/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..f1cb98f
--- /dev/null
+++ b/Projects/Domain/PushService/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,14 @@
+{
+ "images" : [
+ {
+ "filename" : "ICON_DEMO.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Domain/PushService/Example/Resources/Assets.xcassets/contents.json b/Projects/Domain/PushService/Example/Resources/Assets.xcassets/contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/Projects/Domain/PushService/Example/Resources/Assets.xcassets/contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Bold.otf b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Bold.otf
new file mode 100644
index 0000000..a52ef39
Binary files /dev/null and b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Bold.otf differ
diff --git a/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Medium.otf b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Medium.otf
new file mode 100644
index 0000000..a2dc009
Binary files /dev/null and b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Medium.otf differ
diff --git a/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Regular.otf b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Regular.otf
new file mode 100644
index 0000000..c940185
Binary files /dev/null and b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-Regular.otf differ
diff --git a/Projects/Domain/PushService/Example/Resources/Font/Pretendard-SemiBold.otf b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-SemiBold.otf
new file mode 100644
index 0000000..c375b54
Binary files /dev/null and b/Projects/Domain/PushService/Example/Resources/Font/Pretendard-SemiBold.otf differ
diff --git a/Projects/Domain/PushService/Example/Resources/LaunchScreen.storyboard b/Projects/Domain/PushService/Example/Resources/LaunchScreen.storyboard
new file mode 100644
index 0000000..8f1bfc8
--- /dev/null
+++ b/Projects/Domain/PushService/Example/Resources/LaunchScreen.storyboard
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Projects/Domain/PushService/Example/Sources/AppDelegate.swift b/Projects/Domain/PushService/Example/Sources/AppDelegate.swift
new file mode 100644
index 0000000..0d538be
--- /dev/null
+++ b/Projects/Domain/PushService/Example/Sources/AppDelegate.swift
@@ -0,0 +1,11 @@
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
+ ) -> Bool {
+ return true
+ }
+}
diff --git a/Projects/Domain/PushService/Interface/Model/PushNotificationContent.swift b/Projects/Domain/PushService/Interface/Model/PushNotificationContent.swift
new file mode 100644
index 0000000..dea9329
--- /dev/null
+++ b/Projects/Domain/PushService/Interface/Model/PushNotificationContent.swift
@@ -0,0 +1,13 @@
+//
+// PushNotificationContent.swift
+// PushService
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import Foundation
+
+public enum PushNotificationContent: Decodable {
+ case test
+}
diff --git a/Projects/Feature/AppFeature/Interface/AppFeatureInterface.swift b/Projects/Domain/PushService/Interface/PushServiceInterface.swift
similarity index 51%
rename from Projects/Feature/AppFeature/Interface/AppFeatureInterface.swift
rename to Projects/Domain/PushService/Interface/PushServiceInterface.swift
index d8776f5..95ff123 100644
--- a/Projects/Feature/AppFeature/Interface/AppFeatureInterface.swift
+++ b/Projects/Domain/PushService/Interface/PushServiceInterface.swift
@@ -1,5 +1,5 @@
import Foundation
-public struct AppFeatureInterface {
+public struct PushServiceInterface {
public init() {}
}
diff --git a/Projects/Domain/PushService/Project.swift b/Projects/Domain/PushService/Project.swift
new file mode 100644
index 0000000..1e8d980
--- /dev/null
+++ b/Projects/Domain/PushService/Project.swift
@@ -0,0 +1,23 @@
+import ProjectDescription
+import ProjectDescriptionHelpers
+
+@_spi(Domain)
+@_spi(Core)
+import DependencyPlugin
+
+let project: Project = .makeTMABasedProject(
+ module: Domain.PushService,
+ scripts: [],
+ targets: [
+ .sources,
+ .interface,
+ .tests,
+ .testing,
+ .example
+ ],
+ dependencies: [
+ .interface: [
+ .dependency(rootModule: Core.self)
+ ]
+ ]
+)
diff --git a/Projects/Feature/AppFeature/Preview/Resources/dummy.txt b/Projects/Domain/PushService/Resources/dummy.txt
similarity index 100%
rename from Projects/Feature/AppFeature/Preview/Resources/dummy.txt
rename to Projects/Domain/PushService/Resources/dummy.txt
diff --git a/Projects/Feature/AppFeature/Preview/Sources/AppFeature.swift b/Projects/Domain/PushService/Sources/PushService.swift
similarity index 58%
rename from Projects/Feature/AppFeature/Preview/Sources/AppFeature.swift
rename to Projects/Domain/PushService/Sources/PushService.swift
index 6d6f60a..b9bd75e 100644
--- a/Projects/Feature/AppFeature/Preview/Sources/AppFeature.swift
+++ b/Projects/Domain/PushService/Sources/PushService.swift
@@ -1,5 +1,5 @@
import Foundation
-public struct AppFeature {
+public struct PushService {
public init() {}
}
diff --git a/Projects/Feature/AppFeature/Testing/AppFeatureTesting.swift b/Projects/Domain/PushService/Testing/PushServiceTesting.swift
similarity index 53%
rename from Projects/Feature/AppFeature/Testing/AppFeatureTesting.swift
rename to Projects/Domain/PushService/Testing/PushServiceTesting.swift
index 82a04dd..988726a 100644
--- a/Projects/Feature/AppFeature/Testing/AppFeatureTesting.swift
+++ b/Projects/Domain/PushService/Testing/PushServiceTesting.swift
@@ -1,5 +1,5 @@
import Foundation
-public struct AppFeatureTesting {
+public struct PushServiceTesting {
public init() {}
}
diff --git a/Projects/Feature/AppFeature/Tests/AppFeatureTests.swift b/Projects/Domain/PushService/Tests/PushServiceTests.swift
similarity index 54%
rename from Projects/Feature/AppFeature/Tests/AppFeatureTests.swift
rename to Projects/Domain/PushService/Tests/PushServiceTests.swift
index 8c7ac98..b127c16 100644
--- a/Projects/Feature/AppFeature/Tests/AppFeatureTests.swift
+++ b/Projects/Domain/PushService/Tests/PushServiceTests.swift
@@ -1,5 +1,5 @@
import Foundation
-public struct AppFeatureTests {
+public struct PushServiceTests {
public init() {}
}
diff --git a/Projects/Feature/Feature/Project.swift b/Projects/Feature/Feature/Project.swift
index 8267176..9e8761e 100644
--- a/Projects/Feature/Feature/Project.swift
+++ b/Projects/Feature/Feature/Project.swift
@@ -7,5 +7,5 @@ import DependencyPlugin
let project: Project = .makeRootProject(
rootModule: Feature.self,
scripts: [],
- product: .framework
+ product: .staticLibrary
)
diff --git a/Projects/Feature/Feature/Sources/AppCore.swift b/Projects/Feature/Feature/Sources/AppCore.swift
new file mode 100644
index 0000000..7b5182b
--- /dev/null
+++ b/Projects/Feature/Feature/Sources/AppCore.swift
@@ -0,0 +1,93 @@
+//
+// AppCore.swift
+// AppServiceInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import SwiftUI
+
+import HomeFeature
+import HomeFeatureInterface
+import OnboardingFeature
+import OnboardingFeatureInterface
+import PushServiceInterface
+
+import ComposableArchitecture
+
+@Reducer
+public struct AppCore {
+ @ObservableState
+ public struct State: Equatable {
+ public var appDelegate: AppDelegateCore.State = .init()
+ var home: HomeCore.State?
+ var onboarding: OnboardingCore.State?
+
+ public init() {}
+ }
+
+ public enum Action {
+ case onAppear
+ case appDelegate(AppDelegateCore.Action)
+ case didChangeScenePhase(ScenePhase)
+ case home(HomeCore.Action)
+ case onboarding(OnboardingCore.Action)
+ }
+
+ public init() {}
+
+ public var body: some ReducerOf {
+ Scope(state: \.appDelegate, action: \.appDelegate) {
+ AppDelegateCore()
+ }
+ Reduce(self.core)
+ .ifLet(\.home, action: \.home) {
+ HomeCore()
+ }
+ .ifLet(\.onboarding, action: \.onboarding) {
+ OnboardingCore()
+ }
+ }
+
+ private func core(_ state: inout State, _ action: Action) -> EffectOf {
+ switch action {
+ case .onAppear:
+ let isLoggedIn = false
+ if isLoggedIn { // 로그인 판단
+ state.home = HomeCore.State()
+ } else {
+ state.onboarding = OnboardingCore.State()
+ }
+ return .none
+
+ case let .appDelegate(.userNotifications(.didReceiveResponse(response, completionHandler))):
+ let userInfo = response.notification.request.content.userInfo
+ guard let data = try? JSONSerialization.data(withJSONObject: userInfo),
+ let pushNotiContent = try? JSONDecoder().decode(PushNotificationContent.self, from: data)
+ else {
+ completionHandler()
+ return .none
+ }
+ return .run { send in
+ switch pushNotiContent {
+ case .test:
+ break
+ }
+ completionHandler()
+ }
+
+ case .appDelegate:
+ return .none
+
+ case .didChangeScenePhase:
+ return .none
+
+ case .home:
+ return .none
+
+ case .onboarding:
+ return .none
+ }
+ }
+}
diff --git a/Projects/Feature/Feature/Sources/AppDelegateCore.swift b/Projects/Feature/Feature/Sources/AppDelegateCore.swift
new file mode 100644
index 0000000..c3801ca
--- /dev/null
+++ b/Projects/Feature/Feature/Sources/AppDelegateCore.swift
@@ -0,0 +1,89 @@
+//
+// AppDelegateCore.swift
+// AppServiceInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import UIKit
+import Foundation
+
+import UserNotificationClientInterface
+import KeychainClientInterface
+
+import ComposableArchitecture
+import FirebaseCore
+import FirebaseMessaging
+
+@Reducer
+public struct AppDelegateCore {
+ @ObservableState
+ public struct State: Equatable {
+ public init() {}
+ }
+
+ public enum Action {
+ case didFinishLaunching
+ case didRegisterForRemoteNotifications(Result)
+ case userNotifications(UserNotificationClient.DelegateEvent)
+ }
+
+ @Dependency(\.keychainClient) var keychainClient
+ @Dependency(\.userNotificationClient) var userNotificationClient
+
+ public init() {}
+
+ public var body: some ReducerOf {
+ Reduce(self.core)
+ }
+
+ private func core(_ state: inout State, _ action: Action) -> EffectOf {
+ switch action {
+ case .didFinishLaunching:
+ UIApplication.shared.applicationIconBadgeNumber = 0
+ FirebaseApp.configure()
+ keychainClient.checkSubsequentRun()
+ let userNotificationEventStream = userNotificationClient.delegate()
+
+ return .run { send in
+ await withThrowingTaskGroup(of: Void.self) { group in
+ group.addTask {
+ for await event in userNotificationEventStream {
+ await send(.userNotifications(event))
+ }
+ }
+
+ group.addTask {
+ let settings = await userNotificationClient.getNotificationSettings()
+ switch settings.authorizationStatus {
+ case .authorized:
+ guard try await userNotificationClient.requestAuthorization([.badge, .alert, .sound])
+ else { return }
+ case .notDetermined, .provisional:
+ guard try await userNotificationClient.requestAuthorization(.provisional)
+ else { return }
+ default:
+ return
+ }
+ await UIApplication.shared.registerForRemoteNotifications()
+ }
+ }
+ }
+
+ case let .didRegisterForRemoteNotifications(.success(tokenData)):
+ Messaging.messaging().apnsToken = tokenData
+ return .none
+
+ case .didRegisterForRemoteNotifications(.failure):
+ return .none
+
+ case let .userNotifications(.willPresentNotification(_, completionHandler)):
+ completionHandler([.banner, .list, .sound])
+ return .none
+
+ case .userNotifications:
+ return .none
+ }
+ }
+}
diff --git a/Projects/Feature/Feature/Sources/AppView.swift b/Projects/Feature/Feature/Sources/AppView.swift
new file mode 100644
index 0000000..b0e5e2d
--- /dev/null
+++ b/Projects/Feature/Feature/Sources/AppView.swift
@@ -0,0 +1,39 @@
+//
+// AppServcieView.swift
+// AppServiceInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import SwiftUI
+
+import HomeFeature
+import HomeFeatureInterface
+import OnboardingFeature
+import OnboardingFeatureInterface
+
+import ComposableArchitecture
+
+public struct AppView: View {
+ let store: StoreOf
+
+ public init(store: StoreOf) {
+ self.store = store
+ }
+
+ public var body: some View {
+ Group {
+ if let homeStore = store.scope(state: \.home, action: \.home) {
+ HomeView(store: homeStore)
+ } else if let onboardingStore = store.scope(state: \.onboarding, action: \.onboarding) {
+ OnboardingView(store: onboardingStore)
+ } else {
+ Color.red
+ }
+ }
+ .onAppear {
+ store.send(.onAppear)
+ }
+ }
+}
diff --git a/Projects/Feature/Feature/Sources/Exports.swift b/Projects/Feature/Feature/Sources/Exports.swift
deleted file mode 100644
index 5aa4893..0000000
--- a/Projects/Feature/Feature/Sources/Exports.swift
+++ /dev/null
@@ -1,10 +0,0 @@
-//
-// Exports.swift
-// Shared
-//
-// Created by devMinseok on 7/20/24.
-// Copyright © 2024 PomoNyang. All rights reserved.
-//
-
-@_exported import AppFeature
-@_exported import AppFeatureInterface
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..f1cb98f
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,14 @@
+{
+ "images" : [
+ {
+ "filename" : "ICON_DEMO.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/contents.json b/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Example/Resources/Assets.xcassets/contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Bold.otf b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Bold.otf
new file mode 100644
index 0000000..a52ef39
Binary files /dev/null and b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Bold.otf differ
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Medium.otf b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Medium.otf
new file mode 100644
index 0000000..a2dc009
Binary files /dev/null and b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Medium.otf differ
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Regular.otf b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Regular.otf
new file mode 100644
index 0000000..c940185
Binary files /dev/null and b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-Regular.otf differ
diff --git a/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-SemiBold.otf b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-SemiBold.otf
new file mode 100644
index 0000000..c375b54
Binary files /dev/null and b/Projects/Feature/HomeFeature/Example/Resources/Font/Pretendard-SemiBold.otf differ
diff --git a/Projects/Feature/HomeFeature/Example/Resources/LaunchScreen.storyboard b/Projects/Feature/HomeFeature/Example/Resources/LaunchScreen.storyboard
new file mode 100644
index 0000000..be85df4
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Example/Resources/LaunchScreen.storyboard
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Projects/Feature/HomeFeature/Example/Sources/AppDelegate.swift b/Projects/Feature/HomeFeature/Example/Sources/AppDelegate.swift
new file mode 100644
index 0000000..0d538be
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Example/Sources/AppDelegate.swift
@@ -0,0 +1,11 @@
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
+ ) -> Bool {
+ return true
+ }
+}
diff --git a/Projects/Feature/HomeFeature/Interface/HomeCoreInterface.swift b/Projects/Feature/HomeFeature/Interface/HomeCoreInterface.swift
new file mode 100644
index 0000000..87e4b48
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Interface/HomeCoreInterface.swift
@@ -0,0 +1,33 @@
+//
+// HomeCoreInterface.swift
+// HomeFeature
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import Foundation
+
+import ComposableArchitecture
+
+@Reducer
+public struct HomeCore {
+ private let reducer: Reduce
+
+ public init(reducer: Reduce) {
+ self.reducer = reducer
+ }
+
+ @ObservableState
+ public struct State: Equatable {
+ public init() {}
+ }
+
+ public enum Action {
+ case onAppear
+ }
+
+ public var body: some ReducerOf {
+ reducer
+ }
+}
diff --git a/Projects/Feature/HomeFeature/Interface/HomeView.swift b/Projects/Feature/HomeFeature/Interface/HomeView.swift
new file mode 100644
index 0000000..cc78b40
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Interface/HomeView.swift
@@ -0,0 +1,28 @@
+//
+// HomeView.swift
+// HomeFeatureInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import SwiftUI
+
+import ComposableArchitecture
+
+public struct HomeView: View {
+ let store: StoreOf
+
+ public init(store: StoreOf) {
+ self.store = store
+ }
+
+ public var body: some View {
+ VStack {
+ Text("Home")
+ .foregroundStyle(Color.black)
+ }
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
+ .background(Color.white)
+ }
+}
diff --git a/Projects/Feature/AppFeature/Project.swift b/Projects/Feature/HomeFeature/Project.swift
similarity index 84%
rename from Projects/Feature/AppFeature/Project.swift
rename to Projects/Feature/HomeFeature/Project.swift
index 52b2aa5..6f25a9e 100644
--- a/Projects/Feature/AppFeature/Project.swift
+++ b/Projects/Feature/HomeFeature/Project.swift
@@ -1,18 +1,19 @@
import ProjectDescription
import ProjectDescriptionHelpers
-@_spi(Domain)
@_spi(Feature)
+@_spi(Domain)
import DependencyPlugin
let project: Project = .makeTMABasedProject(
- module: Feature.AppFeature,
+ module: Feature.HomeFeature,
scripts: [],
targets: [
.sources,
.interface,
.tests,
- .testing
+ .testing,
+ .example
],
dependencies: [
.interface: [
diff --git a/Projects/Feature/AppFeature/Resources/dummy.txt b/Projects/Feature/HomeFeature/Resources/dummy.txt
similarity index 100%
rename from Projects/Feature/AppFeature/Resources/dummy.txt
rename to Projects/Feature/HomeFeature/Resources/dummy.txt
diff --git a/Projects/Feature/HomeFeature/Sources/HomeCore.swift b/Projects/Feature/HomeFeature/Sources/HomeCore.swift
new file mode 100644
index 0000000..2720af5
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Sources/HomeCore.swift
@@ -0,0 +1,23 @@
+//
+// HomeCore.swift
+// HomeFeature
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import HomeFeatureInterface
+
+import ComposableArchitecture
+
+extension HomeCore {
+ public init() {
+ let reducer = Reduce { state, action in
+ switch action {
+ case .onAppear:
+ return .none
+ }
+ }
+ self.init(reducer: reducer)
+ }
+}
diff --git a/Projects/Feature/HomeFeature/Testing/HomeFeatureTesting.swift b/Projects/Feature/HomeFeature/Testing/HomeFeatureTesting.swift
new file mode 100644
index 0000000..ca81c97
--- /dev/null
+++ b/Projects/Feature/HomeFeature/Testing/HomeFeatureTesting.swift
@@ -0,0 +1,5 @@
+import Foundation
+
+public struct HomeFeatureTesting {
+ public init() {}
+}
diff --git a/Projects/Feature/AppFeature/Sources/AppFeature.swift b/Projects/Feature/HomeFeature/Tests/HomeFeatureTests.swift
similarity index 54%
rename from Projects/Feature/AppFeature/Sources/AppFeature.swift
rename to Projects/Feature/HomeFeature/Tests/HomeFeatureTests.swift
index 6d6f60a..c050739 100644
--- a/Projects/Feature/AppFeature/Sources/AppFeature.swift
+++ b/Projects/Feature/HomeFeature/Tests/HomeFeatureTests.swift
@@ -1,5 +1,5 @@
import Foundation
-public struct AppFeature {
+public struct HomeFeatureTests {
public init() {}
}
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..f1cb98f
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,14 @@
+{
+ "images" : [
+ {
+ "filename" : "ICON_DEMO.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/contents.json b/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Example/Resources/Assets.xcassets/contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Bold.otf b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Bold.otf
new file mode 100644
index 0000000..a52ef39
Binary files /dev/null and b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Bold.otf differ
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Medium.otf b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Medium.otf
new file mode 100644
index 0000000..a2dc009
Binary files /dev/null and b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Medium.otf differ
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Regular.otf b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Regular.otf
new file mode 100644
index 0000000..c940185
Binary files /dev/null and b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-Regular.otf differ
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-SemiBold.otf b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-SemiBold.otf
new file mode 100644
index 0000000..c375b54
Binary files /dev/null and b/Projects/Feature/OnboardingFeature/Example/Resources/Font/Pretendard-SemiBold.otf differ
diff --git a/Projects/Feature/OnboardingFeature/Example/Resources/LaunchScreen.storyboard b/Projects/Feature/OnboardingFeature/Example/Resources/LaunchScreen.storyboard
new file mode 100644
index 0000000..a58716d
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Example/Resources/LaunchScreen.storyboard
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Projects/Feature/OnboardingFeature/Example/Sources/AppDelegate.swift b/Projects/Feature/OnboardingFeature/Example/Sources/AppDelegate.swift
new file mode 100644
index 0000000..0d538be
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Example/Sources/AppDelegate.swift
@@ -0,0 +1,11 @@
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
+ ) -> Bool {
+ return true
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Interface/OnboardingCoreInterface.swift b/Projects/Feature/OnboardingFeature/Interface/OnboardingCoreInterface.swift
new file mode 100644
index 0000000..72fd03e
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Interface/OnboardingCoreInterface.swift
@@ -0,0 +1,33 @@
+//
+// OnboardingCoreInterface.swift
+// OnboardingFeatureInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import Foundation
+
+import ComposableArchitecture
+
+@Reducer
+public struct OnboardingCore {
+ private let reducer: Reduce
+
+ public init(reducer: Reduce) {
+ self.reducer = reducer
+ }
+
+ @ObservableState
+ public struct State: Equatable {
+ public init() {}
+ }
+
+ public enum Action {
+ case onAppear
+ }
+
+ public var body: some ReducerOf {
+ reducer
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Interface/OnboardingView.swift b/Projects/Feature/OnboardingFeature/Interface/OnboardingView.swift
new file mode 100644
index 0000000..6a32071
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Interface/OnboardingView.swift
@@ -0,0 +1,28 @@
+//
+// OnboardingView.swift
+// OnboardingFeatureInterface
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import SwiftUI
+
+import ComposableArchitecture
+
+public struct OnboardingView: View {
+ let store: StoreOf
+
+ public init(store: StoreOf) {
+ self.store = store
+ }
+
+ public var body: some View {
+ VStack {
+ Text("Onboarding")
+ .foregroundStyle(Color.black)
+ }
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
+ .background(Color.white)
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Project.swift b/Projects/Feature/OnboardingFeature/Project.swift
new file mode 100644
index 0000000..8ab4340
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Project.swift
@@ -0,0 +1,23 @@
+import ProjectDescription
+import ProjectDescriptionHelpers
+
+@_spi(Feature)
+@_spi(Domain)
+import DependencyPlugin
+
+let project: Project = .makeTMABasedProject(
+ module: Feature.OnboardingFeature,
+ scripts: [],
+ targets: [
+ .sources,
+ .interface,
+ .tests,
+ .testing,
+ .example
+ ],
+ dependencies: [
+ .interface: [
+ .dependency(rootModule: Domain.self)
+ ]
+ ]
+)
diff --git a/Projects/Shared/DesignSystem/Resources/dummy.txt b/Projects/Feature/OnboardingFeature/Resources/dummy.txt
similarity index 100%
rename from Projects/Shared/DesignSystem/Resources/dummy.txt
rename to Projects/Feature/OnboardingFeature/Resources/dummy.txt
diff --git a/Projects/Feature/OnboardingFeature/Sources/OnboardingCore.swift b/Projects/Feature/OnboardingFeature/Sources/OnboardingCore.swift
new file mode 100644
index 0000000..50a3125
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Sources/OnboardingCore.swift
@@ -0,0 +1,23 @@
+//
+// OnboardingCore.swift
+// OnboardingFeature
+//
+// Created by devMinseok on 7/22/24.
+// Copyright © 2024 PomoNyang. All rights reserved.
+//
+
+import OnboardingFeatureInterface
+
+import ComposableArchitecture
+
+extension OnboardingCore {
+ public init() {
+ let reducer = Reduce { state, action in
+ switch action {
+ case .onAppear:
+ return .none
+ }
+ }
+ self.init(reducer: reducer)
+ }
+}
diff --git a/Projects/Feature/OnboardingFeature/Testing/OnboardingFeatureTesting.swift b/Projects/Feature/OnboardingFeature/Testing/OnboardingFeatureTesting.swift
new file mode 100644
index 0000000..b799b32
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Testing/OnboardingFeatureTesting.swift
@@ -0,0 +1,5 @@
+import Foundation
+
+public struct OnboardingFeatureTesting {
+ public init() {}
+}
diff --git a/Projects/Feature/OnboardingFeature/Tests/OnboardingFeatureTests.swift b/Projects/Feature/OnboardingFeature/Tests/OnboardingFeatureTests.swift
new file mode 100644
index 0000000..f80e247
--- /dev/null
+++ b/Projects/Feature/OnboardingFeature/Tests/OnboardingFeatureTests.swift
@@ -0,0 +1,5 @@
+import Foundation
+
+public struct OnboardingFeatureTests {
+ public init() {}
+}
diff --git a/Projects/Shared/DesignSystem/Project.swift b/Projects/Shared/DesignSystem/Project.swift
index 21cd84d..aa62f73 100644
--- a/Projects/Shared/DesignSystem/Project.swift
+++ b/Projects/Shared/DesignSystem/Project.swift
@@ -6,6 +6,9 @@ import DependencyPlugin
let project: Project = .makeTMABasedProject(
module: Shared.DesignSystem,
+ options: .options(
+ disableSynthesizedResourceAccessors: false
+ ),
includeResource: true,
scripts: [],
targets: [
@@ -14,5 +17,10 @@ let project: Project = .makeTMABasedProject(
.tests,
.testing
],
- dependencies: [:]
+ dependencies: [:],
+ resourceSynthesizers: [
+ .fonts(), // for font
+ .assets(), // for .xcassets,
+ .files(extensions: ["mp4", "gif"])
+ ]
)
diff --git a/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Bold.otf b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Bold.otf
new file mode 100644
index 0000000..a52ef39
Binary files /dev/null and b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Bold.otf differ
diff --git a/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Medium.otf b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Medium.otf
new file mode 100644
index 0000000..a2dc009
Binary files /dev/null and b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Medium.otf differ
diff --git a/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Regular.otf b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Regular.otf
new file mode 100644
index 0000000..c940185
Binary files /dev/null and b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-Regular.otf differ
diff --git a/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-SemiBold.otf b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-SemiBold.otf
new file mode 100644
index 0000000..c375b54
Binary files /dev/null and b/Projects/Shared/DesignSystem/Resources/Font/Pretendard/Pretendard-SemiBold.otf differ
diff --git a/Projects/Shared/Shared/Project.swift b/Projects/Shared/Shared/Project.swift
index 0f00bcd..fbc5383 100644
--- a/Projects/Shared/Shared/Project.swift
+++ b/Projects/Shared/Shared/Project.swift
@@ -7,5 +7,5 @@ import DependencyPlugin
let project: Project = .makeRootProject(
rootModule: Shared.self,
scripts: [],
- product: .framework
+ product: .staticLibrary
)
diff --git a/Projects/Shared/Shared/Sources/Exports.swift b/Projects/Shared/Shared/Sources/Exports.swift
index 8c5e2aa..49b3a1a 100644
--- a/Projects/Shared/Shared/Sources/Exports.swift
+++ b/Projects/Shared/Shared/Sources/Exports.swift
@@ -11,3 +11,7 @@
@_exported import DesignSystemInterface
@_exported import Utils
@_exported import UtilsInterface
+
+@_exported import ThirdParty_SPM
+@_exported import ThirdParty_Firebase
+@_exported import ThirdParty_Realm
diff --git a/Tuist/ProjectDescriptionHelpers/Templates/Project+Extension.swift b/Tuist/ProjectDescriptionHelpers/Templates/Project+Extension.swift
index 5118278..b7047bb 100644
--- a/Tuist/ProjectDescriptionHelpers/Templates/Project+Extension.swift
+++ b/Tuist/ProjectDescriptionHelpers/Templates/Project+Extension.swift
@@ -32,9 +32,9 @@ extension Project {
switch targetType {
case .sources:
let product: Product = if includeResource {
- currentConfig == .dev ? .framework : .staticFramework
+ .staticFramework // currentConfig == .dev ? .framework : .staticFramework
} else {
- currentConfig == .dev ? .framework : .staticLibrary
+ .staticLibrary // currentConfig == .dev ? .framework : .staticLibrary
}
let resources: ResourceFileElements? = includeResource ? ["Resources/**"] : nil
let interfaceDependency: [TargetDependency] = targets.contains(.interface) ? [.target(name: "\(name)Interface")] : []
@@ -51,7 +51,7 @@ extension Project {
projectTargets.append(target)
case .interface:
- let product: Product = currentConfig == .dev ? .framework : .staticLibrary
+ let product: Product = .staticLibrary //currentConfig == .dev ? .framework : .staticLibrary
let target: Target = .target(
name: targetName,
product: product,
@@ -79,11 +79,12 @@ extension Project {
projectTargets.append(target)
case .testing:
+ let product: Product = .staticFramework // currentConfig == .dev ? .framework : .staticFramework
let interfaceDependency: [TargetDependency] = targets.contains(.interface) ? [.target(name: "\(name)Interface")] : []
let dependencies: [TargetDependency] = (interfaceDependency + currentDependencies).compactMap { $0 }
let target: Target = .target(
name: targetName,
- product: .framework,
+ product: product,
infoPlist: infoPlist,
sources: ["Testing/**/*.swift"],
resources: nil,