From ae99009ce772870f2bab707e9d8d01a9c3f5e4c9 Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:33:48 +0900 Subject: [PATCH 01/10] =?UTF-8?q?refactor:=20=EC=86=8C=EC=8A=A4=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B3=84=EC=B8=B5=20=EC=9E=AC=EB=B0=B0?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Root => DevLogApp/Sources/App/Scene}/RootView.swift | 0 .../Sources/App/Scene}/TodoEditorWindowView.swift | 0 .../Sources/{Home => Coordinator}/Home/HomeViewCoordinator.swift | 0 .../Sources/{ => Coordinator}/Home/TodoWindowCoordinator.swift | 0 .../Sources/{ => Coordinator}/Main/MainViewCoordinator.swift | 0 .../{ => Coordinator}/Profile/ProfileViewCoordinator.swift | 0 .../PushNotification/PushNotificationListViewCoordinator.swift | 0 .../Sources/{ => Coordinator}/Today/TodayViewCoordinator.swift | 0 .../Sources/{Common => Routing}/NavigationRouter.swift | 0 .../Sources/{Home => ViewModel}/Home/HomeViewModel.swift | 0 .../Sources/{ => ViewModel}/Home/TodoDetailViewModel.swift | 0 .../Sources/{ => ViewModel}/Home/TodoEditorViewModel.swift | 0 .../Sources/{ => ViewModel}/Home/TodoListViewModel.swift | 0 .../Sources/{ => ViewModel}/Home/TodoManageViewModel.swift | 0 .../Sources/{ => ViewModel}/Login/LoginViewModel.swift | 0 .../Sources/{ => ViewModel}/Main/MainViewModel.swift | 0 .../Sources/{ => ViewModel}/Profile/ProfileViewModel.swift | 0 .../PushNotification/PushNotificationListViewModel.swift | 0 .../Sources/{ => ViewModel}/Root/RootViewModel.swift | 0 .../Sources/{ => ViewModel}/Search/SearchViewModel.swift | 0 .../Sources/{ => ViewModel}/Setting/AccountViewModel.swift | 0 .../Setting/PushNotificationSettingsViewModel.swift | 0 .../Sources/{ => ViewModel}/Setting/SettingViewModel.swift | 0 .../Sources/{ => ViewModel}/Today/TodayViewModel.swift | 0 .../Sources/{Home => Window}/TodoEditorWindowEvent.swift | 0 .../Sources/{Home => Window}/TodoEditorWindowValue.swift | 0 .../Sources/Common/Component/CacheableImage.swift | 0 .../Sources/Common/Component/CheckBox.swift | 0 .../Sources/Common/Component/LoadingView.swift | 0 .../Sources/Common/Component/LoginButton.swift | 0 .../Sources/Common/Component/RelativeTimeText.swift | 0 .../Sources/Common/Component/Tags.swift | 0 .../Sources/Common/Component/Toast.swift | 0 .../Sources/Common/Component/TodoItemRow.swift | 0 .../Sources/Common/Component/ToolbarButtons.swift | 0 .../Sources/Common/Component/UIKitTextEditor.swift | 0 .../Sources/Common/Component/WebItemRow.swift | 0 .../Sources/Common/NavigationBarConfigurator.swift | 0 .../Sources/Common/TodoDetailContentView.swift | 0 .../Sources/Common/TodoInfoSheetView.swift | 0 .../Sources/Common/TodoMarkdownContentView.swift | 0 .../{DevLogPresentation => DevLogUI}/Sources/Common/WebView.swift | 0 .../Sources/Extension/EnvironmentValues+.swift | 0 .../Sources/Extension/View+.swift | 0 .../Sources/Home/Home/HomeView.swift | 0 .../Sources/Home/TodoDetailView.swift | 0 .../Sources/Home/TodoEditorView.swift | 0 .../Sources/Home/TodoListView.swift | 0 .../Sources/Home/TodoManageView.swift | 0 .../Sources/Login/LoginView.swift | 0 .../{DevLogPresentation => DevLogUI}/Sources/Main/MainView.swift | 0 .../Sources/Profile/HeatmapView.swift | 0 .../Sources/Profile/ProfileView.swift | 0 .../Sources/PushNotification/PushNotificationListView.swift | 0 .../Sources/Search/SearchView.swift | 0 .../Sources/Setting/AccountView.swift | 0 .../Sources/Setting/PushNotificationSettingsView.swift | 0 .../Sources/Setting/SettingView.swift | 0 .../Sources/Setting/ThemeView.swift | 0 .../Sources/Today/TodayView.swift | 0 60 files changed, 0 insertions(+), 0 deletions(-) rename Application/{DevLogPresentation/Sources/Root => DevLogApp/Sources/App/Scene}/RootView.swift (100%) rename Application/{DevLogPresentation/Sources/Home => DevLogApp/Sources/App/Scene}/TodoEditorWindowView.swift (100%) rename Application/DevLogPresentation/Sources/{Home => Coordinator}/Home/HomeViewCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{ => Coordinator}/Home/TodoWindowCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{ => Coordinator}/Main/MainViewCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{ => Coordinator}/Profile/ProfileViewCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{ => Coordinator}/PushNotification/PushNotificationListViewCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{ => Coordinator}/Today/TodayViewCoordinator.swift (100%) rename Application/DevLogPresentation/Sources/{Common => Routing}/NavigationRouter.swift (100%) rename Application/DevLogPresentation/Sources/{Home => ViewModel}/Home/HomeViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Home/TodoDetailViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Home/TodoEditorViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Home/TodoListViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Home/TodoManageViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Login/LoginViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Main/MainViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Profile/ProfileViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/PushNotification/PushNotificationListViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Root/RootViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Search/SearchViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Setting/AccountViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Setting/PushNotificationSettingsViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Setting/SettingViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{ => ViewModel}/Today/TodayViewModel.swift (100%) rename Application/DevLogPresentation/Sources/{Home => Window}/TodoEditorWindowEvent.swift (100%) rename Application/DevLogPresentation/Sources/{Home => Window}/TodoEditorWindowValue.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/CacheableImage.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/CheckBox.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/LoadingView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/LoginButton.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/RelativeTimeText.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/Tags.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/Toast.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/TodoItemRow.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/ToolbarButtons.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/UIKitTextEditor.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/Component/WebItemRow.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/NavigationBarConfigurator.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/TodoDetailContentView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/TodoInfoSheetView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/TodoMarkdownContentView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Common/WebView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Extension/EnvironmentValues+.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Extension/View+.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Home/Home/HomeView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Home/TodoDetailView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Home/TodoEditorView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Home/TodoListView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Home/TodoManageView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Login/LoginView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Main/MainView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Profile/HeatmapView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Profile/ProfileView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/PushNotification/PushNotificationListView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Search/SearchView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Setting/AccountView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Setting/PushNotificationSettingsView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Setting/SettingView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Setting/ThemeView.swift (100%) rename Application/{DevLogPresentation => DevLogUI}/Sources/Today/TodayView.swift (100%) diff --git a/Application/DevLogPresentation/Sources/Root/RootView.swift b/Application/DevLogApp/Sources/App/Scene/RootView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Root/RootView.swift rename to Application/DevLogApp/Sources/App/Scene/RootView.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoEditorWindowView.swift b/Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoEditorWindowView.swift rename to Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoWindowCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoWindowCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/Main/MainViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Main/MainViewCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/Profile/ProfileViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Profile/ProfileViewCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/PushNotification/PushNotificationListViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/PushNotification/PushNotificationListViewCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/Today/TodayViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Today/TodayViewCoordinator.swift rename to Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift diff --git a/Application/DevLogPresentation/Sources/Common/NavigationRouter.swift b/Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/NavigationRouter.swift rename to Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoDetailViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoDetailViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoEditorViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoEditorViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoListViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoManageViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoManageViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Login/LoginViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Login/LoginViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Main/MainViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Main/MainViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Profile/ProfileViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Profile/ProfileViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift diff --git a/Application/DevLogPresentation/Sources/PushNotification/PushNotificationListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/PushNotification/PushNotificationListViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Root/RootViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Root/RootViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Search/SearchViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Search/SearchViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Setting/AccountViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/AccountViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Setting/PushNotificationSettingsViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/PushNotificationSettingsViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Setting/SettingViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/SettingViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Today/TodayViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Today/TodayViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoEditorWindowEvent.swift b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoEditorWindowEvent.swift rename to Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoEditorWindowValue.swift b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoEditorWindowValue.swift rename to Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/CacheableImage.swift b/Application/DevLogUI/Sources/Common/Component/CacheableImage.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/CacheableImage.swift rename to Application/DevLogUI/Sources/Common/Component/CacheableImage.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/CheckBox.swift b/Application/DevLogUI/Sources/Common/Component/CheckBox.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/CheckBox.swift rename to Application/DevLogUI/Sources/Common/Component/CheckBox.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/LoadingView.swift b/Application/DevLogUI/Sources/Common/Component/LoadingView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/LoadingView.swift rename to Application/DevLogUI/Sources/Common/Component/LoadingView.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/LoginButton.swift b/Application/DevLogUI/Sources/Common/Component/LoginButton.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/LoginButton.swift rename to Application/DevLogUI/Sources/Common/Component/LoginButton.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/RelativeTimeText.swift b/Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/RelativeTimeText.swift rename to Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/Tags.swift b/Application/DevLogUI/Sources/Common/Component/Tags.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/Tags.swift rename to Application/DevLogUI/Sources/Common/Component/Tags.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/Toast.swift b/Application/DevLogUI/Sources/Common/Component/Toast.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/Toast.swift rename to Application/DevLogUI/Sources/Common/Component/Toast.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/TodoItemRow.swift b/Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/TodoItemRow.swift rename to Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/ToolbarButtons.swift b/Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/ToolbarButtons.swift rename to Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/UIKitTextEditor.swift b/Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/UIKitTextEditor.swift rename to Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift diff --git a/Application/DevLogPresentation/Sources/Common/Component/WebItemRow.swift b/Application/DevLogUI/Sources/Common/Component/WebItemRow.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/Component/WebItemRow.swift rename to Application/DevLogUI/Sources/Common/Component/WebItemRow.swift diff --git a/Application/DevLogPresentation/Sources/Common/NavigationBarConfigurator.swift b/Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/NavigationBarConfigurator.swift rename to Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift diff --git a/Application/DevLogPresentation/Sources/Common/TodoDetailContentView.swift b/Application/DevLogUI/Sources/Common/TodoDetailContentView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/TodoDetailContentView.swift rename to Application/DevLogUI/Sources/Common/TodoDetailContentView.swift diff --git a/Application/DevLogPresentation/Sources/Common/TodoInfoSheetView.swift b/Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/TodoInfoSheetView.swift rename to Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift diff --git a/Application/DevLogPresentation/Sources/Common/TodoMarkdownContentView.swift b/Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/TodoMarkdownContentView.swift rename to Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift diff --git a/Application/DevLogPresentation/Sources/Common/WebView.swift b/Application/DevLogUI/Sources/Common/WebView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Common/WebView.swift rename to Application/DevLogUI/Sources/Common/WebView.swift diff --git a/Application/DevLogPresentation/Sources/Extension/EnvironmentValues+.swift b/Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Extension/EnvironmentValues+.swift rename to Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift diff --git a/Application/DevLogPresentation/Sources/Extension/View+.swift b/Application/DevLogUI/Sources/Extension/View+.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Extension/View+.swift rename to Application/DevLogUI/Sources/Extension/View+.swift diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeView.swift b/Application/DevLogUI/Sources/Home/Home/HomeView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/Home/HomeView.swift rename to Application/DevLogUI/Sources/Home/Home/HomeView.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoDetailView.swift b/Application/DevLogUI/Sources/Home/TodoDetailView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoDetailView.swift rename to Application/DevLogUI/Sources/Home/TodoDetailView.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoEditorView.swift b/Application/DevLogUI/Sources/Home/TodoEditorView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoEditorView.swift rename to Application/DevLogUI/Sources/Home/TodoEditorView.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoListView.swift b/Application/DevLogUI/Sources/Home/TodoListView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoListView.swift rename to Application/DevLogUI/Sources/Home/TodoListView.swift diff --git a/Application/DevLogPresentation/Sources/Home/TodoManageView.swift b/Application/DevLogUI/Sources/Home/TodoManageView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Home/TodoManageView.swift rename to Application/DevLogUI/Sources/Home/TodoManageView.swift diff --git a/Application/DevLogPresentation/Sources/Login/LoginView.swift b/Application/DevLogUI/Sources/Login/LoginView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Login/LoginView.swift rename to Application/DevLogUI/Sources/Login/LoginView.swift diff --git a/Application/DevLogPresentation/Sources/Main/MainView.swift b/Application/DevLogUI/Sources/Main/MainView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Main/MainView.swift rename to Application/DevLogUI/Sources/Main/MainView.swift diff --git a/Application/DevLogPresentation/Sources/Profile/HeatmapView.swift b/Application/DevLogUI/Sources/Profile/HeatmapView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Profile/HeatmapView.swift rename to Application/DevLogUI/Sources/Profile/HeatmapView.swift diff --git a/Application/DevLogPresentation/Sources/Profile/ProfileView.swift b/Application/DevLogUI/Sources/Profile/ProfileView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Profile/ProfileView.swift rename to Application/DevLogUI/Sources/Profile/ProfileView.swift diff --git a/Application/DevLogPresentation/Sources/PushNotification/PushNotificationListView.swift b/Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/PushNotification/PushNotificationListView.swift rename to Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift diff --git a/Application/DevLogPresentation/Sources/Search/SearchView.swift b/Application/DevLogUI/Sources/Search/SearchView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Search/SearchView.swift rename to Application/DevLogUI/Sources/Search/SearchView.swift diff --git a/Application/DevLogPresentation/Sources/Setting/AccountView.swift b/Application/DevLogUI/Sources/Setting/AccountView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/AccountView.swift rename to Application/DevLogUI/Sources/Setting/AccountView.swift diff --git a/Application/DevLogPresentation/Sources/Setting/PushNotificationSettingsView.swift b/Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/PushNotificationSettingsView.swift rename to Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift diff --git a/Application/DevLogPresentation/Sources/Setting/SettingView.swift b/Application/DevLogUI/Sources/Setting/SettingView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/SettingView.swift rename to Application/DevLogUI/Sources/Setting/SettingView.swift diff --git a/Application/DevLogPresentation/Sources/Setting/ThemeView.swift b/Application/DevLogUI/Sources/Setting/ThemeView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Setting/ThemeView.swift rename to Application/DevLogUI/Sources/Setting/ThemeView.swift diff --git a/Application/DevLogPresentation/Sources/Today/TodayView.swift b/Application/DevLogUI/Sources/Today/TodayView.swift similarity index 100% rename from Application/DevLogPresentation/Sources/Today/TodayView.swift rename to Application/DevLogUI/Sources/Today/TodayView.swift From 74c8f8c7d87a05bef5277c7b528ea9d57d8a9863 Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:34:21 +0900 Subject: [PATCH 02/10] =?UTF-8?q?chore:=20DevLogUI=20=ED=83=80=EA=B9=83=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DevLogApp.xcodeproj/project.pbxproj | 22 + Application/DevLogApp/Project.swift | 1 + .../project.pbxproj | 518 ++++++------- .../DevLogUI.xcodeproj/project.pbxproj | 708 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/DevLogUI.xcscheme | 77 ++ Application/DevLogUI/Project.swift | 13 + Application/DevLogUI/Sources/.swiftlint.yml | 1 + DevLog.xcworkspace/contents.xcworkspacedata | 3 + Workspace.swift | 1 + 10 files changed, 1062 insertions(+), 289 deletions(-) create mode 100644 Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj create mode 100644 Application/DevLogUI/DevLogUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Application/DevLogUI/DevLogUI.xcodeproj/xcshareddata/xcschemes/DevLogUI.xcscheme create mode 100644 Application/DevLogUI/Project.swift create mode 100644 Application/DevLogUI/Sources/.swiftlint.yml diff --git a/Application/DevLogApp/DevLogApp.xcodeproj/project.pbxproj b/Application/DevLogApp/DevLogApp.xcodeproj/project.pbxproj index 9ed8dab0..dca91965 100644 --- a/Application/DevLogApp/DevLogApp.xcodeproj/project.pbxproj +++ b/Application/DevLogApp/DevLogApp.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 014266F6F7BFECD66B6DFFAE /* DevLogPersistence.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2242DBABD8ABF11A23160669 /* DevLogPersistence.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 0839F65046F9E9A7CD41A531 /* DevLogUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1D82B3A3D99364567064B1 /* DevLogUI.framework */; }; 088CF111FEB9773D36BFDAFB /* LocalFirebaseRESTSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6750095BE316E855E5B6DFFB /* LocalFirebaseRESTSupport.swift */; }; 0B79D44CFEC6A20F873CF3A9 /* DevLogCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1F60100641A6FBC29ED402D /* DevLogCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1056A18C4306853A83487239 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 53D7AC935B97855AA743EFC0 /* Assets.xcassets */; }; @@ -15,6 +16,7 @@ 23B23964D44D78E8CFF0D97C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AC12B5E227050E4BAEF315D /* AppDelegate.swift */; }; 25E825500273F1F887CCC6DC /* NotificationName+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EADB630F7E3DEFAA6A8DEF4 /* NotificationName+.swift */; }; 2C2180289EEF65F3CF5C1273 /* DevLogWidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D0044D9310C29492954FD1F7 /* DevLogWidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 37996815654B34E69C60877B /* DevLogUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1D82B3A3D99364567064B1 /* DevLogUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3BFF117D0E2682ECB0044884 /* MainTab+WidgetDeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAEEC97A4EC302C6974E1A4E /* MainTab+WidgetDeepLink.swift */; }; 3CC295543F33CF6BE9560AE0 /* WidgetSessionSyncHandlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 462271192C47C593C36AC403 /* WidgetSessionSyncHandlerTests.swift */; }; 423070F73AE0E059BC417D30 /* DevLogPresentation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECA33E1403AF8BDB84D46C01 /* DevLogPresentation.framework */; }; @@ -35,7 +37,9 @@ AE8FAFB84865A9798429346B /* DevLogPersistence.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2242DBABD8ABF11A23160669 /* DevLogPersistence.framework */; }; B154A155136A179166B00EAC /* DevLogApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44AFCDB8890714D634C4536 /* DevLogApp.swift */; }; CED2148B1FA2117B58665B63 /* DevLogWidgetExtension.appex in Dependencies */ = {isa = PBXBuildFile; fileRef = D0044D9310C29492954FD1F7 /* DevLogWidgetExtension.appex */; }; + CF9A2B14D691948BA64EAF7D /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8713EA9CC7AFF3F0A584863 /* RootView.swift */; }; D892FE40671E7C165DBE4E4D /* DevLogInfra.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 28ECC31B0B7F9C0A9BB4F55C /* DevLogInfra.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + DAA07C6782ECCD9D9047D56D /* TodoEditorWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C4CC786C01FCD38075E60D0 /* TodoEditorWindowView.swift */; }; DF971A154668D99F2A646957 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 026FE38633FEFB0DD0575244 /* GoogleService-Info.plist */; }; E312AB98EB0B33141E499A04 /* DeleteWebPageIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B937350A0682E6F1CD20536 /* DeleteWebPageIntegrationTests.swift */; }; EDE9714BCCC50B8950F0E911 /* DevLogPresentation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = ECA33E1403AF8BDB84D46C01 /* DevLogPresentation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -77,6 +81,7 @@ D892FE40671E7C165DBE4E4D /* DevLogInfra.framework in Embed Frameworks */, 014266F6F7BFECD66B6DFFAE /* DevLogPersistence.framework in Embed Frameworks */, EDE9714BCCC50B8950F0E911 /* DevLogPresentation.framework in Embed Frameworks */, + 37996815654B34E69C60877B /* DevLogUI.framework in Embed Frameworks */, F2F380C38E8953DB78F85FC2 /* DevLogWidgetCore.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -111,11 +116,13 @@ 2242DBABD8ABF11A23160669 /* DevLogPersistence.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogPersistence.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28ECC31B0B7F9C0A9BB4F55C /* DevLogInfra.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogInfra.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2B937350A0682E6F1CD20536 /* DeleteWebPageIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteWebPageIntegrationTests.swift; sourceTree = ""; }; + 2C4CC786C01FCD38075E60D0 /* TodoEditorWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowView.swift; sourceTree = ""; }; 346173767E6ED68E9DFDA51C /* FCMTokenSyncHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FCMTokenSyncHandler.swift; sourceTree = ""; }; 3494F50D6E7BC9510DE43F65 /* DevLogDomain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogDomain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3AC12B5E227050E4BAEF315D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 462271192C47C593C36AC403 /* WidgetSessionSyncHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetSessionSyncHandlerTests.swift; sourceTree = ""; }; 4635BA36DE82C73A105E7157 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; + 4B1D82B3A3D99364567064B1 /* DevLogUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 534E5D11EAA2E34D71F066DB /* PushNotificationRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationRoute.swift; sourceTree = ""; }; 53D7AC935B97855AA743EFC0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 544C918C2E050DFD80C83157 /* DevLogData.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogData.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -135,6 +142,7 @@ C44AFCDB8890714D634C4536 /* DevLogApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevLogApp.swift; sourceTree = ""; }; CAEEC97A4EC302C6974E1A4E /* MainTab+WidgetDeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainTab+WidgetDeepLink.swift"; sourceTree = ""; }; D0044D9310C29492954FD1F7 /* DevLogWidgetExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = DevLogWidgetExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + D8713EA9CC7AFF3F0A584863 /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; DCC05042BEB7C047BE4DB7E9 /* DevLogWidgetCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogWidgetCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; ECA33E1403AF8BDB84D46C01 /* DevLogPresentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogPresentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F078E79DE65AE8D92F556B27 /* DeletePushNotificationIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletePushNotificationIntegrationTests.swift; sourceTree = ""; }; @@ -151,6 +159,7 @@ AA5C5ACB75796DECF2BE6939 /* DevLogInfra.framework in Frameworks */, AE8FAFB84865A9798429346B /* DevLogPersistence.framework in Frameworks */, 423070F73AE0E059BC417D30 /* DevLogPresentation.framework in Frameworks */, + 0839F65046F9E9A7CD41A531 /* DevLogUI.framework in Frameworks */, A93F228DD04515584B150BCE /* DevLogWidgetCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -195,6 +204,7 @@ 28ECC31B0B7F9C0A9BB4F55C /* DevLogInfra.framework */, 2242DBABD8ABF11A23160669 /* DevLogPersistence.framework */, ECA33E1403AF8BDB84D46C01 /* DevLogPresentation.framework */, + 4B1D82B3A3D99364567064B1 /* DevLogUI.framework */, DCC05042BEB7C047BE4DB7E9 /* DevLogWidgetCore.framework */, D0044D9310C29492954FD1F7 /* DevLogWidgetExtension.appex */, ); @@ -255,6 +265,7 @@ FC39B353F5CB051101B824C1 /* Handler */, D4C5B7F48B3861AC6A9E4972 /* Notification */, 8B85D312D1D8054055A7F251 /* Routing */, + A3B5438D0D9EDCCCA37FEB88 /* Scene */, C44AFCDB8890714D634C4536 /* DevLogApp.swift */, B347482071F5035929CB7CFB /* TempView.swift */, ); @@ -289,6 +300,15 @@ name = Project; sourceTree = ""; }; + A3B5438D0D9EDCCCA37FEB88 /* Scene */ = { + isa = PBXGroup; + children = ( + D8713EA9CC7AFF3F0A584863 /* RootView.swift */, + 2C4CC786C01FCD38075E60D0 /* TodoEditorWindowView.swift */, + ); + path = Scene; + sourceTree = ""; + }; A921B89C54E83E78FB2AC773 /* Derived */ = { isa = PBXGroup; children = ( @@ -484,6 +504,8 @@ 25E825500273F1F887CCC6DC /* NotificationName+.swift in Sources */, 3BFF117D0E2682ECB0044884 /* MainTab+WidgetDeepLink.swift in Sources */, 5B1CB12023BE41B32EA64B95 /* PushNotificationRoute.swift in Sources */, + CF9A2B14D691948BA64EAF7D /* RootView.swift in Sources */, + DAA07C6782ECCD9D9047D56D /* TodoEditorWindowView.swift in Sources */, 47A3EA049D3AF319B62853ED /* TempView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Application/DevLogApp/Project.swift b/Application/DevLogApp/Project.swift index c910cb7f..671d1b0a 100644 --- a/Application/DevLogApp/Project.swift +++ b/Application/DevLogApp/Project.swift @@ -26,6 +26,7 @@ let project = Project( entitlements: .file(path: "Sources/Resource/DevLog.entitlements"), dependencies: [ .project(target: "DevLogPresentation", path: "../DevLogPresentation"), + .project(target: "DevLogUI", path: "../DevLogUI"), .project(target: "DevLogPersistence", path: "../DevLogPersistence"), .project(target: "DevLogInfra", path: "../DevLogInfra"), .project(target: "DevLogData", path: "../DevLogData"), diff --git a/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj b/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj index 96aecf5d..1117f7e9 100644 --- a/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj +++ b/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj @@ -8,93 +8,64 @@ /* Begin PBXBuildFile section */ 03CF7E696626224FFE93FFDD /* TodoReferenceItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B8F3DEEF6527F9FBCBDCD5A /* TodoReferenceItem.swift */; }; - 042A04373E0BF17A8C0E90A1 /* CheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F32D20E83ABB122630F67BD /* CheckBox.swift */; }; 053BC20B9244F93FFE9E6FA7 /* UserTodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10169ED43745C8286BAA560A /* UserTodoCategoryItem.swift */; }; - 0675430931A12884236C92E7 /* EnvironmentValues+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79043B9D995BD5D987320FE6 /* EnvironmentValues+.swift */; }; 09A7C0CA26E4129EBADE0928 /* TodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE04D300F1054596E630CF48 /* TodoCategoryItem.swift */; }; - 0B436A4BB4F4289DC5A24286 /* TodoListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34028ABF87BCFE5E95B8DF2C /* TodoListView.swift */; }; - 0BDF307FFD70E121BFE54B64 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46339787CA1BCF8EF8AACBC6 /* LoadingView.swift */; }; + 0A25E266F29F6ACD7E6154EE /* PushNotificationListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */; }; + 0C65DE6F8B9FB06F8D121D1E /* TodoViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D87C5787A3E9EAD0CC10A3D /* TodoViewModelFactory.swift */; }; + 0DA6A035B08B2E1FA91A5CCA /* TodoEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */; }; 116BB487A24975CAAD4AC940 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 56A49A4AE77CECF9ABEC6861 /* MarkdownUI */; }; - 164FF0D15F3671EC5B8175B4 /* PushNotificationListViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F52E54B2F053507AE43819 /* PushNotificationListViewCoordinator.swift */; }; 173C43896990D2469CB29D6B /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38030D2CAA016ABB3D0C396B /* Store.swift */; }; - 175898C005C97BED56549457 /* TodoEditorWindowEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 085FC0504CE36484B655FB09 /* TodoEditorWindowEvent.swift */; }; - 19A49575DE29575B3E30D42F /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C25193961AAF03B736D8BA4D /* MainViewModel.swift */; }; - 21D9F0E69F0F648AA719D3A8 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6D5BDBC6990696C3FA5B22A /* Toast.swift */; }; 26ED8F658B02153735BD8692 /* Color+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852D34A35C60375D1D9F9566 /* Color+Hex.swift */; }; + 26F47ED71B5B0701B1344A17 /* TodoEditorWindowDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C76C1FD0B57BC6E736F16F9 /* TodoEditorWindowDependencies.swift */; }; 277C3C6802370B2DB28EA92A /* WebPageItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D191AD793EE0AC702B1539 /* WebPageItem.swift */; }; - 2B0C47EBD387EEABE2A90A99 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCFF8EE1B8855BA6B7BC315F /* SearchViewModel.swift */; }; 2C9840C424A0D3C85D1001C9 /* TestSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156DCFD77B78CAEE004CDDD /* TestSupport.swift */; }; 2DB84D2FBEA0653D48DF614F /* HeatmapDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70B652BF58D45805A57ECCE0 /* HeatmapDay.swift */; }; 336D5F52E964A099E10AECFF /* TodoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB658B8B1246F4399493FE3 /* TodoListItem.swift */; }; + 34151EB8B72D12C8D373F567 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */; }; 34AFBED9DAEBD1F4E4A2DB2B /* TodoIdItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08ACC3D94A90881383764E6C /* TodoIdItem.swift */; }; - 3801176C353549D8D259FF4A /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4279F380763E7CFF063F4416 /* LoginView.swift */; }; - 3A78734125366B547D0C4261 /* TodoDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A6BFC9AC306836245B6E5CD /* TodoDetailView.swift */; }; - 3AE04B27F085D1E67BA64537 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF52D6EE30673D682147FAFE /* LoginViewModel.swift */; }; - 40B4784EB5FDD90B5A2EC81B /* TodoManageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E90A0B2F4523B8570322F54C /* TodoManageViewModel.swift */; }; + 35639553522A1CEFDCF455D7 /* TodoEditorWindowValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9206293A713E904877705C2 /* TodoEditorWindowValue.swift */; }; + 38BA6B9310BB45F46683D105 /* TodoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */; }; + 3D0FB9275F7BC7D914D8EC55 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F895EDEF78B5D98FB2A38 /* NavigationRouter.swift */; }; + 3F8512559CCF262222ACCAE2 /* RootViewDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7A86BE16165EE865C2CCB1 /* RootViewDependencies.swift */; }; 41A5C4626505C6BF0643E43B /* MainTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290DE2215D7061AC10A057D8 /* MainTab.swift */; }; - 439047A7AF80D876838710F2 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4CFA6FFA82E0EC3C25D527B /* AccountView.swift */; }; - 49631F09477091376DDA0E4D /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B457717DEF395F131159C04 /* MainView.swift */; }; 4BE7032EE7146793A5C58A94 /* ActivityKindItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CC8A2FCF1577B150A08D83 /* ActivityKindItem.swift */; }; - 4C07B469D6576A76BE71E639 /* TodoMarkdownContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFB7CB1992F8434647D2E8D1 /* TodoMarkdownContentView.swift */; }; - 57373F815DB5EF9310AC641D /* LoginButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8C462E5D83C6B639A66ED26 /* LoginButton.swift */; }; - 58A933F1C49D9977217BE84C /* ToolbarButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4AC141E5E2C9474DDBD35C /* ToolbarButtons.swift */; }; - 5931685A7811D0DCDF5508BF /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA75873FCFFC6182662694B /* ProfileView.swift */; }; + 5357B7DBEC07C590B8C70E20 /* TodayRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1E4F3FA850AB900BD0837A /* TodayRoute.swift */; }; + 5529852916250307CEDF2210 /* RootViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */; }; + 5DDA91AD574C37E26C667F24 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */; }; 5E9F72DE540DFEC1518CDDAE /* RecentTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A6CF5AAB9CCEAB35FB10A8 /* RecentTodoItem.swift */; }; - 5FD86AC94DE236C77BA69CB0 /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC9F3129E8EEBF9CAC622E7 /* ProfileViewModel.swift */; }; - 5FF8EAE9E54F8359A5391EFC /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E71459EB54EF7A0B3F294418 /* WebView.swift */; }; - 653BC11E9CB8F74FC090E3A1 /* View+.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA4D52F1343CECB8E0AC4742 /* View+.swift */; }; 65BFE2061C37BC86E811266E /* SystemTodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0CBB0EEB3B15A4BE2EF9641 /* SystemTodoCategoryItem.swift */; }; - 6DC7980E5F659AC3FB56427E /* PushNotificationListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACFDECD5652C67B68D4936D /* PushNotificationListViewModel.swift */; }; + 6E428FE9D2F09F9696B4BB52 /* SettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */; }; 6F7ED28364309E79840E1B1A /* DeleteWebPageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37323FDF36DF44C549A71A85 /* DeleteWebPageTests.swift */; }; - 70FC630DC3FC27D77EA868FD /* TodoInfoSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AED8D48F34AE2476CCF4F5A /* TodoInfoSheetView.swift */; }; - 711C3E31B02B60A4E1FB01CF /* UIKitTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87DA85DC7F13D4E5B570ED6 /* UIKitTextEditor.swift */; }; - 84866D96D8DE6F76E805050F /* RootViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53892CB6FB8F39CE967A3344 /* RootViewModel.swift */; }; - 8A76D55BB0714508C1019108 /* PushNotificationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE62ED6DF757AF15ACBB2E07 /* PushNotificationListView.swift */; }; - 8D320EC70D396E019F964166 /* HeatmapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D0037871D0A9E16D94C59 /* HeatmapView.swift */; }; - 9060015EC9ECBFF1A2511DC6 /* HomeViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7236EA0D4F011DB8D2922A65 /* HomeViewCoordinator.swift */; }; - 909B1608BDEDA51B07F27332 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80B7DE00658AC1080A3741C9 /* SearchView.swift */; }; - 90A88D80EF02129348CE35C5 /* TodoListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DDABB53271F38BCC892B6DD /* TodoListViewModel.swift */; }; + 7BAB031CACEE7F60CC0A14D9 /* TodoListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */; }; 91A04437CA63E957BDD1A060 /* TodayTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B2119664DB4FDF4A18FFE /* TodayTodoItem.swift */; }; 92DAE6E67927B3014F7FB18A /* PushNotificationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C7A0A3DE0AB6D5E4DD116B /* PushNotificationItem.swift */; }; - 959832CAA00E2B06DF0B8A83 /* TodoEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E2D739A2380C3D28C575D08 /* TodoEditorViewModel.swift */; }; - 9ADFFABEE75489A526E1ECE5 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 252057C930A70DC1D5674EE5 /* HomeView.swift */; }; - 9D69715291EB7F2AE704A722 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D136528209E2B94793441C78 /* NavigationRouter.swift */; }; - A302B2F9FDCDAFAE5A852E94 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2195BF2BC362FB4BD570C915 /* RootView.swift */; }; + 99EFDC252204B10E9D40C261 /* PushNotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */; }; + A638A1BE16A54E3211622438 /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694B2D575BBBC41B71834329 /* AccountViewModel.swift */; }; + A641ED77789933A35718DC56 /* ProfileRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDC14187D2E0615DBF2A5E /* ProfileRoute.swift */; }; + A7605511964265827B06E268 /* ProfileViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15BF430A0A932B943CE74B1 /* ProfileViewCoordinator.swift */; }; A93B2FC0C15576DDAD9F1772 /* DevLogCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70A888BE16FA57ED1309E014 /* DevLogCore.framework */; }; + AAB8401E0FE7598F54D43BFD /* TodoManageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */; }; + AC7102A1D35CB1817BD885E8 /* TodoEditorWindowEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF251D17AB6A6BE27E94F83F /* TodoEditorWindowEvent.swift */; }; + AD97294A20E386D840EADDDB /* MainViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD678C679B9975DFD646F8FE /* MainViewCoordinator.swift */; }; AECD97E6C980B7940A3112E4 /* Error+SocialLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6F1C309AC57614AD630F79 /* Error+SocialLogin.swift */; }; - AFF2EFF4181D0AB292540962 /* NavigationBarConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A16A2DF4C226ACFE7E2F2BD /* NavigationBarConfigurator.swift */; }; B11D48231BFAFAA422C7CB30 /* DevLogPresentation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D36A4E11056749B1D5DEF446 /* DevLogPresentation.framework */; }; - B81EE3C71EC5CCC8CB9D5CAC /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48DEAD71515D037F501E9B9F /* TodayViewModel.swift */; }; - B8792A002416865EF41FCB5D /* TodayViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B434E6F27EFBC9D054461A /* TodayViewCoordinator.swift */; }; - BC607762E625C0DCD3B66E8A /* PushNotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2663D0FE64234FEBBDA9362C /* PushNotificationSettingsViewModel.swift */; }; - BCDC49501F5BA61CABB12D2B /* MainViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36FA78DB36F62C17E9957AFF /* MainViewCoordinator.swift */; }; - BE51244E594875155551774A /* WebItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1D8AFC51309CDFB5962985 /* WebItemRow.swift */; }; - C13E62E8FB7D681C14A42AC1 /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E834C7D761EA77E717C9DE /* HomeViewModel.swift */; }; - C2530FF7F76903E54626D73B /* TodoEditorWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E802368D0BA811BD50470735 /* TodoEditorWindowView.swift */; }; + B947B17E4DFD433FD61EDEBF /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD96AE666281D6C27D81F773 /* HomeViewModel.swift */; }; C26C5A74B162EF0866093F6E /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = F44AF3158F945047473FA5E7 /* OrderedCollections */; }; - C3883077C738EF1E76DFCC4C /* RelativeTimeText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB112B525D9D6CB7B001028A /* RelativeTimeText.swift */; }; - CAD9F0F9CDADF2FA55CBC78B /* CacheableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C52955505427FEA95D9B3CC8 /* CacheableImage.swift */; }; + C5FD25074C105C9F278C71E6 /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */; }; + C9553B4DC3249D9EC36473AC /* HomeViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600892295632C397ECDD8AF4 /* HomeViewCoordinator.swift */; }; CB6204EC0FB8557D7FAF7174 /* HeatmapActivityItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E174814D9FFAFC79746E1902 /* HeatmapActivityItem.swift */; }; - D4C92919FF08171E53C15011 /* TodoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 334EB88BC5FC0BD7DDA6A0FE /* TodoDetailViewModel.swift */; }; + CDD5185569899FF1F600DD08 /* PushNotificationListViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7822B9271036D58AB46DB3 /* PushNotificationListViewCoordinator.swift */; }; D73622D51033A4BAF3B68DAC /* HeatmapMonth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD8C6D9E12E040F7B612FB1 /* HeatmapMonth.swift */; }; - D7E51185AD82E7DB333300AF /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D6ACE383B5F1DA964DAB252 /* AccountViewModel.swift */; }; + D7D6E761D1C930C71E445FC6 /* TodoWindowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04907C8B1F51AC9D8A164F02 /* TodoWindowCoordinator.swift */; }; D7F0530537BE180AEAA579BB /* DeletePushNotificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A05BB3C999F4A364401871C5 /* DeletePushNotificationTests.swift */; }; D878C47DE4B2E1A9525FBCBF /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DA5CF22287DA889A033F8E /* LoadingState.swift */; }; - D988D2118F62024F5BA6A095 /* TodoEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82C8541262E532FA4A218650 /* TodoEditorView.swift */; }; - D99AD1D26B1D745028A93B8A /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB82F4B31B49736F70F50EE7 /* SettingView.swift */; }; + DA951ACBCB7C625E36B2E709 /* HomeRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82BEFB32E7D34AB261823961 /* HomeRoute.swift */; }; + DC04D254D882504D1F00F609 /* TodayViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92080C40972043791AC990C /* TodayViewCoordinator.swift */; }; + DC2E2AB959A0EB7A28344690 /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4870173271638E9190A3E93B /* MainViewModel.swift */; }; DCD8775B3F51592DD956952F /* HeatmapQuarter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573AD2720FA89362FF4C4CEF /* HeatmapQuarter.swift */; }; - DDC4E20C8BDB38D0087A5190 /* TodoDetailContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1EE8F142D93B01909B6D5C8 /* TodoDetailContentView.swift */; }; - DFF40ACAFF99281CECC2303E /* PushNotificationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C346B13A821F3DFAB3489BBB /* PushNotificationSettingsView.swift */; }; - E53B0B91BEE6857758DAF9ED /* TodoItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA81C7F4127479FE7CCE033 /* TodoItemRow.swift */; }; - E548BBC38D99E0D2C7D1FA4B /* Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D1521A459AF5AEFFA99A83 /* Tags.swift */; }; - E635248ED51664A502A7F08A /* ThemeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89BC344F5437426E7A309429 /* ThemeView.swift */; }; - E8077B723C81E374416DE861 /* TodoEditorWindowValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA597F8A6C68F9460DE11FC /* TodoEditorWindowValue.swift */; }; E95BB5F53AE62F152798567D /* DevLogDomain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 950469A44DFD1834A6BFC4B2 /* DevLogDomain.framework */; }; - ED2003CBD86C61AB483F9D15 /* TodoManageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41DC5D62BCD0C53ADF8E7A6 /* TodoManageView.swift */; }; - EDDAC6A024EB85257A37723E /* TodayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C91DE4D388124119156BC64E /* TodayView.swift */; }; - F20FC30D05246FD333F034DE /* SettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81F9AF1E3CEC36D194A916C /* SettingViewModel.swift */; }; - F5D87CFA04C5DF6A6FA36129 /* TodoWindowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0435F01417FE17DE757ADB /* TodoWindowCoordinator.swift */; }; - FA2E29AB049CAC97DE350BE9 /* ProfileViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A87C034F294C1825D3AC49C3 /* ProfileViewCoordinator.swift */; }; + F62CD09589BE8D580A4197B3 /* MainViewDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6320220D0E377BC611B291CA /* MainViewDependencies.swift */; }; + FB83D3B1D387EB6E5E3F76BA /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C773450E521557929ED525E /* ProfileViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -131,96 +102,67 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 085FC0504CE36484B655FB09 /* TodoEditorWindowEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowEvent.swift; sourceTree = ""; }; + 04907C8B1F51AC9D8A164F02 /* TodoWindowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoWindowCoordinator.swift; sourceTree = ""; }; 08ACC3D94A90881383764E6C /* TodoIdItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoIdItem.swift; sourceTree = ""; }; 09CC8A2FCF1577B150A08D83 /* ActivityKindItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityKindItem.swift; sourceTree = ""; }; 0B8F3DEEF6527F9FBCBDCD5A /* TodoReferenceItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoReferenceItem.swift; sourceTree = ""; }; + 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewModel.swift; sourceTree = ""; }; 0EB658B8B1246F4399493FE3 /* TodoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListItem.swift; sourceTree = ""; }; 10169ED43745C8286BAA560A /* UserTodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTodoCategoryItem.swift; sourceTree = ""; }; 14DA5CF22287DA889A033F8E /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = ""; }; 160AF2C6625745DEFB4DB23C /* DevLogPresentationTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DevLogPresentationTests-Info.plist"; sourceTree = ""; }; 1B6F1C309AC57614AD630F79 /* Error+SocialLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+SocialLogin.swift"; sourceTree = ""; }; - 2195BF2BC362FB4BD570C915 /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = ""; }; - 252057C930A70DC1D5674EE5 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; - 2663D0FE64234FEBBDA9362C /* PushNotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsViewModel.swift; sourceTree = ""; }; 290DE2215D7061AC10A057D8 /* MainTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTab.swift; sourceTree = ""; }; - 2AED8D48F34AE2476CCF4F5A /* TodoInfoSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoInfoSheetView.swift; sourceTree = ""; }; - 334EB88BC5FC0BD7DDA6A0FE /* TodoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailViewModel.swift; sourceTree = ""; }; - 34028ABF87BCFE5E95B8DF2C /* TodoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListView.swift; sourceTree = ""; }; + 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModel.swift; sourceTree = ""; }; + 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewModel.swift; sourceTree = ""; }; + 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModel.swift; sourceTree = ""; }; 34C7A0A3DE0AB6D5E4DD116B /* PushNotificationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationItem.swift; sourceTree = ""; }; - 36FA78DB36F62C17E9957AFF /* MainViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewCoordinator.swift; sourceTree = ""; }; + 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailViewModel.swift; sourceTree = ""; }; 37323FDF36DF44C549A71A85 /* DeleteWebPageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteWebPageTests.swift; sourceTree = ""; }; 38030D2CAA016ABB3D0C396B /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; - 3CA75873FCFFC6182662694B /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; - 3D6ACE383B5F1DA964DAB252 /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = ""; }; - 3DC9F3129E8EEBF9CAC622E7 /* ProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; - 3EA81C7F4127479FE7CCE033 /* TodoItemRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoItemRow.swift; sourceTree = ""; }; - 4279F380763E7CFF063F4416 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; - 437D0037871D0A9E16D94C59 /* HeatmapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapView.swift; sourceTree = ""; }; - 46339787CA1BCF8EF8AACBC6 /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; - 48DEAD71515D037F501E9B9F /* TodayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModel.swift; sourceTree = ""; }; + 4870173271638E9190A3E93B /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; + 4C773450E521557929ED525E /* ProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; 4CD8C6D9E12E040F7B612FB1 /* HeatmapMonth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapMonth.swift; sourceTree = ""; }; - 4F32D20E83ABB122630F67BD /* CheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBox.swift; sourceTree = ""; }; + 4D87C5787A3E9EAD0CC10A3D /* TodoViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoViewModelFactory.swift; sourceTree = ""; }; + 4E7A86BE16165EE865C2CCB1 /* RootViewDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewDependencies.swift; sourceTree = ""; }; 5156DCFD77B78CAEE004CDDD /* TestSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSupport.swift; sourceTree = ""; }; - 53892CB6FB8F39CE967A3344 /* RootViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModel.swift; sourceTree = ""; }; - 55E834C7D761EA77E717C9DE /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; 573AD2720FA89362FF4C4CEF /* HeatmapQuarter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapQuarter.swift; sourceTree = ""; }; 587B2119664DB4FDF4A18FFE /* TodayTodoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayTodoItem.swift; sourceTree = ""; }; - 5A16A2DF4C226ACFE7E2F2BD /* NavigationBarConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarConfigurator.swift; sourceTree = ""; }; - 5F4AC141E5E2C9474DDBD35C /* ToolbarButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarButtons.swift; sourceTree = ""; }; + 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageViewModel.swift; sourceTree = ""; }; + 600892295632C397ECDD8AF4 /* HomeViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewCoordinator.swift; sourceTree = ""; }; 62A6CF5AAB9CCEAB35FB10A8 /* RecentTodoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentTodoItem.swift; sourceTree = ""; }; + 6320220D0E377BC611B291CA /* MainViewDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewDependencies.swift; sourceTree = ""; }; + 694B2D575BBBC41B71834329 /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = ""; }; 6AC3FF6088F0D784788A2E07 /* DevLogPresentationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DevLogPresentationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6B457717DEF395F131159C04 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; + 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorViewModel.swift; sourceTree = ""; }; 70A888BE16FA57ED1309E014 /* DevLogCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 70B652BF58D45805A57ECCE0 /* HeatmapDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapDay.swift; sourceTree = ""; }; - 7236EA0D4F011DB8D2922A65 /* HomeViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewCoordinator.swift; sourceTree = ""; }; - 79043B9D995BD5D987320FE6 /* EnvironmentValues+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+.swift"; sourceTree = ""; }; - 7DDABB53271F38BCC892B6DD /* TodoListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListViewModel.swift; sourceTree = ""; }; - 7FA597F8A6C68F9460DE11FC /* TodoEditorWindowValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowValue.swift; sourceTree = ""; }; - 80B7DE00658AC1080A3741C9 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; - 82C8541262E532FA4A218650 /* TodoEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorView.swift; sourceTree = ""; }; + 82BEFB32E7D34AB261823961 /* HomeRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRoute.swift; sourceTree = ""; }; 852D34A35C60375D1D9F9566 /* Color+Hex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Hex.swift"; sourceTree = ""; }; - 89BC344F5437426E7A309429 /* ThemeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeView.swift; sourceTree = ""; }; + 8C76C1FD0B57BC6E736F16F9 /* TodoEditorWindowDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowDependencies.swift; sourceTree = ""; }; 950469A44DFD1834A6BFC4B2 /* DevLogDomain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogDomain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9A6BFC9AC306836245B6E5CD /* TodoDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailView.swift; sourceTree = ""; }; - 9E2D739A2380C3D28C575D08 /* TodoEditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorViewModel.swift; sourceTree = ""; }; A05BB3C999F4A364401871C5 /* DeletePushNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletePushNotificationTests.swift; sourceTree = ""; }; - A4CFA6FFA82E0EC3C25D527B /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = ""; }; - A6F52E54B2F053507AE43819 /* PushNotificationListViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewCoordinator.swift; sourceTree = ""; }; - A87C034F294C1825D3AC49C3 /* ProfileViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewCoordinator.swift; sourceTree = ""; }; - A9B434E6F27EFBC9D054461A /* TodayViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewCoordinator.swift; sourceTree = ""; }; - AB112B525D9D6CB7B001028A /* RelativeTimeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelativeTimeText.swift; sourceTree = ""; }; ACA48428342FE3040FE708BE /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; - B1EE8F142D93B01909B6D5C8 /* TodoDetailContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailContentView.swift; sourceTree = ""; }; - B2D1521A459AF5AEFFA99A83 /* Tags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tags.swift; sourceTree = ""; }; - B81F9AF1E3CEC36D194A916C /* SettingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewModel.swift; sourceTree = ""; }; - B8C462E5D83C6B639A66ED26 /* LoginButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginButton.swift; sourceTree = ""; }; - BA1D8AFC51309CDFB5962985 /* WebItemRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebItemRow.swift; sourceTree = ""; }; + AD7822B9271036D58AB46DB3 /* PushNotificationListViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewCoordinator.swift; sourceTree = ""; }; + B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; + BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListViewModel.swift; sourceTree = ""; }; BAD66EB3834CFD3D64831511 /* DevLogPresentation-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DevLogPresentation-Info.plist"; sourceTree = ""; }; - BF0435F01417FE17DE757ADB /* TodoWindowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoWindowCoordinator.swift; sourceTree = ""; }; C0CBB0EEB3B15A4BE2EF9641 /* SystemTodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemTodoCategoryItem.swift; sourceTree = ""; }; - C25193961AAF03B736D8BA4D /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; - C346B13A821F3DFAB3489BBB /* PushNotificationSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsView.swift; sourceTree = ""; }; - C52955505427FEA95D9B3CC8 /* CacheableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheableImage.swift; sourceTree = ""; }; C8D191AD793EE0AC702B1539 /* WebPageItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebPageItem.swift; sourceTree = ""; }; - C91DE4D388124119156BC64E /* TodayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayView.swift; sourceTree = ""; }; - CFB7CB1992F8434647D2E8D1 /* TodoMarkdownContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoMarkdownContentView.swift; sourceTree = ""; }; - D136528209E2B94793441C78 /* NavigationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; + CE1E4F3FA850AB900BD0837A /* TodayRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayRoute.swift; sourceTree = ""; }; + CF251D17AB6A6BE27E94F83F /* TodoEditorWindowEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowEvent.swift; sourceTree = ""; }; + D15BF430A0A932B943CE74B1 /* ProfileViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewCoordinator.swift; sourceTree = ""; }; D36A4E11056749B1D5DEF446 /* DevLogPresentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogPresentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D87DA85DC7F13D4E5B570ED6 /* UIKitTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitTextEditor.swift; sourceTree = ""; }; - DA4D52F1343CECB8E0AC4742 /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = ""; }; + D92080C40972043791AC990C /* TodayViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewCoordinator.swift; sourceTree = ""; }; + D92F895EDEF78B5D98FB2A38 /* NavigationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; + DD96AE666281D6C27D81F773 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; DE04D300F1054596E630CF48 /* TodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoCategoryItem.swift; sourceTree = ""; }; E174814D9FFAFC79746E1902 /* HeatmapActivityItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapActivityItem.swift; sourceTree = ""; }; - E41DC5D62BCD0C53ADF8E7A6 /* TodoManageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageView.swift; sourceTree = ""; }; - E71459EB54EF7A0B3F294418 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; - E802368D0BA811BD50470735 /* TodoEditorWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowView.swift; sourceTree = ""; }; - E90A0B2F4523B8570322F54C /* TodoManageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageViewModel.swift; sourceTree = ""; }; - EACFDECD5652C67B68D4936D /* PushNotificationListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewModel.swift; sourceTree = ""; }; - F6D5BDBC6990696C3FA5B22A /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; - FB82F4B31B49736F70F50EE7 /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = ""; }; - FCFF8EE1B8855BA6B7BC315F /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; - FE62ED6DF757AF15ACBB2E07 /* PushNotificationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListView.swift; sourceTree = ""; }; - FF52D6EE30673D682147FAFE /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; + E2DDC14187D2E0615DBF2A5E /* ProfileRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRoute.swift; sourceTree = ""; }; + E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsViewModel.swift; sourceTree = ""; }; + EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; + F9206293A713E904877705C2 /* TodoEditorWindowValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowValue.swift; sourceTree = ""; }; + FD678C679B9975DFD646F8FE /* MainViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewCoordinator.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -246,16 +188,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 08B3FDD8A289549DF72F6194 /* PushNotification */ = { - isa = PBXGroup; - children = ( - FE62ED6DF757AF15ACBB2E07 /* PushNotificationListView.swift */, - A6F52E54B2F053507AE43819 /* PushNotificationListViewCoordinator.swift */, - EACFDECD5652C67B68D4936D /* PushNotificationListViewModel.swift */, - ); - path = PushNotification; - sourceTree = ""; - }; 14A1A6F2D3820B4A5D46C522 /* Structure */ = { isa = PBXGroup; children = ( @@ -267,37 +199,29 @@ path = Structure; sourceTree = ""; }; + 18C9CF72DAC34ECA7E31E748 /* Today */ = { + isa = PBXGroup; + children = ( + 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */, + ); + path = Today; + sourceTree = ""; + }; 27063F597048D820F9883728 /* Common */ = { isa = PBXGroup; children = ( - 371B9B2F1875AEA0F43E3E0E /* Component */, 14DA5CF22287DA889A033F8E /* LoadingState.swift */, - 5A16A2DF4C226ACFE7E2F2BD /* NavigationBarConfigurator.swift */, - D136528209E2B94793441C78 /* NavigationRouter.swift */, - B1EE8F142D93B01909B6D5C8 /* TodoDetailContentView.swift */, - 2AED8D48F34AE2476CCF4F5A /* TodoInfoSheetView.swift */, - CFB7CB1992F8434647D2E8D1 /* TodoMarkdownContentView.swift */, - E71459EB54EF7A0B3F294418 /* WebView.swift */, ); path = Common; sourceTree = ""; }; - 371B9B2F1875AEA0F43E3E0E /* Component */ = { + 37D573EBC059DB8F9B39E8A5 /* Home */ = { isa = PBXGroup; children = ( - C52955505427FEA95D9B3CC8 /* CacheableImage.swift */, - 4F32D20E83ABB122630F67BD /* CheckBox.swift */, - 46339787CA1BCF8EF8AACBC6 /* LoadingView.swift */, - B8C462E5D83C6B639A66ED26 /* LoginButton.swift */, - AB112B525D9D6CB7B001028A /* RelativeTimeText.swift */, - B2D1521A459AF5AEFFA99A83 /* Tags.swift */, - F6D5BDBC6990696C3FA5B22A /* Toast.swift */, - 3EA81C7F4127479FE7CCE033 /* TodoItemRow.swift */, - 5F4AC141E5E2C9474DDBD35C /* ToolbarButtons.swift */, - D87DA85DC7F13D4E5B570ED6 /* UIKitTextEditor.swift */, - BA1D8AFC51309CDFB5962985 /* WebItemRow.swift */, + 600892295632C397ECDD8AF4 /* HomeViewCoordinator.swift */, + 04907C8B1F51AC9D8A164F02 /* TodoWindowCoordinator.swift */, ); - path = Component; + path = Home; sourceTree = ""; }; 390E12487BFADB4E24342432 = { @@ -316,6 +240,15 @@ path = PushNotification; sourceTree = ""; }; + 42BBD3AF2069409BC92F4836 /* Window */ = { + isa = PBXGroup; + children = ( + CF251D17AB6A6BE27E94F83F /* TodoEditorWindowEvent.swift */, + F9206293A713E904877705C2 /* TodoEditorWindowValue.swift */, + ); + path = Window; + sourceTree = ""; + }; 45314146CCCDB21E58DBA0E4 /* Todo */ = { isa = PBXGroup; children = ( @@ -331,97 +264,95 @@ path = Todo; sourceTree = ""; }; + 4C1C8973B4B04EE1A85E7BC3 /* Main */ = { + isa = PBXGroup; + children = ( + FD678C679B9975DFD646F8FE /* MainViewCoordinator.swift */, + ); + path = Main; + sourceTree = ""; + }; 4D616118490727A8BF1F8245 /* Sources */ = { isa = PBXGroup; children = ( 27063F597048D820F9883728 /* Common */, + 5F58BA536C964633FB5CDF43 /* Coordinator */, + 541E93B971F2E4140A81FFAA /* Dependency */, EB3C311DC8A5D8096FAA76BC /* Extension */, - 5E947E5BECBCBF1C9366945E /* Home */, - BEA53BCE9F5CBA2B9D2748D9 /* Login */, - 95FF4A87BE2DD7696EA4E3D1 /* Main */, - 75CBC4AAD72E791B1C0D3F88 /* Profile */, F3DDEDB0AF4ACA47ACCB8AEA /* Protocol */, - 08B3FDD8A289549DF72F6194 /* PushNotification */, - E35F56087C5F3A236FD17FF2 /* Root */, D04E76D2F842BF00A4AC7226 /* Routing */, - 7530E5897034E53A8917ABEF /* Search */, - 7A7A479862A8D15E79182C88 /* Setting */, 14A1A6F2D3820B4A5D46C522 /* Structure */, - E90A426B16234A9CFAB33C3A /* Today */, + CD4F7027F750752F2BD6484D /* ViewModel */, + 42BBD3AF2069409BC92F4836 /* Window */, ); path = Sources; sourceTree = ""; }; - 553C78A90E9B182409A7EBAE /* Home */ = { + 541E93B971F2E4140A81FFAA /* Dependency */ = { isa = PBXGroup; children = ( - 252057C930A70DC1D5674EE5 /* HomeView.swift */, - 7236EA0D4F011DB8D2922A65 /* HomeViewCoordinator.swift */, - 55E834C7D761EA77E717C9DE /* HomeViewModel.swift */, + 6320220D0E377BC611B291CA /* MainViewDependencies.swift */, + 4E7A86BE16165EE865C2CCB1 /* RootViewDependencies.swift */, + 8C76C1FD0B57BC6E736F16F9 /* TodoEditorWindowDependencies.swift */, + 4D87C5787A3E9EAD0CC10A3D /* TodoViewModelFactory.swift */, ); - path = Home; + path = Dependency; sourceTree = ""; }; - 5E947E5BECBCBF1C9366945E /* Home */ = { + 5F58BA536C964633FB5CDF43 /* Coordinator */ = { isa = PBXGroup; children = ( - 553C78A90E9B182409A7EBAE /* Home */, - 9A6BFC9AC306836245B6E5CD /* TodoDetailView.swift */, - 334EB88BC5FC0BD7DDA6A0FE /* TodoDetailViewModel.swift */, - 82C8541262E532FA4A218650 /* TodoEditorView.swift */, - 9E2D739A2380C3D28C575D08 /* TodoEditorViewModel.swift */, - 085FC0504CE36484B655FB09 /* TodoEditorWindowEvent.swift */, - 7FA597F8A6C68F9460DE11FC /* TodoEditorWindowValue.swift */, - E802368D0BA811BD50470735 /* TodoEditorWindowView.swift */, - 34028ABF87BCFE5E95B8DF2C /* TodoListView.swift */, - 7DDABB53271F38BCC892B6DD /* TodoListViewModel.swift */, - E41DC5D62BCD0C53ADF8E7A6 /* TodoManageView.swift */, - E90A0B2F4523B8570322F54C /* TodoManageViewModel.swift */, - BF0435F01417FE17DE757ADB /* TodoWindowCoordinator.swift */, + 37D573EBC059DB8F9B39E8A5 /* Home */, + 4C1C8973B4B04EE1A85E7BC3 /* Main */, + CBE2F0C6D1C3C09A2123FB42 /* Profile */, + 6284DFBA7474E6C90C8AC1A8 /* PushNotification */, + 62DD3E6D02222D2A8BABFFE7 /* Today */, ); - path = Home; + path = Coordinator; sourceTree = ""; }; - 662F424B1BAF5366B2AE858C /* Derived */ = { + 6284DFBA7474E6C90C8AC1A8 /* PushNotification */ = { isa = PBXGroup; children = ( - 9105D8FAAC29C3CC853C4FFB /* InfoPlists */, + AD7822B9271036D58AB46DB3 /* PushNotificationListViewCoordinator.swift */, ); - path = Derived; + path = PushNotification; sourceTree = ""; }; - 7530E5897034E53A8917ABEF /* Search */ = { + 62DD3E6D02222D2A8BABFFE7 /* Today */ = { isa = PBXGroup; children = ( - 80B7DE00658AC1080A3741C9 /* SearchView.swift */, - FCFF8EE1B8855BA6B7BC315F /* SearchViewModel.swift */, + D92080C40972043791AC990C /* TodayViewCoordinator.swift */, ); - path = Search; + path = Today; sourceTree = ""; }; - 75CBC4AAD72E791B1C0D3F88 /* Profile */ = { + 662F424B1BAF5366B2AE858C /* Derived */ = { isa = PBXGroup; children = ( - 437D0037871D0A9E16D94C59 /* HeatmapView.swift */, - 3CA75873FCFFC6182662694B /* ProfileView.swift */, - A87C034F294C1825D3AC49C3 /* ProfileViewCoordinator.swift */, - 3DC9F3129E8EEBF9CAC622E7 /* ProfileViewModel.swift */, + 9105D8FAAC29C3CC853C4FFB /* InfoPlists */, + ); + path = Derived; + sourceTree = ""; + }; + 737FAF490D9B7B4331080E45 /* Profile */ = { + isa = PBXGroup; + children = ( + 4C773450E521557929ED525E /* ProfileViewModel.swift */, ); path = Profile; sourceTree = ""; }; - 7A7A479862A8D15E79182C88 /* Setting */ = { + 7D6CA57DBD171C456BFEE533 /* Home */ = { isa = PBXGroup; children = ( - A4CFA6FFA82E0EC3C25D527B /* AccountView.swift */, - 3D6ACE383B5F1DA964DAB252 /* AccountViewModel.swift */, - C346B13A821F3DFAB3489BBB /* PushNotificationSettingsView.swift */, - 2663D0FE64234FEBBDA9362C /* PushNotificationSettingsViewModel.swift */, - FB82F4B31B49736F70F50EE7 /* SettingView.swift */, - B81F9AF1E3CEC36D194A916C /* SettingViewModel.swift */, - 89BC344F5437426E7A309429 /* ThemeView.swift */, + DD96AE666281D6C27D81F773 /* HomeViewModel.swift */, + 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */, + 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */, + BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */, + 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */, ); - path = Setting; + path = Home; sourceTree = ""; }; 80795F4F20E81C1E84803EB8 /* Support */ = { @@ -464,43 +395,68 @@ name = Products; sourceTree = ""; }; - 95FF4A87BE2DD7696EA4E3D1 /* Main */ = { + BF5F3862615F56298F9D9B7B /* Tests */ = { isa = PBXGroup; children = ( - 6B457717DEF395F131159C04 /* MainView.swift */, - 36FA78DB36F62C17E9957AFF /* MainViewCoordinator.swift */, - C25193961AAF03B736D8BA4D /* MainViewModel.swift */, + 3E97BDE9D214E3A24DC7BA47 /* PushNotification */, + 80795F4F20E81C1E84803EB8 /* Support */, + E58AB79C6479D3AAF6226813 /* WebPage */, ); - path = Main; + path = Tests; sourceTree = ""; }; - BEA53BCE9F5CBA2B9D2748D9 /* Login */ = { + CA2593D720DA024EF27E514A /* Login */ = { isa = PBXGroup; children = ( - 4279F380763E7CFF063F4416 /* LoginView.swift */, - FF52D6EE30673D682147FAFE /* LoginViewModel.swift */, + B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */, ); path = Login; sourceTree = ""; }; - BF5F3862615F56298F9D9B7B /* Tests */ = { + CBE2F0C6D1C3C09A2123FB42 /* Profile */ = { isa = PBXGroup; children = ( - 3E97BDE9D214E3A24DC7BA47 /* PushNotification */, - 80795F4F20E81C1E84803EB8 /* Support */, - E58AB79C6479D3AAF6226813 /* WebPage */, + D15BF430A0A932B943CE74B1 /* ProfileViewCoordinator.swift */, ); - path = Tests; + path = Profile; + sourceTree = ""; + }; + CD4F7027F750752F2BD6484D /* ViewModel */ = { + isa = PBXGroup; + children = ( + 7D6CA57DBD171C456BFEE533 /* Home */, + CA2593D720DA024EF27E514A /* Login */, + F7D309730F31660066D7246C /* Main */, + 737FAF490D9B7B4331080E45 /* Profile */, + DC9C55D162DD068D635BA358 /* PushNotification */, + D62728F4D18FC50778C86BF9 /* Root */, + F75E3F153FDD92A392CE9F77 /* Search */, + FAC2309E83621894414350E6 /* Setting */, + 18C9CF72DAC34ECA7E31E748 /* Today */, + ); + path = ViewModel; sourceTree = ""; }; D04E76D2F842BF00A4AC7226 /* Routing */ = { isa = PBXGroup; children = ( + 82BEFB32E7D34AB261823961 /* HomeRoute.swift */, 290DE2215D7061AC10A057D8 /* MainTab.swift */, + D92F895EDEF78B5D98FB2A38 /* NavigationRouter.swift */, + E2DDC14187D2E0615DBF2A5E /* ProfileRoute.swift */, + CE1E4F3FA850AB900BD0837A /* TodayRoute.swift */, ); path = Routing; sourceTree = ""; }; + D62728F4D18FC50778C86BF9 /* Root */ = { + isa = PBXGroup; + children = ( + 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */, + ); + path = Root; + sourceTree = ""; + }; D68750D8827585A7F938F99E /* Project */ = { isa = PBXGroup; children = ( @@ -512,13 +468,12 @@ name = Project; sourceTree = ""; }; - E35F56087C5F3A236FD17FF2 /* Root */ = { + DC9C55D162DD068D635BA358 /* PushNotification */ = { isa = PBXGroup; children = ( - 2195BF2BC362FB4BD570C915 /* RootView.swift */, - 53892CB6FB8F39CE967A3344 /* RootViewModel.swift */, + 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */, ); - path = Root; + path = PushNotification; sourceTree = ""; }; E58AB79C6479D3AAF6226813 /* WebPage */ = { @@ -529,23 +484,11 @@ path = WebPage; sourceTree = ""; }; - E90A426B16234A9CFAB33C3A /* Today */ = { - isa = PBXGroup; - children = ( - C91DE4D388124119156BC64E /* TodayView.swift */, - A9B434E6F27EFBC9D054461A /* TodayViewCoordinator.swift */, - 48DEAD71515D037F501E9B9F /* TodayViewModel.swift */, - ); - path = Today; - sourceTree = ""; - }; EB3C311DC8A5D8096FAA76BC /* Extension */ = { isa = PBXGroup; children = ( 852D34A35C60375D1D9F9566 /* Color+Hex.swift */, - 79043B9D995BD5D987320FE6 /* EnvironmentValues+.swift */, 1B6F1C309AC57614AD630F79 /* Error+SocialLogin.swift */, - DA4D52F1343CECB8E0AC4742 /* View+.swift */, ); path = Extension; sourceTree = ""; @@ -558,6 +501,32 @@ path = Protocol; sourceTree = ""; }; + F75E3F153FDD92A392CE9F77 /* Search */ = { + isa = PBXGroup; + children = ( + EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */, + ); + path = Search; + sourceTree = ""; + }; + F7D309730F31660066D7246C /* Main */ = { + isa = PBXGroup; + children = ( + 4870173271638E9190A3E93B /* MainViewModel.swift */, + ); + path = Main; + sourceTree = ""; + }; + FAC2309E83621894414350E6 /* Setting */ = { + isa = PBXGroup; + children = ( + 694B2D575BBBC41B71834329 /* AccountViewModel.swift */, + E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */, + 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */, + ); + path = Setting; + sourceTree = ""; + }; FF7A52F8B2FCBBE98267FD8D /* Shared */ = { isa = PBXGroup; children = ( @@ -674,68 +643,25 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CAD9F0F9CDADF2FA55CBC78B /* CacheableImage.swift in Sources */, - 042A04373E0BF17A8C0E90A1 /* CheckBox.swift in Sources */, - 0BDF307FFD70E121BFE54B64 /* LoadingView.swift in Sources */, - 57373F815DB5EF9310AC641D /* LoginButton.swift in Sources */, - C3883077C738EF1E76DFCC4C /* RelativeTimeText.swift in Sources */, - E548BBC38D99E0D2C7D1FA4B /* Tags.swift in Sources */, - 21D9F0E69F0F648AA719D3A8 /* Toast.swift in Sources */, - E53B0B91BEE6857758DAF9ED /* TodoItemRow.swift in Sources */, - 58A933F1C49D9977217BE84C /* ToolbarButtons.swift in Sources */, - 711C3E31B02B60A4E1FB01CF /* UIKitTextEditor.swift in Sources */, - BE51244E594875155551774A /* WebItemRow.swift in Sources */, D878C47DE4B2E1A9525FBCBF /* LoadingState.swift in Sources */, - AFF2EFF4181D0AB292540962 /* NavigationBarConfigurator.swift in Sources */, - 9D69715291EB7F2AE704A722 /* NavigationRouter.swift in Sources */, - DDC4E20C8BDB38D0087A5190 /* TodoDetailContentView.swift in Sources */, - 70FC630DC3FC27D77EA868FD /* TodoInfoSheetView.swift in Sources */, - 4C07B469D6576A76BE71E639 /* TodoMarkdownContentView.swift in Sources */, - 5FF8EAE9E54F8359A5391EFC /* WebView.swift in Sources */, + C9553B4DC3249D9EC36473AC /* HomeViewCoordinator.swift in Sources */, + D7D6E761D1C930C71E445FC6 /* TodoWindowCoordinator.swift in Sources */, + AD97294A20E386D840EADDDB /* MainViewCoordinator.swift in Sources */, + A7605511964265827B06E268 /* ProfileViewCoordinator.swift in Sources */, + CDD5185569899FF1F600DD08 /* PushNotificationListViewCoordinator.swift in Sources */, + DC04D254D882504D1F00F609 /* TodayViewCoordinator.swift in Sources */, + F62CD09589BE8D580A4197B3 /* MainViewDependencies.swift in Sources */, + 3F8512559CCF262222ACCAE2 /* RootViewDependencies.swift in Sources */, + 26F47ED71B5B0701B1344A17 /* TodoEditorWindowDependencies.swift in Sources */, + 0C65DE6F8B9FB06F8D121D1E /* TodoViewModelFactory.swift in Sources */, 26ED8F658B02153735BD8692 /* Color+Hex.swift in Sources */, - 0675430931A12884236C92E7 /* EnvironmentValues+.swift in Sources */, AECD97E6C980B7940A3112E4 /* Error+SocialLogin.swift in Sources */, - 653BC11E9CB8F74FC090E3A1 /* View+.swift in Sources */, - 9ADFFABEE75489A526E1ECE5 /* HomeView.swift in Sources */, - 9060015EC9ECBFF1A2511DC6 /* HomeViewCoordinator.swift in Sources */, - C13E62E8FB7D681C14A42AC1 /* HomeViewModel.swift in Sources */, - 3A78734125366B547D0C4261 /* TodoDetailView.swift in Sources */, - D4C92919FF08171E53C15011 /* TodoDetailViewModel.swift in Sources */, - D988D2118F62024F5BA6A095 /* TodoEditorView.swift in Sources */, - 959832CAA00E2B06DF0B8A83 /* TodoEditorViewModel.swift in Sources */, - 175898C005C97BED56549457 /* TodoEditorWindowEvent.swift in Sources */, - E8077B723C81E374416DE861 /* TodoEditorWindowValue.swift in Sources */, - C2530FF7F76903E54626D73B /* TodoEditorWindowView.swift in Sources */, - 0B436A4BB4F4289DC5A24286 /* TodoListView.swift in Sources */, - 90A88D80EF02129348CE35C5 /* TodoListViewModel.swift in Sources */, - ED2003CBD86C61AB483F9D15 /* TodoManageView.swift in Sources */, - 40B4784EB5FDD90B5A2EC81B /* TodoManageViewModel.swift in Sources */, - F5D87CFA04C5DF6A6FA36129 /* TodoWindowCoordinator.swift in Sources */, - 3801176C353549D8D259FF4A /* LoginView.swift in Sources */, - 3AE04B27F085D1E67BA64537 /* LoginViewModel.swift in Sources */, - 49631F09477091376DDA0E4D /* MainView.swift in Sources */, - BCDC49501F5BA61CABB12D2B /* MainViewCoordinator.swift in Sources */, - 19A49575DE29575B3E30D42F /* MainViewModel.swift in Sources */, - 8D320EC70D396E019F964166 /* HeatmapView.swift in Sources */, - 5931685A7811D0DCDF5508BF /* ProfileView.swift in Sources */, - FA2E29AB049CAC97DE350BE9 /* ProfileViewCoordinator.swift in Sources */, - 5FD86AC94DE236C77BA69CB0 /* ProfileViewModel.swift in Sources */, 173C43896990D2469CB29D6B /* Store.swift in Sources */, - 8A76D55BB0714508C1019108 /* PushNotificationListView.swift in Sources */, - 164FF0D15F3671EC5B8175B4 /* PushNotificationListViewCoordinator.swift in Sources */, - 6DC7980E5F659AC3FB56427E /* PushNotificationListViewModel.swift in Sources */, - A302B2F9FDCDAFAE5A852E94 /* RootView.swift in Sources */, - 84866D96D8DE6F76E805050F /* RootViewModel.swift in Sources */, + DA951ACBCB7C625E36B2E709 /* HomeRoute.swift in Sources */, 41A5C4626505C6BF0643E43B /* MainTab.swift in Sources */, - 909B1608BDEDA51B07F27332 /* SearchView.swift in Sources */, - 2B0C47EBD387EEABE2A90A99 /* SearchViewModel.swift in Sources */, - 439047A7AF80D876838710F2 /* AccountView.swift in Sources */, - D7E51185AD82E7DB333300AF /* AccountViewModel.swift in Sources */, - DFF40ACAFF99281CECC2303E /* PushNotificationSettingsView.swift in Sources */, - BC607762E625C0DCD3B66E8A /* PushNotificationSettingsViewModel.swift in Sources */, - D99AD1D26B1D745028A93B8A /* SettingView.swift in Sources */, - F20FC30D05246FD333F034DE /* SettingViewModel.swift in Sources */, - E635248ED51664A502A7F08A /* ThemeView.swift in Sources */, + 3D0FB9275F7BC7D914D8EC55 /* NavigationRouter.swift in Sources */, + A641ED77789933A35718DC56 /* ProfileRoute.swift in Sources */, + 5357B7DBEC07C590B8C70E20 /* TodayRoute.swift in Sources */, 4BE7032EE7146793A5C58A94 /* ActivityKindItem.swift in Sources */, CB6204EC0FB8557D7FAF7174 /* HeatmapActivityItem.swift in Sources */, 2DB84D2FBEA0653D48DF614F /* HeatmapDay.swift in Sources */, @@ -751,9 +677,23 @@ 03CF7E696626224FFE93FFDD /* TodoReferenceItem.swift in Sources */, 053BC20B9244F93FFE9E6FA7 /* UserTodoCategoryItem.swift in Sources */, 277C3C6802370B2DB28EA92A /* WebPageItem.swift in Sources */, - EDDAC6A024EB85257A37723E /* TodayView.swift in Sources */, - B8792A002416865EF41FCB5D /* TodayViewCoordinator.swift in Sources */, - B81EE3C71EC5CCC8CB9D5CAC /* TodayViewModel.swift in Sources */, + B947B17E4DFD433FD61EDEBF /* HomeViewModel.swift in Sources */, + 38BA6B9310BB45F46683D105 /* TodoDetailViewModel.swift in Sources */, + 0DA6A035B08B2E1FA91A5CCA /* TodoEditorViewModel.swift in Sources */, + 7BAB031CACEE7F60CC0A14D9 /* TodoListViewModel.swift in Sources */, + AAB8401E0FE7598F54D43BFD /* TodoManageViewModel.swift in Sources */, + 34151EB8B72D12C8D373F567 /* LoginViewModel.swift in Sources */, + DC2E2AB959A0EB7A28344690 /* MainViewModel.swift in Sources */, + FB83D3B1D387EB6E5E3F76BA /* ProfileViewModel.swift in Sources */, + 0A25E266F29F6ACD7E6154EE /* PushNotificationListViewModel.swift in Sources */, + 5529852916250307CEDF2210 /* RootViewModel.swift in Sources */, + 5DDA91AD574C37E26C667F24 /* SearchViewModel.swift in Sources */, + A638A1BE16A54E3211622438 /* AccountViewModel.swift in Sources */, + 99EFDC252204B10E9D40C261 /* PushNotificationSettingsViewModel.swift in Sources */, + 6E428FE9D2F09F9696B4BB52 /* SettingViewModel.swift in Sources */, + C5FD25074C105C9F278C71E6 /* TodayViewModel.swift in Sources */, + AC7102A1D35CB1817BD885E8 /* TodoEditorWindowEvent.swift in Sources */, + 35639553522A1CEFDCF455D7 /* TodoEditorWindowValue.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj b/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj new file mode 100644 index 00000000..5e4a830e --- /dev/null +++ b/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj @@ -0,0 +1,708 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 07DC30D6EE53D3FEB18D4560 /* WebItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F78B3C0ACB40D516459405 /* WebItemRow.swift */; }; + 1F194D9E0C40F9C8D0BBFD81 /* CacheableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211DFAB11C0329E438E5D600 /* CacheableImage.swift */; }; + 3BC362E7B3729B9B766D0E82 /* TodoItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 529B9370AF656D07E6CF9C75 /* TodoItemRow.swift */; }; + 3CD4C5F7BA6AE10FD96EED2D /* PushNotificationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11529C090F3011129AC4A3 /* PushNotificationListView.swift */; }; + 436190F41C9108F6D4936027 /* TodoInfoSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FC36435309F9D84B455253 /* TodoInfoSheetView.swift */; }; + 4726811A94C0478F5A807A02 /* View+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B63ED91862D0C29DCF3ACA6 /* View+.swift */; }; + 534E2A2C85E646406895773D /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFDA486635D32624EED7F8D /* MainView.swift */; }; + 62A8F2367EF38AD98E4C4539 /* HeatmapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E82400E6B2C33B0E139E7C5D /* HeatmapView.swift */; }; + 62DB113F0728D6B2A24D4ECA /* RelativeTimeText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53E6647B22EA064CB79BABF1 /* RelativeTimeText.swift */; }; + 6878F8DBE4009B0462BFCAB4 /* TodoListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B6C083CF1FB1B18A7A7C0 /* TodoListView.swift */; }; + 69E94B7AD0D2AF37B418A8F4 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80338B4AC83F0BC401B73C81 /* ProfileView.swift */; }; + 76DBAFDBB18F6EC9ABACFC2D /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8D9416BB473F30DCCD7E859 /* HomeView.swift */; }; + 76DFE29F22D4336EE4C36B73 /* ThemeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A44E5A8322D9ADC2D2709471 /* ThemeView.swift */; }; + 7856BF83CB7D2D0F7B4774CF /* EnvironmentValues+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6056412772C2E91882B9C3D3 /* EnvironmentValues+.swift */; }; + 7DE3B4F05C4BEEF05B58FCF5 /* SettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2EB00F69C800B922FF8A48A /* SettingView.swift */; }; + 81BC04E40F6CED522AF09D8F /* PushNotificationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C41C9CD1A01AFBD1B64281D2 /* PushNotificationSettingsView.swift */; }; + 823A5A6BA41BCA257AD3586D /* TodoManageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AF9DFAB631D9D4BFE8D5891 /* TodoManageView.swift */; }; + 87FF186B7907E7F1B2DE5E60 /* AccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56823A0901F960041578908A /* AccountView.swift */; }; + 9D8ECA3815FA283133EBFE93 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = CCFA0DE9FF601686A0FFA868 /* OrderedCollections */; }; + 9E96551C79A75284146EC61D /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3EC0620703CDC1D064C2F8 /* LoginView.swift */; }; + 9FC8F731D0C5F71AE08884ED /* TodoEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E155E338E408858E973C7C /* TodoEditorView.swift */; }; + AC8A6800BA486E5B49DF24D3 /* DevLogPresentation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D26E37F394F95F6AA0B184A4 /* DevLogPresentation.framework */; }; + AD69309B3A8854AC0C659DFF /* CheckBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CE52F7F2F780808645E2DBF /* CheckBox.swift */; }; + AF285B7139AEDA9D38AF387F /* ToolbarButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0F84711E9735427E326A3D6 /* ToolbarButtons.swift */; }; + B32465C08D91FC006E5CF3D2 /* LoginButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC25959F0F7C16E491AF3A74 /* LoginButton.swift */; }; + B440FE5BC83625806D5137DC /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77A2025370CB07568F045A6E /* WebView.swift */; }; + BF37121E20F7AE5443957E16 /* TodayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F2B7063B902FE6BD1DAD25 /* TodayView.swift */; }; + CD5C10D07CBA3369F4BE94D5 /* UIKitTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8001CAEEA6AF0CD88497E1 /* UIKitTextEditor.swift */; }; + E18A468C5AC5A60C18CF7A99 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B2F723F05245A13C55118AC /* SearchView.swift */; }; + E1F211A3100CD23E688CFEAD /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00F4FF1816573AFDF15BC06F /* LoadingView.swift */; }; + E20A6D6F2126952F83EF28AD /* TodoDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CBD74F72172BA31A47E1961 /* TodoDetailView.swift */; }; + E4AFAE6984B3251648B09C49 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEB00DB87DA750172D839934 /* Toast.swift */; }; + EC510917A2262FEE5842FADD /* Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = C70BAD6474F5C8DA82B47AA2 /* Tags.swift */; }; + EE11A7B71A16E9A205B163D1 /* NavigationBarConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83E8FBE8B634CD815D40C928 /* NavigationBarConfigurator.swift */; }; + F0AA0AF4F10C13242BBD4025 /* TodoDetailContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51ADB239DCB3639943C6EE7 /* TodoDetailContentView.swift */; }; + FBAFCE11F1766FBFBB24807C /* TodoMarkdownContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F3BBD8DF91AE3A8B7FAC599 /* TodoMarkdownContentView.swift */; }; + FD6C0E913FFA9988FFCF8419 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 7A26AD882B24E0CD5F4DEC5C /* MarkdownUI */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 1E92F96D37C3D41CAC9C29AF /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 00F4FF1816573AFDF15BC06F /* LoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = ""; }; + 19FC36435309F9D84B455253 /* TodoInfoSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoInfoSheetView.swift; sourceTree = ""; }; + 1BFDA486635D32624EED7F8D /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; }; + 1CE52F7F2F780808645E2DBF /* CheckBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBox.swift; sourceTree = ""; }; + 1F083216D01A83A4386A1258 /* DevLogUI-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DevLogUI-Info.plist"; sourceTree = ""; }; + 211DFAB11C0329E438E5D600 /* CacheableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheableImage.swift; sourceTree = ""; }; + 2B2F723F05245A13C55118AC /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; + 2C3EC0620703CDC1D064C2F8 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = ""; }; + 508B6C083CF1FB1B18A7A7C0 /* TodoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListView.swift; sourceTree = ""; }; + 52512F0A61A001595E088847 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; + 529B9370AF656D07E6CF9C75 /* TodoItemRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoItemRow.swift; sourceTree = ""; }; + 53E6647B22EA064CB79BABF1 /* RelativeTimeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelativeTimeText.swift; sourceTree = ""; }; + 56823A0901F960041578908A /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = ""; }; + 5AF9DFAB631D9D4BFE8D5891 /* TodoManageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageView.swift; sourceTree = ""; }; + 6056412772C2E91882B9C3D3 /* EnvironmentValues+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+.swift"; sourceTree = ""; }; + 6B63ED91862D0C29DCF3ACA6 /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = ""; }; + 77A2025370CB07568F045A6E /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; + 80338B4AC83F0BC401B73C81 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; + 83E8FBE8B634CD815D40C928 /* NavigationBarConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarConfigurator.swift; sourceTree = ""; }; + 99F78B3C0ACB40D516459405 /* WebItemRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebItemRow.swift; sourceTree = ""; }; + 9CBD74F72172BA31A47E1961 /* TodoDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailView.swift; sourceTree = ""; }; + 9F3BBD8DF91AE3A8B7FAC599 /* TodoMarkdownContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoMarkdownContentView.swift; sourceTree = ""; }; + A44E5A8322D9ADC2D2709471 /* ThemeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeView.swift; sourceTree = ""; }; + A8D9416BB473F30DCCD7E859 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + AEB00DB87DA750172D839934 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; + BD11529C090F3011129AC4A3 /* PushNotificationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListView.swift; sourceTree = ""; }; + C41C9CD1A01AFBD1B64281D2 /* PushNotificationSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsView.swift; sourceTree = ""; }; + C70BAD6474F5C8DA82B47AA2 /* Tags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tags.swift; sourceTree = ""; }; + CA0F9AEA78082777BD930922 /* DevLogUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + CC25959F0F7C16E491AF3A74 /* LoginButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginButton.swift; sourceTree = ""; }; + CE8001CAEEA6AF0CD88497E1 /* UIKitTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitTextEditor.swift; sourceTree = ""; }; + D26E37F394F95F6AA0B184A4 /* DevLogPresentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogPresentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D51ADB239DCB3639943C6EE7 /* TodoDetailContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailContentView.swift; sourceTree = ""; }; + D5F2B7063B902FE6BD1DAD25 /* TodayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayView.swift; sourceTree = ""; }; + E2EB00F69C800B922FF8A48A /* SettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingView.swift; sourceTree = ""; }; + E82400E6B2C33B0E139E7C5D /* HeatmapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapView.swift; sourceTree = ""; }; + F0F84711E9735427E326A3D6 /* ToolbarButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarButtons.swift; sourceTree = ""; }; + F6E155E338E408858E973C7C /* TodoEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FE93059CE51F086DC6395122 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AC8A6800BA486E5B49DF24D3 /* DevLogPresentation.framework in Frameworks */, + FD6C0E913FFA9988FFCF8419 /* MarkdownUI in Frameworks */, + 9D8ECA3815FA283133EBFE93 /* OrderedCollections in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0F62DEECBFA6B482A490C188 /* Sources */ = { + isa = PBXGroup; + children = ( + AC7918DF414EAC42574C43C8 /* Common */, + 1BD39CF102FF36BDEDB10517 /* Extension */, + E30D4244433A5F1D744A152C /* Home */, + 82B843E51D57EFD360E76AA1 /* Login */, + 2C336E1602D5099AF3FA0726 /* Main */, + 9BC94E41246B01D219246605 /* Profile */, + CBE61554E7CA53C42DEA3473 /* PushNotification */, + 2BA5EAEFFE2AA1A6A16CF6D3 /* Search */, + BCA2DFAF282AC5461CF72C04 /* Setting */, + E2476D845591F375F0AB695C /* Today */, + ); + path = Sources; + sourceTree = ""; + }; + 1BD39CF102FF36BDEDB10517 /* Extension */ = { + isa = PBXGroup; + children = ( + 6056412772C2E91882B9C3D3 /* EnvironmentValues+.swift */, + 6B63ED91862D0C29DCF3ACA6 /* View+.swift */, + ); + path = Extension; + sourceTree = ""; + }; + 25EB81C4CCB2507411589B48 = { + isa = PBXGroup; + children = ( + B94A7F98803FFD2D526DC3F0 /* Products */, + AA9D3556BF0D5914D341DA26 /* Project */, + ); + sourceTree = ""; + }; + 2BA5EAEFFE2AA1A6A16CF6D3 /* Search */ = { + isa = PBXGroup; + children = ( + 2B2F723F05245A13C55118AC /* SearchView.swift */, + ); + path = Search; + sourceTree = ""; + }; + 2C336E1602D5099AF3FA0726 /* Main */ = { + isa = PBXGroup; + children = ( + 1BFDA486635D32624EED7F8D /* MainView.swift */, + ); + path = Main; + sourceTree = ""; + }; + 5582AA34439F4532105E68D4 /* Component */ = { + isa = PBXGroup; + children = ( + 211DFAB11C0329E438E5D600 /* CacheableImage.swift */, + 1CE52F7F2F780808645E2DBF /* CheckBox.swift */, + 00F4FF1816573AFDF15BC06F /* LoadingView.swift */, + CC25959F0F7C16E491AF3A74 /* LoginButton.swift */, + 53E6647B22EA064CB79BABF1 /* RelativeTimeText.swift */, + C70BAD6474F5C8DA82B47AA2 /* Tags.swift */, + AEB00DB87DA750172D839934 /* Toast.swift */, + 529B9370AF656D07E6CF9C75 /* TodoItemRow.swift */, + F0F84711E9735427E326A3D6 /* ToolbarButtons.swift */, + CE8001CAEEA6AF0CD88497E1 /* UIKitTextEditor.swift */, + 99F78B3C0ACB40D516459405 /* WebItemRow.swift */, + ); + path = Component; + sourceTree = ""; + }; + 6883B25D0D519884DF1060AB /* Shared */ = { + isa = PBXGroup; + children = ( + 52512F0A61A001595E088847 /* Version.xcconfig */, + ); + name = Shared; + path = ../Shared; + sourceTree = ""; + }; + 82B843E51D57EFD360E76AA1 /* Login */ = { + isa = PBXGroup; + children = ( + 2C3EC0620703CDC1D064C2F8 /* LoginView.swift */, + ); + path = Login; + sourceTree = ""; + }; + 9BC94E41246B01D219246605 /* Profile */ = { + isa = PBXGroup; + children = ( + E82400E6B2C33B0E139E7C5D /* HeatmapView.swift */, + 80338B4AC83F0BC401B73C81 /* ProfileView.swift */, + ); + path = Profile; + sourceTree = ""; + }; + AA9D3556BF0D5914D341DA26 /* Project */ = { + isa = PBXGroup; + children = ( + E4BC1BD7D39331BC72355666 /* Derived */, + 6883B25D0D519884DF1060AB /* Shared */, + 0F62DEECBFA6B482A490C188 /* Sources */, + ); + name = Project; + sourceTree = ""; + }; + AC7918DF414EAC42574C43C8 /* Common */ = { + isa = PBXGroup; + children = ( + 5582AA34439F4532105E68D4 /* Component */, + 83E8FBE8B634CD815D40C928 /* NavigationBarConfigurator.swift */, + D51ADB239DCB3639943C6EE7 /* TodoDetailContentView.swift */, + 19FC36435309F9D84B455253 /* TodoInfoSheetView.swift */, + 9F3BBD8DF91AE3A8B7FAC599 /* TodoMarkdownContentView.swift */, + 77A2025370CB07568F045A6E /* WebView.swift */, + ); + path = Common; + sourceTree = ""; + }; + B94A7F98803FFD2D526DC3F0 /* Products */ = { + isa = PBXGroup; + children = ( + D26E37F394F95F6AA0B184A4 /* DevLogPresentation.framework */, + CA0F9AEA78082777BD930922 /* DevLogUI.framework */, + ); + name = Products; + sourceTree = ""; + }; + BCA2DFAF282AC5461CF72C04 /* Setting */ = { + isa = PBXGroup; + children = ( + 56823A0901F960041578908A /* AccountView.swift */, + C41C9CD1A01AFBD1B64281D2 /* PushNotificationSettingsView.swift */, + E2EB00F69C800B922FF8A48A /* SettingView.swift */, + A44E5A8322D9ADC2D2709471 /* ThemeView.swift */, + ); + path = Setting; + sourceTree = ""; + }; + C47B5B4ADB099CAA5E1E6730 /* Home */ = { + isa = PBXGroup; + children = ( + A8D9416BB473F30DCCD7E859 /* HomeView.swift */, + ); + path = Home; + sourceTree = ""; + }; + CBE61554E7CA53C42DEA3473 /* PushNotification */ = { + isa = PBXGroup; + children = ( + BD11529C090F3011129AC4A3 /* PushNotificationListView.swift */, + ); + path = PushNotification; + sourceTree = ""; + }; + E2476D845591F375F0AB695C /* Today */ = { + isa = PBXGroup; + children = ( + D5F2B7063B902FE6BD1DAD25 /* TodayView.swift */, + ); + path = Today; + sourceTree = ""; + }; + E30D4244433A5F1D744A152C /* Home */ = { + isa = PBXGroup; + children = ( + C47B5B4ADB099CAA5E1E6730 /* Home */, + 9CBD74F72172BA31A47E1961 /* TodoDetailView.swift */, + F6E155E338E408858E973C7C /* TodoEditorView.swift */, + 508B6C083CF1FB1B18A7A7C0 /* TodoListView.swift */, + 5AF9DFAB631D9D4BFE8D5891 /* TodoManageView.swift */, + ); + path = Home; + sourceTree = ""; + }; + E4BC1BD7D39331BC72355666 /* Derived */ = { + isa = PBXGroup; + children = ( + F1D1E807CD22F002CA87CBD0 /* InfoPlists */, + ); + path = Derived; + sourceTree = ""; + }; + F1D1E807CD22F002CA87CBD0 /* InfoPlists */ = { + isa = PBXGroup; + children = ( + 1F083216D01A83A4386A1258 /* DevLogUI-Info.plist */, + ); + path = InfoPlists; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + AE12CA663131269C6EAB64F6 /* DevLogUI */ = { + isa = PBXNativeTarget; + buildConfigurationList = B87B2F8C687DAEE31621C1FD /* Build configuration list for PBXNativeTarget "DevLogUI" */; + buildPhases = ( + 6D6CD97FC849787DAD728B74 /* Sources */, + 4183F2CD6DE0FA9F29BF0EB7 /* Resources */, + FE93059CE51F086DC6395122 /* Frameworks */, + 1E92F96D37C3D41CAC9C29AF /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 3E13A9270FB03C78A0CE8011 /* PBXTargetDependency */, + ); + name = DevLogUI; + packageProductDependencies = ( + 7A26AD882B24E0CD5F4DEC5C /* MarkdownUI */, + CCFA0DE9FF601686A0FFA868 /* OrderedCollections */, + ); + productName = DevLogUI; + productReference = CA0F9AEA78082777BD930922 /* DevLogUI.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4766CAAF698AB49836766AC8 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 2650; + TargetAttributes = { + }; + }; + buildConfigurationList = 4B3A402E29F80157ACDEB612 /* Build configuration list for PBXProject "DevLogUI" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 25EB81C4CCB2507411589B48; + packageReferences = ( + 44402A3549052498AEA6F35E /* XCRemoteSwiftPackageReference "swift-collections" */, + 6FBE97EF929D461E04729183 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */, + 39308EE445B3D9740715053D /* XCRemoteSwiftPackageReference "SwiftLint" */, + ); + productRefGroup = B94A7F98803FFD2D526DC3F0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + AE12CA663131269C6EAB64F6 /* DevLogUI */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4183F2CD6DE0FA9F29BF0EB7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6D6CD97FC849787DAD728B74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F194D9E0C40F9C8D0BBFD81 /* CacheableImage.swift in Sources */, + AD69309B3A8854AC0C659DFF /* CheckBox.swift in Sources */, + E1F211A3100CD23E688CFEAD /* LoadingView.swift in Sources */, + B32465C08D91FC006E5CF3D2 /* LoginButton.swift in Sources */, + 62DB113F0728D6B2A24D4ECA /* RelativeTimeText.swift in Sources */, + EC510917A2262FEE5842FADD /* Tags.swift in Sources */, + E4AFAE6984B3251648B09C49 /* Toast.swift in Sources */, + 3BC362E7B3729B9B766D0E82 /* TodoItemRow.swift in Sources */, + AF285B7139AEDA9D38AF387F /* ToolbarButtons.swift in Sources */, + CD5C10D07CBA3369F4BE94D5 /* UIKitTextEditor.swift in Sources */, + 07DC30D6EE53D3FEB18D4560 /* WebItemRow.swift in Sources */, + EE11A7B71A16E9A205B163D1 /* NavigationBarConfigurator.swift in Sources */, + F0AA0AF4F10C13242BBD4025 /* TodoDetailContentView.swift in Sources */, + 436190F41C9108F6D4936027 /* TodoInfoSheetView.swift in Sources */, + FBAFCE11F1766FBFBB24807C /* TodoMarkdownContentView.swift in Sources */, + B440FE5BC83625806D5137DC /* WebView.swift in Sources */, + 7856BF83CB7D2D0F7B4774CF /* EnvironmentValues+.swift in Sources */, + 4726811A94C0478F5A807A02 /* View+.swift in Sources */, + 76DBAFDBB18F6EC9ABACFC2D /* HomeView.swift in Sources */, + E20A6D6F2126952F83EF28AD /* TodoDetailView.swift in Sources */, + 9FC8F731D0C5F71AE08884ED /* TodoEditorView.swift in Sources */, + 6878F8DBE4009B0462BFCAB4 /* TodoListView.swift in Sources */, + 823A5A6BA41BCA257AD3586D /* TodoManageView.swift in Sources */, + 9E96551C79A75284146EC61D /* LoginView.swift in Sources */, + 534E2A2C85E646406895773D /* MainView.swift in Sources */, + 62A8F2367EF38AD98E4C4539 /* HeatmapView.swift in Sources */, + 69E94B7AD0D2AF37B418A8F4 /* ProfileView.swift in Sources */, + 3CD4C5F7BA6AE10FD96EED2D /* PushNotificationListView.swift in Sources */, + E18A468C5AC5A60C18CF7A99 /* SearchView.swift in Sources */, + 87FF186B7907E7F1B2DE5E60 /* AccountView.swift in Sources */, + 81BC04E40F6CED522AF09D8F /* PushNotificationSettingsView.swift in Sources */, + 7DE3B4F05C4BEEF05B58FCF5 /* SettingView.swift in Sources */, + 76DFE29F22D4336EE4C36B73 /* ThemeView.swift in Sources */, + BF37121E20F7AE5443957E16 /* TodayView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3E13A9270FB03C78A0CE8011 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = AA737E3F8BA86338D8508844 /* SwiftLintBuildToolPlugin */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 791C4AC0851482878752E469 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52512F0A61A001595E088847 /* Version.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 4CPC6N38WA; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_KEY_CFBundleShortVersionString = "$(MARKETING_VERSION)"; + INFOPLIST_KEY_CFBundleVersion = "$(CURRENT_PROJECT_VERSION)"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8462DF0BADC3222ED4E4A89B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52512F0A61A001595E088847 /* Version.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Derived/InfoPlists/DevLogUI-Info.plist"; + INFOPLIST_KEY_CFBundleShortVersionString = "$(MARKETING_VERSION)"; + INFOPLIST_KEY_CFBundleVersion = "$(CURRENT_PROJECT_VERSION)"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-L$(DT_TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.opfic.DevLog.DevLogUI; + PRODUCT_NAME = DevLogUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 84C2AC99DFE2402189CE2500 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52512F0A61A001595E088847 /* Version.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 4CPC6N38WA; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_KEY_CFBundleShortVersionString = "$(MARKETING_VERSION)"; + INFOPLIST_KEY_CFBundleVersion = "$(CURRENT_PROJECT_VERSION)"; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E6C58351FF08829E9E26F1D2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52512F0A61A001595E088847 /* Version.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Derived/InfoPlists/DevLogUI-Info.plist"; + INFOPLIST_KEY_CFBundleShortVersionString = "$(MARKETING_VERSION)"; + INFOPLIST_KEY_CFBundleVersion = "$(CURRENT_PROJECT_VERSION)"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-L$(DT_TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.opfic.DevLog.DevLogUI; + PRODUCT_NAME = DevLogUI; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + DEBUG, + ); + SWIFT_COMPILATION_MODE = singlefile; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4B3A402E29F80157ACDEB612 /* Build configuration list for PBXProject "DevLogUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 84C2AC99DFE2402189CE2500 /* Debug */, + 791C4AC0851482878752E469 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B87B2F8C687DAEE31621C1FD /* Build configuration list for PBXNativeTarget "DevLogUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E6C58351FF08829E9E26F1D2 /* Debug */, + 8462DF0BADC3222ED4E4A89B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 39308EE445B3D9740715053D /* XCRemoteSwiftPackageReference "SwiftLint" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/realm/SwiftLint"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.62.1; + }; + }; + 44402A3549052498AEA6F35E /* XCRemoteSwiftPackageReference "swift-collections" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-collections.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.3.0; + }; + }; + 6FBE97EF929D461E04729183 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/gonzalezreal/swift-markdown-ui.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.4.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 7A26AD882B24E0CD5F4DEC5C /* MarkdownUI */ = { + isa = XCSwiftPackageProductDependency; + productName = MarkdownUI; + }; + AA737E3F8BA86338D8508844 /* SwiftLintBuildToolPlugin */ = { + isa = XCSwiftPackageProductDependency; + productName = "plugin:SwiftLintBuildToolPlugin"; + }; + CCFA0DE9FF601686A0FFA868 /* OrderedCollections */ = { + isa = XCSwiftPackageProductDependency; + productName = OrderedCollections; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 4766CAAF698AB49836766AC8 /* Project object */; +} diff --git a/Application/DevLogUI/DevLogUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Application/DevLogUI/DevLogUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/Application/DevLogUI/DevLogUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Application/DevLogUI/DevLogUI.xcodeproj/xcshareddata/xcschemes/DevLogUI.xcscheme b/Application/DevLogUI/DevLogUI.xcodeproj/xcshareddata/xcschemes/DevLogUI.xcscheme new file mode 100644 index 00000000..732553b2 --- /dev/null +++ b/Application/DevLogUI/DevLogUI.xcodeproj/xcshareddata/xcschemes/DevLogUI.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Application/DevLogUI/Project.swift b/Application/DevLogUI/Project.swift new file mode 100644 index 00000000..6691decc --- /dev/null +++ b/Application/DevLogUI/Project.swift @@ -0,0 +1,13 @@ +import ProjectDescription +import ProjectDescriptionHelpers + +let project = Project.devlogFramework( + name: "DevLogUI", + bundleId: "com.opfic.DevLog.DevLogUI", + versionXcconfigPath: "../Shared/Version.xcconfig", + packages: DevLogPackages.presentationPackages, + dependencies: [ + .project(target: "DevLogPresentation", path: "../DevLogPresentation"), + ] + DevLogPackages.presentationPackageDependencies, + hasTests: false +) diff --git a/Application/DevLogUI/Sources/.swiftlint.yml b/Application/DevLogUI/Sources/.swiftlint.yml new file mode 100644 index 00000000..1242ffca --- /dev/null +++ b/Application/DevLogUI/Sources/.swiftlint.yml @@ -0,0 +1 @@ +parent_config: ../../../.swiftlint.yml diff --git a/DevLog.xcworkspace/contents.xcworkspacedata b/DevLog.xcworkspace/contents.xcworkspacedata index 3f7e3c4b..506c34f3 100644 --- a/DevLog.xcworkspace/contents.xcworkspacedata +++ b/DevLog.xcworkspace/contents.xcworkspacedata @@ -25,6 +25,9 @@ + + Date: Tue, 2 Jun 2026 10:34:43 +0900 Subject: [PATCH 03/10] =?UTF-8?q?refactor:=20Presentation=20=EA=B2=BD?= =?UTF-8?q?=EA=B3=84=20API=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Common/LoadingState.swift | 2 +- .../Home/HomeViewCoordinator.swift | 18 ++-- .../Home/TodoWindowCoordinator.swift | 10 +-- .../Main/MainViewCoordinator.swift | 6 +- .../Profile/ProfileViewCoordinator.swift | 18 ++-- .../PushNotificationListViewCoordinator.swift | 12 +-- .../Today/TodayViewCoordinator.swift | 10 +-- .../Dependency/MainViewDependencies.swift | 29 +++++++ .../Dependency/RootViewDependencies.swift | 38 ++++++++ .../TodoEditorWindowDependencies.swift | 47 ++++++++++ .../Dependency/TodoViewModelFactory.swift | 57 ++++++++++++ .../Sources/Extension/Color+Hex.swift | 3 +- .../Sources/Extension/Error+SocialLogin.swift | 2 +- .../Sources/Protocol/Store.swift | 2 +- .../Sources/Routing/HomeRoute.swift | 14 +++ .../Sources/Routing/NavigationRouter.swift | 14 +-- .../Sources/Routing/ProfileRoute.swift | 16 ++++ .../Sources/Routing/TodayRoute.swift | 12 +++ .../Structure/Profile/ActivityKindItem.swift | 8 +- .../Structure/PushNotificationItem.swift | 2 +- .../Todo/SystemTodoCategoryItem.swift | 2 +- .../Structure/Todo/TodoCategoryItem.swift | 4 +- .../Sources/Structure/Todo/TodoIdItem.swift | 4 + .../Structure/Todo/TodoReferenceItem.swift | 2 +- .../Structure/Todo/UserTodoCategoryItem.swift | 2 +- .../Sources/Structure/WebPageItem.swift | 2 +- .../ViewModel/Home/HomeViewModel.swift | 70 +++++++-------- .../ViewModel/Home/TodoDetailViewModel.swift | 38 ++++---- .../ViewModel/Home/TodoEditorViewModel.swift | 68 +++++++-------- .../ViewModel/Home/TodoListViewModel.swift | 60 +++++++------ .../ViewModel/Home/TodoManageViewModel.swift | 34 ++++---- .../ViewModel/Login/LoginViewModel.swift | 28 +++--- .../ViewModel/Main/MainViewModel.swift | 24 ++--- .../ViewModel/Profile/ProfileViewModel.swift | 87 ++++++++++++------- .../PushNotificationListViewModel.swift | 48 +++++----- .../ViewModel/Root/RootViewModel.swift | 28 +++--- .../ViewModel/Search/SearchViewModel.swift | 40 ++++----- .../ViewModel/Setting/AccountViewModel.swift | 50 ++++++----- .../PushNotificationSettingsViewModel.swift | 42 ++++----- .../ViewModel/Setting/SettingViewModel.swift | 42 ++++----- .../ViewModel/Today/TodayViewModel.swift | 63 +++++++------- .../Window/TodoEditorWindowEvent.swift | 4 +- .../Window/TodoEditorWindowValue.swift | 20 ++--- 43 files changed, 673 insertions(+), 409 deletions(-) create mode 100644 Application/DevLogPresentation/Sources/Dependency/MainViewDependencies.swift create mode 100644 Application/DevLogPresentation/Sources/Dependency/RootViewDependencies.swift create mode 100644 Application/DevLogPresentation/Sources/Dependency/TodoEditorWindowDependencies.swift create mode 100644 Application/DevLogPresentation/Sources/Dependency/TodoViewModelFactory.swift create mode 100644 Application/DevLogPresentation/Sources/Routing/HomeRoute.swift create mode 100644 Application/DevLogPresentation/Sources/Routing/ProfileRoute.swift create mode 100644 Application/DevLogPresentation/Sources/Routing/TodayRoute.swift diff --git a/Application/DevLogPresentation/Sources/Common/LoadingState.swift b/Application/DevLogPresentation/Sources/Common/LoadingState.swift index 00aca6c5..4ce62b60 100644 --- a/Application/DevLogPresentation/Sources/Common/LoadingState.swift +++ b/Application/DevLogPresentation/Sources/Common/LoadingState.swift @@ -26,7 +26,7 @@ public final class LoadingState { private var visibleDelayedTargets = Set() private var visibleTargets = Set() - init(delay: Duration = .seconds(0.3)) { + public init(delay: Duration = .seconds(0.3)) { self.delay = delay } diff --git a/Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift index fbbc9410..7ef19f7c 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/Home/HomeViewCoordinator.swift @@ -12,14 +12,14 @@ import DevLogDomain @MainActor @Observable -final class HomeViewCoordinator { - let viewModel: HomeViewModel - let router = NavigationRouter() +public final class HomeViewCoordinator { + public let viewModel: HomeViewModel + public let router = NavigationRouter() private let container: DIContainer @ObservationIgnored private var cancellable: AnyCancellable? - init(container: DIContainer) { + public init(container: DIContainer) { self.container = container self.viewModel = HomeViewModel( fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), @@ -34,11 +34,11 @@ final class HomeViewCoordinator { ) } - func fetchData() { + public func fetchData() { viewModel.send(.fetchData) } - func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) { + public func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) { guard cancellable == nil else { return } cancellable = windowEvent.submits @@ -48,11 +48,11 @@ final class HomeViewCoordinator { } } - func makeTodoManageViewModel() -> TodoManageViewModel { + public func makeTodoManageViewModel() -> TodoManageViewModel { TodoManageViewModel(viewModel.state.preferences) } - func makeTodoEditorViewModel(category: TodoCategory) -> TodoEditorViewModel { + public func makeTodoEditorViewModel(category: TodoCategory) -> TodoEditorViewModel { TodoEditorViewModel( category: category, fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), @@ -66,7 +66,7 @@ final class HomeViewCoordinator { ) } - func makeSearchViewModel() -> SearchViewModel { + public func makeSearchViewModel() -> SearchViewModel { SearchViewModel( fetchWebPagesUseCase: container.resolve(FetchWebPagesUseCase.self), fetchTodosUseCase: container.resolve(FetchTodosUseCase.self), diff --git a/Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift index 525daf60..55b638ac 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/Home/TodoWindowCoordinator.swift @@ -12,7 +12,7 @@ import DevLogDomain @MainActor @Observable -final class TodoWindowCoordinator { +public final class TodoWindowCoordinator { private let container: DIContainer @ObservationIgnored private var listViewModel: TodoListViewModel? @@ -21,11 +21,11 @@ final class TodoWindowCoordinator { @ObservationIgnored private var cancellable: AnyCancellable? - init(container: DIContainer) { + public init(container: DIContainer) { self.container = container } - func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) { + public func bindWindowEvent(_ windowEvent: TodoEditorWindowEvent) { guard cancellable == nil else { return } cancellable = windowEvent.submits @@ -34,7 +34,7 @@ final class TodoWindowCoordinator { } } - func makeListViewModel(category: TodoCategory) -> TodoListViewModel { + public func makeListViewModel(category: TodoCategory) -> TodoListViewModel { if let listViewModel, listViewModel.category == category { return listViewModel @@ -53,7 +53,7 @@ final class TodoWindowCoordinator { return listViewModel } - func makeDetailViewModel( + public func makeDetailViewModel( todoId: String, showEditButton: Bool = true ) -> TodoDetailViewModel { diff --git a/Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift index 825265f8..28911670 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/Main/MainViewCoordinator.swift @@ -11,10 +11,10 @@ import DevLogDomain @MainActor @Observable -final class MainViewCoordinator { - let viewModel: MainViewModel +public final class MainViewCoordinator { + public let viewModel: MainViewModel - init(container: DIContainer) { + public init(container: DIContainer) { self.viewModel = MainViewModel( trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), unreadPushCountUseCase: container.resolve(ObserveUnreadPushCountUseCase.self) diff --git a/Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift index 2a90f684..28b0180d 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/Profile/ProfileViewCoordinator.swift @@ -11,13 +11,13 @@ import DevLogDomain @MainActor @Observable -final class ProfileViewCoordinator { - let viewModel: ProfileViewModel - let settingViewModel: SettingViewModel - var router = NavigationRouter() +public final class ProfileViewCoordinator { + public let viewModel: ProfileViewModel + public let settingViewModel: SettingViewModel + public var router = NavigationRouter() private let container: DIContainer - init(container: DIContainer) { + public init(container: DIContainer) { self.container = container self.viewModel = ProfileViewModel( fetchUserDataUseCase: container.resolve(FetchUserDataUseCase.self), @@ -38,11 +38,11 @@ final class ProfileViewCoordinator { ) } - func fetchData() { + public func fetchData() { viewModel.send(.fetchData) } - func makeAccountViewModel() -> AccountViewModel { + public func makeAccountViewModel() -> AccountViewModel { AccountViewModel( fetchProvidersUseCase: container.resolve(FetchAuthProvidersUseCase.self), linkProviderUseCase: container.resolve(LinkAuthProviderUseCase.self), @@ -50,14 +50,14 @@ final class ProfileViewCoordinator { ) } - func makePushNotificationSettingsViewModel() -> PushNotificationSettingsViewModel { + public func makePushNotificationSettingsViewModel() -> PushNotificationSettingsViewModel { PushNotificationSettingsViewModel( fetchPushSettingsUseCase: container.resolve(FetchPushSettingsUseCase.self), updatePushSettingsUseCase: container.resolve(UpdatePushSettingsUseCase.self) ) } - func makeTodoDetailViewModel(todoId: String) -> TodoDetailViewModel { + public func makeTodoDetailViewModel(todoId: String) -> TodoDetailViewModel { TodoDetailViewModel( fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), diff --git a/Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift index 23b9bee8..c5830a64 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/PushNotification/PushNotificationListViewCoordinator.swift @@ -11,14 +11,14 @@ import DevLogDomain @MainActor @Observable -final class PushNotificationListViewCoordinator { - let viewModel: PushNotificationListViewModel - var todoIdToPresent: TodoIdItem? +public final class PushNotificationListViewCoordinator { + public let viewModel: PushNotificationListViewModel + public var todoIdToPresent: TodoIdItem? private let container: DIContainer @ObservationIgnored private var todoDetailViewModel: TodoDetailViewModel? - init(container: DIContainer) { + public init(container: DIContainer) { self.container = container self.viewModel = PushNotificationListViewModel( fetchUseCase: container.resolve(FetchPushNotificationsUseCase.self), @@ -30,11 +30,11 @@ final class PushNotificationListViewCoordinator { ) } - func fetchData() { + public func fetchData() { viewModel.send(.fetchNotifications) } - func makeTodoDetailViewModel(todoId: String) -> TodoDetailViewModel { + public func makeTodoDetailViewModel(todoId: String) -> TodoDetailViewModel { if let todoDetailViewModel, todoDetailViewModel.todoId == todoId, !todoDetailViewModel.showEditButton { diff --git a/Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift b/Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift index 22b052bf..e16aeb87 100644 --- a/Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Coordinator/Today/TodayViewCoordinator.swift @@ -11,11 +11,11 @@ import DevLogDomain @MainActor @Observable -final class TodayViewCoordinator { - let viewModel: TodayViewModel - let router = NavigationRouter() +public final class TodayViewCoordinator { + public let viewModel: TodayViewModel + public let router = NavigationRouter() - init(container: DIContainer) { + public init(container: DIContainer) { self.viewModel = TodayViewModel( fetchTodosUseCase: container.resolve(FetchTodosUseCase.self), fetchTodoByIdUseCase: container.resolve(FetchTodoByIdUseCase.self), @@ -26,7 +26,7 @@ final class TodayViewCoordinator { ) } - func fetchData() { + public func fetchData() { viewModel.send(.fetchData) } } diff --git a/Application/DevLogPresentation/Sources/Dependency/MainViewDependencies.swift b/Application/DevLogPresentation/Sources/Dependency/MainViewDependencies.swift new file mode 100644 index 00000000..72b74be5 --- /dev/null +++ b/Application/DevLogPresentation/Sources/Dependency/MainViewDependencies.swift @@ -0,0 +1,29 @@ +// +// MainViewDependencies.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import DevLogCore + +@MainActor +public struct MainViewDependencies { + public let coordinator: MainViewCoordinator + public let todoWindowCoordinator: TodoWindowCoordinator + public let homeViewCoordinator: HomeViewCoordinator + public let todayViewCoordinator: TodayViewCoordinator + public let pushNotificationListViewCoordinator: PushNotificationListViewCoordinator + public let profileViewCoordinator: ProfileViewCoordinator + public let todoViewModelFactory: TodoViewModelFactory + + public init(container: DIContainer) { + self.coordinator = MainViewCoordinator(container: container) + self.todoWindowCoordinator = TodoWindowCoordinator(container: container) + self.homeViewCoordinator = HomeViewCoordinator(container: container) + self.todayViewCoordinator = TodayViewCoordinator(container: container) + self.pushNotificationListViewCoordinator = PushNotificationListViewCoordinator(container: container) + self.profileViewCoordinator = ProfileViewCoordinator(container: container) + self.todoViewModelFactory = TodoViewModelFactory(container: container) + } +} diff --git a/Application/DevLogPresentation/Sources/Dependency/RootViewDependencies.swift b/Application/DevLogPresentation/Sources/Dependency/RootViewDependencies.swift new file mode 100644 index 00000000..9ea13444 --- /dev/null +++ b/Application/DevLogPresentation/Sources/Dependency/RootViewDependencies.swift @@ -0,0 +1,38 @@ +// +// RootViewDependencies.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import DevLogCore +import DevLogDomain + +@MainActor +public struct RootViewDependencies { + public let viewModel: RootViewModel + public let mainViewDependencies: MainViewDependencies + public let makeLoginViewModel: () -> LoginViewModel + public let makeTodoDetailViewModel: (String) -> TodoDetailViewModel + + public init(container: DIContainer) { + self.viewModel = RootViewModel( + sessionUseCase: container.resolve(ObserveAuthSessionUseCase.self), + networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self), + systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self), + trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self) + ) + self.mainViewDependencies = MainViewDependencies(container: container) + self.makeLoginViewModel = { + LoginViewModel(signInUseCase: container.resolve(SignInUseCase.self)) + } + self.makeTodoDetailViewModel = { todoId in + TodoDetailViewModel( + fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), + fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), + todoId: todoId, + showEditButton: false + ) + } + } +} diff --git a/Application/DevLogPresentation/Sources/Dependency/TodoEditorWindowDependencies.swift b/Application/DevLogPresentation/Sources/Dependency/TodoEditorWindowDependencies.swift new file mode 100644 index 00000000..919ec9f2 --- /dev/null +++ b/Application/DevLogPresentation/Sources/Dependency/TodoEditorWindowDependencies.swift @@ -0,0 +1,47 @@ +// +// TodoEditorWindowDependencies.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import DevLogCore +import DevLogDomain + +@MainActor +public struct TodoEditorWindowDependencies { + public let todoViewModelFactory: TodoViewModelFactory + private let windowEvent: TodoEditorWindowEvent + + public init( + container: DIContainer, + windowEvent: TodoEditorWindowEvent + ) { + self.todoViewModelFactory = TodoViewModelFactory(container: container) + self.windowEvent = windowEvent + } + + public func makeEditorViewModel( + value: TodoEditorWindowValue, + onClose: @escaping () -> Void + ) -> TodoEditorViewModel { + switch value { + case .create(let windowCategory, _): + return todoViewModelFactory.makeEditorViewModel( + category: windowCategory.todoCategory, + onUpsertSuccess: { todo in + windowEvent.submit(value: value, todo: todo) + onClose() + } + ) + case .edit(let windowTodo): + return todoViewModelFactory.makeEditorViewModel( + todo: windowTodo.todo, + onUpsertSuccess: { todo in + windowEvent.submit(value: value, todo: todo) + onClose() + } + ) + } + } +} diff --git a/Application/DevLogPresentation/Sources/Dependency/TodoViewModelFactory.swift b/Application/DevLogPresentation/Sources/Dependency/TodoViewModelFactory.swift new file mode 100644 index 00000000..fa00d82b --- /dev/null +++ b/Application/DevLogPresentation/Sources/Dependency/TodoViewModelFactory.swift @@ -0,0 +1,57 @@ +// +// TodoViewModelFactory.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import DevLogCore +import DevLogDomain + +@MainActor +public struct TodoViewModelFactory { + private let container: DIContainer + + public init(container: DIContainer) { + self.container = container + } + + public func makeDetailViewModel( + todoId: String, + showEditButton: Bool = true + ) -> TodoDetailViewModel { + TodoDetailViewModel( + fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), + fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), + todoId: todoId, + showEditButton: showEditButton + ) + } + + public func makeEditorViewModel( + category: TodoCategory, + onUpsertSuccess: ((Todo) -> Void)? = nil + ) -> TodoEditorViewModel { + TodoEditorViewModel( + category: category, + fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), + fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), + upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), + trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), + onUpsertSuccess: onUpsertSuccess + ) + } + + public func makeEditorViewModel( + todo: Todo, + onUpsertSuccess: ((Todo) -> Void)? = nil + ) -> TodoEditorViewModel { + TodoEditorViewModel( + todo: todo, + fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), + fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), + upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), + onUpsertSuccess: onUpsertSuccess + ) + } +} diff --git a/Application/DevLogPresentation/Sources/Extension/Color+Hex.swift b/Application/DevLogPresentation/Sources/Extension/Color+Hex.swift index 43f2b88d..12c91e48 100644 --- a/Application/DevLogPresentation/Sources/Extension/Color+Hex.swift +++ b/Application/DevLogPresentation/Sources/Extension/Color+Hex.swift @@ -6,9 +6,8 @@ // import SwiftUI -import DevLogDomain -extension Color { +public extension Color { static var randomValue: Color { Color( red: Double(Int.random(in: 0...255)) / 255, diff --git a/Application/DevLogPresentation/Sources/Extension/Error+SocialLogin.swift b/Application/DevLogPresentation/Sources/Extension/Error+SocialLogin.swift index a6d061bf..8f24bf52 100644 --- a/Application/DevLogPresentation/Sources/Extension/Error+SocialLogin.swift +++ b/Application/DevLogPresentation/Sources/Extension/Error+SocialLogin.swift @@ -8,7 +8,7 @@ import AuthenticationServices import Foundation -extension Error { +public extension Error { var isSocialLoginCancelled: Bool { switch self { case let authError as ASAuthorizationError: diff --git a/Application/DevLogPresentation/Sources/Protocol/Store.swift b/Application/DevLogPresentation/Sources/Protocol/Store.swift index b99e183a..da7e27fc 100644 --- a/Application/DevLogPresentation/Sources/Protocol/Store.swift +++ b/Application/DevLogPresentation/Sources/Protocol/Store.swift @@ -20,7 +20,7 @@ public protocol Store: AnyObject { func run(_ effect: SideEffect) } -extension Store { +public extension Store { func send(_ action: Action) { let sideEffects = reduce(with: action) sideEffects.forEach(run) diff --git a/Application/DevLogPresentation/Sources/Routing/HomeRoute.swift b/Application/DevLogPresentation/Sources/Routing/HomeRoute.swift new file mode 100644 index 00000000..b36aa0d8 --- /dev/null +++ b/Application/DevLogPresentation/Sources/Routing/HomeRoute.swift @@ -0,0 +1,14 @@ +// +// HomeRoute.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import Foundation + +public enum HomeRoute: Hashable { + case category(TodoCategoryItem) + case todo(TodoIdItem) + case webPage(WebPageItem) +} diff --git a/Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift b/Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift index ce420e9f..a26fb296 100644 --- a/Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift +++ b/Application/DevLogPresentation/Sources/Routing/NavigationRouter.swift @@ -9,14 +9,16 @@ import SwiftUI import DevLogDomain @Observable -final class NavigationRouter { - var path: [Route] = [] +public final class NavigationRouter { + public var path: [Route] = [] - var root: Route? { + public init() { } + + public var root: Route? { path.first } - var detailPath: [Route] { + public var detailPath: [Route] { get { Array(path.dropFirst()) } @@ -29,11 +31,11 @@ final class NavigationRouter { } } - func replace(with route: Route) { + public func replace(with route: Route) { path = [route] } - func push(_ route: Route) { + public func push(_ route: Route) { path.append(route) } } diff --git a/Application/DevLogPresentation/Sources/Routing/ProfileRoute.swift b/Application/DevLogPresentation/Sources/Routing/ProfileRoute.swift new file mode 100644 index 00000000..e57b4c95 --- /dev/null +++ b/Application/DevLogPresentation/Sources/Routing/ProfileRoute.swift @@ -0,0 +1,16 @@ +// +// ProfileRoute.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import Foundation + +public enum ProfileRoute: Hashable { + case settings + case activity(String) + case theme + case pushNotification + case account +} diff --git a/Application/DevLogPresentation/Sources/Routing/TodayRoute.swift b/Application/DevLogPresentation/Sources/Routing/TodayRoute.swift new file mode 100644 index 00000000..bbe34f7a --- /dev/null +++ b/Application/DevLogPresentation/Sources/Routing/TodayRoute.swift @@ -0,0 +1,12 @@ +// +// TodayRoute.swift +// DevLogPresentation +// +// Created by opfic on 6/2/26. +// + +import Foundation + +public enum TodayRoute: Hashable { + case todo(TodoIdItem) +} diff --git a/Application/DevLogPresentation/Sources/Structure/Profile/ActivityKindItem.swift b/Application/DevLogPresentation/Sources/Structure/Profile/ActivityKindItem.swift index b5311bf2..347b525d 100644 --- a/Application/DevLogPresentation/Sources/Structure/Profile/ActivityKindItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Profile/ActivityKindItem.swift @@ -11,12 +11,16 @@ import DevLogCore public struct ActivityKindItem: Identifiable, Hashable { private let activityKind: ActivityKind - init(from activityKind: ActivityKind) { + public init(from activityKind: ActivityKind) { self.activityKind = activityKind } + public static let created = ActivityKindItem(from: .created) + public static let completed = ActivityKindItem(from: .completed) + public static let deleted = ActivityKindItem(from: .deleted) + public static var selectableItems: [ActivityKindItem] {[ - .init(from: .created), .init(from: .completed), .init(from: .deleted) ] + .created, .completed, .deleted ] } public var id: String { activityKind.rawValue } diff --git a/Application/DevLogPresentation/Sources/Structure/PushNotificationItem.swift b/Application/DevLogPresentation/Sources/Structure/PushNotificationItem.swift index 9bfe900f..547277e5 100644 --- a/Application/DevLogPresentation/Sources/Structure/PushNotificationItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/PushNotificationItem.swift @@ -18,7 +18,7 @@ public struct PushNotificationItem: Identifiable, Hashable { public let todoId: String public let todoCategory: TodoCategory - init(from notification: PushNotification) { + public init(from notification: PushNotification) { self.id = notification.id self.title = notification.title self.body = notification.body diff --git a/Application/DevLogPresentation/Sources/Structure/Todo/SystemTodoCategoryItem.swift b/Application/DevLogPresentation/Sources/Structure/Todo/SystemTodoCategoryItem.swift index a83b50f3..f6bfeefc 100644 --- a/Application/DevLogPresentation/Sources/Structure/Todo/SystemTodoCategoryItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Todo/SystemTodoCategoryItem.swift @@ -11,7 +11,7 @@ import DevLogDomain public struct SystemTodoCategoryItem: Identifiable, Hashable { public let systemTodoCategory: SystemTodoCategory - init(from systemTodoCategory: SystemTodoCategory) { + public init(from systemTodoCategory: SystemTodoCategory) { self.systemTodoCategory = systemTodoCategory } diff --git a/Application/DevLogPresentation/Sources/Structure/Todo/TodoCategoryItem.swift b/Application/DevLogPresentation/Sources/Structure/Todo/TodoCategoryItem.swift index a986255f..5b2d769e 100644 --- a/Application/DevLogPresentation/Sources/Structure/Todo/TodoCategoryItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Todo/TodoCategoryItem.swift @@ -12,12 +12,12 @@ public struct TodoCategoryItem: Identifiable, Hashable { public var category: TodoCategory public var isVisible: Bool - init(from preference: TodoCategoryPreference) { + public init(from preference: TodoCategoryPreference) { self.category = preference.category self.isVisible = preference.isVisible } - init( + public init( from category: TodoCategory, isVisible: Bool = true ) { diff --git a/Application/DevLogPresentation/Sources/Structure/Todo/TodoIdItem.swift b/Application/DevLogPresentation/Sources/Structure/Todo/TodoIdItem.swift index 1e3d0ea8..cdcf5ac7 100644 --- a/Application/DevLogPresentation/Sources/Structure/Todo/TodoIdItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Todo/TodoIdItem.swift @@ -10,4 +10,8 @@ import DevLogDomain public struct TodoIdItem: Identifiable, Hashable { public let id: String + + public init(id: String) { + self.id = id + } } diff --git a/Application/DevLogPresentation/Sources/Structure/Todo/TodoReferenceItem.swift b/Application/DevLogPresentation/Sources/Structure/Todo/TodoReferenceItem.swift index a6e396f3..928763fd 100644 --- a/Application/DevLogPresentation/Sources/Structure/Todo/TodoReferenceItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Todo/TodoReferenceItem.swift @@ -13,7 +13,7 @@ public struct TodoReferenceItem: Equatable { public let title: String public let category: TodoCategoryItem - init(from todoReference: TodoReference) { + public init(from todoReference: TodoReference) { self.id = todoReference.id self.title = todoReference.title self.category = TodoCategoryItem(from: todoReference.category) diff --git a/Application/DevLogPresentation/Sources/Structure/Todo/UserTodoCategoryItem.swift b/Application/DevLogPresentation/Sources/Structure/Todo/UserTodoCategoryItem.swift index 517189cd..e0aa2fcf 100644 --- a/Application/DevLogPresentation/Sources/Structure/Todo/UserTodoCategoryItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/Todo/UserTodoCategoryItem.swift @@ -11,7 +11,7 @@ import DevLogDomain public struct UserTodoCategoryItem: Identifiable, Hashable { public let userTodoCategory: UserTodoCategory - init(from userTodoCategory: UserTodoCategory) { + public init(from userTodoCategory: UserTodoCategory) { self.userTodoCategory = userTodoCategory } diff --git a/Application/DevLogPresentation/Sources/Structure/WebPageItem.swift b/Application/DevLogPresentation/Sources/Structure/WebPageItem.swift index 666d1aaf..6c797401 100644 --- a/Application/DevLogPresentation/Sources/Structure/WebPageItem.swift +++ b/Application/DevLogPresentation/Sources/Structure/WebPageItem.swift @@ -12,7 +12,7 @@ public struct WebPageItem: Identifiable, Hashable { private let metadata: WebPage public var isHidden = false - init(from metadata: WebPage) { + public init(from metadata: WebPage) { self.metadata = metadata } diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift index 1fa8b7ce..bd8291c6 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift @@ -11,33 +11,33 @@ import DevLogCore import DevLogDomain @Observable -final class HomeViewModel: Store { - struct State: Equatable { - var preferences: [TodoCategoryItem] = [] - var recentTodos: [RecentTodoItem] = [] - var webPages: [WebPageItem] = [] - var needsWebPageRefresh = false - var isNetworkConnected: Bool = true - var showContentPicker: Bool = false - var showTodoEditor: Bool = false - var showSearchView: Bool = false - var webPageURLInput: String = "https://" - var selectedTodoCategory: TodoCategory? - var reorderTodo: Bool = false - var isPreferencesLoading: Bool = false - var isRecentTodosLoading: Bool = false - var isWebPageLoading: Bool = false - var isAppending: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertType: AlertType? - var alertMessage: String = "" - var showToast: Bool = false - var toastType: ToastType? - var toastMessage: String = "" +public final class HomeViewModel: Store { + public struct State: Equatable { + public var preferences: [TodoCategoryItem] = [] + public var recentTodos: [RecentTodoItem] = [] + public var webPages: [WebPageItem] = [] + public var needsWebPageRefresh = false + public var isNetworkConnected: Bool = true + public var showContentPicker: Bool = false + public var showTodoEditor: Bool = false + public var showSearchView: Bool = false + public var webPageURLInput: String = "https://" + public var selectedTodoCategory: TodoCategory? + public var reorderTodo: Bool = false + public var isPreferencesLoading: Bool = false + public var isRecentTodosLoading: Bool = false + public var isWebPageLoading: Bool = false + public var isAppending: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertType: AlertType? + public var alertMessage: String = "" + public var showToast: Bool = false + public var toastType: ToastType? + public var toastMessage: String = "" } - enum Action { + public enum Action { case fetchData case networkStatusChanged(Bool) case setPresentation(Presentation, Bool) @@ -58,7 +58,7 @@ final class HomeViewModel: Store { case updateWebPages([WebPageItem]) } - enum SideEffect { + public enum SideEffect { case addWebPage(String) case deleteWebPage(WebPageItem) case undoDeleteWebPage(String) @@ -69,36 +69,36 @@ final class HomeViewModel: Store { case showModalAfterDelay(ModalType) } - enum AlertType { + public enum AlertType { case webPageInput case invalidURL case error } - enum ToastType { + public enum ToastType { case deleteWebPage } - enum ModalType { + public enum ModalType { case todoEditor case urlInputAlert } - enum Presentation { + public enum Presentation { case reorderTodo case todoEditor case contentPicker case searchView } - enum LoadingTarget: Hashable { + public enum LoadingTarget: Hashable { case preferences case recentTodos case webPage case overlay } - private(set) var state = State() + public private(set) var state = State() private let fetchPreferencesUseCase: FetchTodoCategoryPreferencesUseCase private let updatePreferencesUseCase: UpdateTodoCategoryPreferencesUseCase private let addWebPageUseCase: AddWebPageUseCase @@ -112,7 +112,7 @@ final class HomeViewModel: Store { private var deletedWebPageURLString: String? private var cancellables = Set() - init( + public init( fetchPreferencesUseCase: FetchTodoCategoryPreferencesUseCase, updatePreferencesUseCase: UpdateTodoCategoryPreferencesUseCase, addWebPageUseCase: AddWebPageUseCase, @@ -136,7 +136,7 @@ final class HomeViewModel: Store { setupNetworkObserving() } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -157,7 +157,7 @@ final class HomeViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchTodoCategoryPreferences: beginLoading(for: .preferences, mode: .immediate) diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift index dc068268..b8523ca7 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift @@ -9,20 +9,20 @@ import Foundation import DevLogDomain @Observable -final class TodoDetailViewModel: Store { - struct State: Equatable { - var todo: Todo? - var selectedTodoId: TodoIdItem? - var referenceItems: [Int: TodoReferenceItem] = [:] - var isLoading: Bool = false - var showAlert: Bool = false - var showEditor: Bool = false - var showInfo: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" +public final class TodoDetailViewModel: Store { + public struct State: Equatable { + public var todo: Todo? + public var selectedTodoId: TodoIdItem? + public var referenceItems: [Int: TodoReferenceItem] = [:] + public var isLoading: Bool = false + public var showAlert: Bool = false + public var showEditor: Bool = false + public var showInfo: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" } - enum Action { + public enum Action { case onAppear case setAlert(Bool) case setShowEditor(Bool) @@ -33,19 +33,19 @@ final class TodoDetailViewModel: Store { case setLoading(Bool) } - enum SideEffect { + public enum SideEffect { case fetchTodo case resolveMarkdown(String) } - private(set) var state: State = .init() - let todoId: String - let showEditButton: Bool + public private(set) var state: State = .init() + public let todoId: String + public let showEditButton: Bool private let fetchTodoUseCase: FetchTodoByIdUseCase private let fetchReferenceItemsUseCase: FetchReferenceItemsUseCase private let loadingState = LoadingState() - init( + public init( fetchTodoUseCase: FetchTodoByIdUseCase, fetchReferenceItemsUseCase: FetchReferenceItemsUseCase, todoId: String, @@ -57,7 +57,7 @@ final class TodoDetailViewModel: Store { self.showEditButton = showEditButton } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -86,7 +86,7 @@ final class TodoDetailViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchTodo: beginLoading(.delayed) diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift index 82fac208..1c7682b2 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift @@ -10,7 +10,7 @@ import OrderedCollections import DevLogDomain @Observable -final class TodoEditorViewModel: Store { +public final class TodoEditorViewModel: Store { private struct Draft: Equatable { let isCompleted: Bool let completedAt: Date? @@ -44,36 +44,36 @@ final class TodoEditorViewModel: Store { } } - struct State: Equatable { - var isCompleted: Bool = false - var completedAt: Date? - var isPinned: Bool = false - var selectedTodoId: TodoIdItem? - var title: String = "" - var content: String = "" - var referenceItems: [Int: TodoReferenceItem] = [:] - var dueDate: Date? - var showInfo: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var isLoading: Bool = false - var tags: OrderedSet = [] - var tagText: String = "" - var focusOnEditor: Bool = false - var tabViewTag: Tag = .editor - var categories: [TodoCategoryItem] = [] - var category = TodoCategoryItem(from: .system(.etc)) - var isValidToSave: Bool { + public struct State: Equatable { + public var isCompleted: Bool = false + public var completedAt: Date? + public var isPinned: Bool = false + public var selectedTodoId: TodoIdItem? + public var title: String = "" + public var content: String = "" + public var referenceItems: [Int: TodoReferenceItem] = [:] + public var dueDate: Date? + public var showInfo: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var isLoading: Bool = false + public var tags: OrderedSet = [] + public var tagText: String = "" + public var focusOnEditor: Bool = false + public var tabViewTag: Tag = .editor + public var categories: [TodoCategoryItem] = [] + public var category = TodoCategoryItem(from: .system(.etc)) + public var isValidToSave: Bool { !title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty } } - enum Tag { + public enum Tag { case editor, preview } - enum Action { + public enum Action { case onAppear case addTag(String) case removeTag(String) @@ -94,13 +94,13 @@ final class TodoEditorViewModel: Store { case upsertTodo(Todo) } - enum SideEffect { + public enum SideEffect { case fetchCategories case resolveMarkdown(String) case upsertTodo(Todo) } - private(set) var state = State() + public private(set) var state = State() private let calendar = Calendar.current private let fetchPreferencesUseCase: FetchTodoCategoryPreferencesUseCase private let fetchReferenceItemsUseCase: FetchReferenceItemsUseCase @@ -115,7 +115,7 @@ final class TodoEditorViewModel: Store { private let deletedAt: Date? private let originalDraft: Draft? - var navigationTitle: String { + public var navigationTitle: String { if originalDraft == nil { return String.localizedStringWithFormat( String(localized: "todo_editor_new_format"), @@ -126,17 +126,17 @@ final class TodoEditorViewModel: Store { return String(localized: "todo_edit") } - var hasChanges: Bool { + public var hasChanges: Bool { guard let originalDraft else { return true } return originalDraft != Draft(state: state) } - var isReadyToSubmit: Bool { + public var isReadyToSubmit: Bool { state.isValidToSave && hasChanges } // 새로운 Todo 생성용 생성자 - init( + public init( category: TodoCategory, fetchPreferencesUseCase: FetchTodoCategoryPreferencesUseCase, fetchReferenceItemsUseCase: FetchReferenceItemsUseCase, @@ -161,7 +161,7 @@ final class TodoEditorViewModel: Store { } // 기존 Todo 편집용 생성자 - init( + public init( todo: Todo, fetchPreferencesUseCase: FetchTodoCategoryPreferencesUseCase, fetchReferenceItemsUseCase: FetchReferenceItemsUseCase, @@ -191,7 +191,7 @@ final class TodoEditorViewModel: Store { state.category = TodoCategoryItem(from: todo.category) } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -251,7 +251,7 @@ final class TodoEditorViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchCategories: Task { @@ -294,7 +294,7 @@ final class TodoEditorViewModel: Store { } } -extension TodoEditorViewModel { +public extension TodoEditorViewModel { private func handleStringAction( _ action: Action, stringValue: String, diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift index 9467e77b..fd7778c8 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift @@ -10,25 +10,29 @@ import DevLogCore import DevLogDomain @Observable -final class TodoListViewModel: Store { - struct State: Equatable { - var todos: [TodoListItem] = [] - var searchText: String = "" - var searchResults: [TodoListItem] = [] - var showEditor: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var isSearching: Bool = false - var showAllSearchResults: Bool = false - var query: TodoQuery - var isLoading: Bool = false - var showToast: Bool = false - var toastMessage: String = "" - var hasMore: Bool = false +public final class TodoListViewModel: Store { + public typealias SortTarget = TodoQuery.SortTarget + public typealias SortOrder = TodoQuery.SortOrder + public typealias CompletionFilter = TodoQuery.CompletionFilter + + public struct State: Equatable { + public var todos: [TodoListItem] = [] + public var searchText: String = "" + public var searchResults: [TodoListItem] = [] + public var showEditor: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var isSearching: Bool = false + public var showAllSearchResults: Bool = false + public var query: TodoQuery + public var isLoading: Bool = false + public var showToast: Bool = false + public var toastMessage: String = "" + public var hasMore: Bool = false } - enum Action { + public enum Action { // User case refresh case setAlert(Bool) @@ -63,7 +67,7 @@ final class TodoListViewModel: Store { case setHasMore(Bool) } - enum SideEffect { + public enum SideEffect { case cancelSearch case debounceSearch(String) case fetch @@ -80,8 +84,8 @@ final class TodoListViewModel: Store { case request } - let category: TodoCategory - private(set) var state: State + public let category: TodoCategory + public private(set) var state: State private let fetchTodosUseCase: FetchTodosUseCase private let fetchTodoByIdUseCase: FetchTodoByIdUseCase private let upsertTodoUseCase: UpsertTodoUseCase @@ -94,7 +98,7 @@ final class TodoListViewModel: Store { private var searchTasks: [SearchTaskKind: Task] = [:] private let searchDebounceDelay: Double = 0.4 - init( + public init( fetchTodosUseCase: FetchTodosUseCase, fetchTodoByIdUseCase: FetchTodoByIdUseCase, upsertTodoUseCase: UpsertTodoUseCase, @@ -115,9 +119,9 @@ final class TodoListViewModel: Store { ) } - let searchResultsLimit = 5 + public let searchResultsLimit = 5 - var appliedFilterCount: Int { + public var appliedFilterCount: Int { var count = 0 if state.query.sortTarget != .createdAt { count += 1 } if state.query.sortOrder != .latest { count += 1 } @@ -126,7 +130,7 @@ final class TodoListViewModel: Store { return count } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -149,7 +153,7 @@ final class TodoListViewModel: Store { } // swiftlint:disable function_body_length - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .cancelSearch: cancelSearch() @@ -467,7 +471,7 @@ private extension TodoListViewModel { } } -extension TodoQuery.SortTarget { +public extension TodoQuery.SortTarget { var title: String { switch self { case .createdAt: @@ -484,7 +488,7 @@ extension TodoQuery.SortTarget { } } -extension TodoQuery.SortOrder { +public extension TodoQuery.SortOrder { var title: String { switch self { case .latest: @@ -495,7 +499,7 @@ extension TodoQuery.SortOrder { } } -extension TodoQuery.CompletionFilter { +public extension TodoQuery.CompletionFilter { var title: String { switch self { case .all: diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift index 72c30bc5..5c5ea986 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift @@ -9,15 +9,15 @@ import SwiftUI import DevLogDomain @Observable -final class TodoManageViewModel: Store { - struct State: Equatable { - var preferences: [TodoCategoryItem] - var category: TodoCategoryItem? - var showSheet: Bool = false - var showAlert: Bool = false +public final class TodoManageViewModel: Store { + public struct State: Equatable { + public var preferences: [TodoCategoryItem] + public var category: TodoCategoryItem? + public var showSheet: Bool = false + public var showAlert: Bool = false } - enum Action { + public enum Action { case tapAddUserCategory case moveItem(from: IndexSet, target: Int) case tapItem(TodoCategoryItem) @@ -32,11 +32,11 @@ final class TodoManageViewModel: Store { case saveUserCategory } - enum SideEffect { } + public enum SideEffect { } - private(set) var state: State + public private(set) var state: State - var isEditing: Bool { + public var isEditing: Bool { guard let categoryItem = state.category else { return false } @@ -44,19 +44,19 @@ final class TodoManageViewModel: Store { return state.preferences.contains { $0.id == categoryItem.id } } - var navigationTitle: String { + public var navigationTitle: String { isEditing ? String(localized: "todo_manage_edit_category_title") : String(localized: "todo_manage_add_category_title") } - var submitTitle: String { + public var submitTitle: String { isEditing ? String(localized: "todo_manage_save") : String(localized: "todo_add") } - var placeholder: String { + public var placeholder: String { guard let item = state.category, case .user(let category) = item.category @@ -67,7 +67,7 @@ final class TodoManageViewModel: Store { return category.name } - var categoryNameCountText: String { + public var categoryNameCountText: String { guard let item = state.category, case .user(let category) = item.category @@ -78,7 +78,7 @@ final class TodoManageViewModel: Store { return "\(category.name.count)/20" } - var canSubmitUserCategory: Bool { + public var canSubmitUserCategory: Bool { guard let item = state.category, case .user(let category) = item.category @@ -119,11 +119,11 @@ final class TodoManageViewModel: Store { return true } - init(_ preferences: [TodoCategoryItem]) { + public init(_ preferences: [TodoCategoryItem]) { self.state = State(preferences: preferences) } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state switch action { diff --git a/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift index dffd2361..0a82b9ca 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift @@ -9,26 +9,26 @@ import Foundation import DevLogDomain @Observable -final class LoginViewModel: Store { - struct State: Equatable { - var isLoading = false - var showAlert: Bool = false - var alertType: AlertType? - var alertTitle: String = "" - var alertMessage: String = "" +public final class LoginViewModel: Store { + public struct State: Equatable { + public var isLoading = false + public var showAlert: Bool = false + public var alertType: AlertType? + public var alertTitle: String = "" + public var alertMessage: String = "" } - enum Action { + public enum Action { case setAlert(Bool, AlertType? = nil) case tapSignInButton(AuthProvider) case setLoading(Bool) } - enum SideEffect { + public enum SideEffect { case signIn(AuthProvider) } - enum AlertType { + public enum AlertType { case emailUnavailable case error } @@ -36,15 +36,15 @@ final class LoginViewModel: Store { private let signInUseCase: SignInUseCase private let loadingState = LoadingState() - private(set) var state = State() + public private(set) var state = State() - init( + public init( signInUseCase: SignInUseCase ) { self.signInUseCase = signInUseCase } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -61,7 +61,7 @@ final class LoginViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .signIn(let authProvider): beginLoading(.immediate) diff --git a/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift index 4679faaf..eb33fe05 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift @@ -12,35 +12,35 @@ import DevLogDomain import DevLogCore @Observable -final class MainViewModel: Store { - struct State: Equatable { - var unreadPushCount = 0 - var showAlert = false - var alertTitle = "" - var alertMessage = "" +public final class MainViewModel: Store { + public struct State: Equatable { + public var unreadPushCount = 0 + public var showAlert = false + public var alertTitle = "" + public var alertMessage = "" } - enum Action { + public enum Action { case onAppear case selectedTabChanged(MainTab) case setUnreadPushCount(Int) case setAlert(Bool) } - enum SideEffect { + public enum SideEffect { case observeUnreadPushCount case trackScreenView(MainTab) case updateBadgeCount(Int) } - private(set) var state = State() + public private(set) var state = State() private let logger = Logger(category: "MainViewModel") private var cancellables = Set() private var isObservingUnreadPushCount = false private let trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase private let unreadPushCountUseCase: ObserveUnreadPushCountUseCase - init( + public init( trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase, unreadPushCountUseCase: ObserveUnreadPushCountUseCase ) { @@ -48,7 +48,7 @@ final class MainViewModel: Store { self.unreadPushCountUseCase = unreadPushCountUseCase } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var sideEffects: [SideEffect] = [] @@ -73,7 +73,7 @@ final class MainViewModel: Store { return sideEffects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .observeUnreadPushCount: observeUnreadPushCount() diff --git a/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift index af46da00..4b259c66 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift @@ -11,29 +11,29 @@ import DevLogCore import DevLogDomain @Observable -final class ProfileViewModel: Store { - struct State: Equatable { - var name: String = "" - var email: String = "" - var isNetworkConnected: Bool = true - var isLoading: Bool = false - var statusMessage: String = "" - var avatarURL: URL? - var earliestQuarterStart: Date? - var selectedQuarterStart: Date? - var showQuarterPicker: Bool = false - var selectedQuarterPickerYear = Calendar.current.component(.year, from: Date()) - var activityQuarter: HeatmapQuarter? - var dayActivitiesByDate: [Date: [HeatmapActivityItem]] = [:] - var selectedActivityKinds: Set = [.created, .completed, .deleted] - var selectedDay: HeatmapDay? - var showDoneButton: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - } - - enum Action { +public final class ProfileViewModel: Store { + public struct State: Equatable { + public var name: String = "" + public var email: String = "" + public var isNetworkConnected: Bool = true + public var isLoading: Bool = false + public var statusMessage: String = "" + public var avatarURL: URL? + public var earliestQuarterStart: Date? + public var selectedQuarterStart: Date? + public var showQuarterPicker: Bool = false + public var selectedQuarterPickerYear = Calendar.current.component(.year, from: Date()) + public var activityQuarter: HeatmapQuarter? + public var dayActivitiesByDate: [Date: [HeatmapActivityItem]] = [:] + public var selectedActivityKinds: Set = [.created, .completed, .deleted] + public var selectedDay: HeatmapDay? + public var showDoneButton: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + } + + public enum Action { case fetchData, refresh case networkStatusChanged(Bool) case setLoading(Bool) @@ -58,14 +58,18 @@ final class ProfileViewModel: Store { case updateStatusTextFieldFocus(Bool) } - enum SideEffect { + public enum SideEffect { case fetchUserData case fetchActivityQuarter(Date) case updateStatusMessage(String) case updateHeatmapActivityKinds(Set) } - private(set) var state = State() + public private(set) var state = State() + public var selectedActivityKindItems: Set { + Set(state.selectedActivityKinds.map(ActivityKindItem.init(from:))) + } + private let fetchUserDataUseCase: FetchUserDataUseCase private let fetchTodosUseCase: FetchTodosUseCase private let upsertStatusMessageUseCase: UpsertStatusMessageUseCase @@ -76,7 +80,7 @@ final class ProfileViewModel: Store { private let loadingState = LoadingState() private var cancellables = Set() - init( + public init( fetchUserDataUseCase: FetchUserDataUseCase, fetchTodosUseCase: FetchTodosUseCase, upsertStatusMessageUseCase: UpsertStatusMessageUseCase, @@ -93,8 +97,33 @@ final class ProfileViewModel: Store { setupNetworkObserving() } + public func isSelected(_ activityKindItem: ActivityKindItem) -> Bool { + guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { + return false + } + + return state.selectedActivityKinds.contains(activityKind) + } + + public func isOnlySelected(_ activityKindItem: ActivityKindItem) -> Bool { + guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { + return false + } + + return state.selectedActivityKinds.count == 1 + && state.selectedActivityKinds.contains(activityKind) + } + + public func toggle(_ activityKindItem: ActivityKindItem) { + guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { + return + } + + send(.toggleActivityKind(activityKind)) + } + // swiftlint:disable cyclomatic_complexity - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] switch action { @@ -191,7 +220,7 @@ final class ProfileViewModel: Store { } // swiftlint:enable cyclomatic_complexity - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchUserData: Task { @@ -263,7 +292,7 @@ private struct HeatmapActivityEntry { var activityKinds: Set } -extension ProfileViewModel { +public extension ProfileViewModel { private func setupNetworkObserving() { networkConnectivityUseCase.observe() .receive(on: DispatchQueue.main) diff --git a/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift index a46c630b..0f30350a 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift @@ -11,23 +11,25 @@ import DevLogCore import DevLogDomain @Observable -final class PushNotificationListViewModel: Store { - struct State: Equatable { - var notifications: [PushNotificationItem] = [] - var showAlert: Bool = false - var showToast: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var toastMessage: String = "" - var isLoading: Bool = false - var hasMore: Bool = false - var nextCursor: PushNotificationCursor? - var query: PushNotificationQuery - var selectedNotificationId: String? - var selectedTodoId: TodoIdItem? +public final class PushNotificationListViewModel: Store { + public typealias TimeFilter = PushNotificationQuery.TimeFilter + + public struct State: Equatable { + public var notifications: [PushNotificationItem] = [] + public var showAlert: Bool = false + public var showToast: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var toastMessage: String = "" + public var isLoading: Bool = false + public var hasMore: Bool = false + public var nextCursor: PushNotificationCursor? + public var query: PushNotificationQuery + public var selectedNotificationId: String? + public var selectedTodoId: TodoIdItem? } - enum Action { + public enum Action { case fetchNotifications case loadNextPage case deleteNotification(PushNotificationItem) @@ -48,14 +50,14 @@ final class PushNotificationListViewModel: Store { case selectNotification(String?) } - enum SideEffect { + public enum SideEffect { case fetchNotifications(PushNotificationQuery, cursor: PushNotificationCursor?) case delete(PushNotificationItem) case undoDelete(String) case toggleRead(String) } - private(set) var state: State + public private(set) var state: State private let fetchUseCase: FetchPushNotificationsUseCase private let deleteUseCase: DeletePushNotificationUseCase private let undoDeleteUseCase: UndoDeletePushNotificationUseCase @@ -66,7 +68,7 @@ final class PushNotificationListViewModel: Store { private var undoNotificationId: String? private var cancellable: AnyCancellable? - init( + public init( fetchUseCase: FetchPushNotificationsUseCase, deleteUseCase: DeletePushNotificationUseCase, undoDeleteUseCase: UndoDeletePushNotificationUseCase, @@ -85,7 +87,7 @@ final class PushNotificationListViewModel: Store { ) } - var appliedFilterCount: Int { + public var appliedFilterCount: Int { var count = 0 if state.query.sortOrder != .latest { count += 1 } if state.query.timeFilter != .none { count += 1 } @@ -93,7 +95,7 @@ final class PushNotificationListViewModel: Store { return count } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -114,7 +116,7 @@ final class PushNotificationListViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchNotifications(let query, let cursor): if cursor == nil { @@ -386,7 +388,7 @@ private extension PushNotificationListViewModel { } } -extension PushNotificationQuery.SortOrder { +public extension PushNotificationQuery.SortOrder { var title: String { switch self { case .latest: return String(localized: "push_sort_latest") @@ -395,7 +397,7 @@ extension PushNotificationQuery.SortOrder { } } -extension PushNotificationQuery.TimeFilter { +public extension PushNotificationQuery.TimeFilter { var title: String { switch self { case .none: diff --git a/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift index 3c63f0da..4d00e43d 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift @@ -12,17 +12,17 @@ import DevLogCore import DevLogDomain @Observable -final class RootViewModel: Store { - struct State: Equatable { - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var isNetworkConnected: Bool = true - var signIn: Bool? - var theme: SystemTheme = .automatic +public final class RootViewModel: Store { + public struct State: Equatable { + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var isNetworkConnected: Bool = true + public var signIn: Bool? + public var theme: SystemTheme = .automatic } - enum Action { + public enum Action { case onAppear case setAlert(Bool) case networkStatusChanged(Bool) @@ -30,19 +30,19 @@ final class RootViewModel: Store { case didLogined(Bool) } - enum SideEffect { + public enum SideEffect { case clearApplicationBadgeCount case trackLoginScreen } - private(set) var state: State + public private(set) var state: State private var cancellables = Set() private let sessionUseCase: ObserveAuthSessionUseCase private let networkConnectivityUseCase: ObserveNetworkConnectivityUseCase private let systemThemeUseCase: ObserveSystemThemeUseCase private let trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase - init( + public init( sessionUseCase: ObserveAuthSessionUseCase, networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, systemThemeUseCase: ObserveSystemThemeUseCase, @@ -59,7 +59,7 @@ final class RootViewModel: Store { setupThemeObserving() } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -87,7 +87,7 @@ final class RootViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .clearApplicationBadgeCount: UNUserNotificationCenter.current().setBadgeCount(0) { _ in } diff --git a/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift index 31532af3..744bf9e0 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift @@ -11,22 +11,22 @@ import DevLogCore import DevLogDomain @Observable -final class SearchViewModel: Store { - struct State: Equatable { - var isLoading: Bool = false - var isSearching: Bool = false - var searchQuery: String = "" - var webPages: [WebPageItem] = [] - var todos: [TodoListItem] = [] - var recentQueries: OrderedSet = [] - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var showAllTodos: Bool = false - var showAllWebPages: Bool = false +public final class SearchViewModel: Store { + public struct State: Equatable { + public var isLoading: Bool = false + public var isSearching: Bool = false + public var searchQuery: String = "" + public var webPages: [WebPageItem] = [] + public var todos: [TodoListItem] = [] + public var recentQueries: OrderedSet = [] + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var showAllTodos: Bool = false + public var showAllWebPages: Bool = false } - enum Action { + public enum Action { case fetchWebPage([WebPageItem]) case fetchTodos([TodoListItem]) case addRecentQuery(String) @@ -41,7 +41,7 @@ final class SearchViewModel: Store { case setShowAllWebPages(Bool) } - enum SideEffect { + public enum SideEffect { case cancelSearch case debounceFetch(String) case fetch(String) @@ -52,19 +52,19 @@ final class SearchViewModel: Store { case request } - private(set) var state: State = .init() + public private(set) var state: State = .init() private let fetchWebPagesUseCase: FetchWebPagesUseCase private let fetchTodosUseCase: FetchTodosUseCase private let fetchRecentSearchQueriesUseCase: FetchRecentSearchQueriesUseCase private let updateRecentSearchQueriesUseCase: UpdateRecentSearchQueriesUseCase private let loadingState = LoadingState() - let contentsLimit: Int = 5 + public let contentsLimit: Int = 5 private let maxRecentQueries = 20 private let searchDebounceDelay: Double = 0.4 private var searchTasks: [SearchTaskKind: Task] = [:] - init( + public init( fetchWebPagesUseCase: FetchWebPagesUseCase, fetchTodosUseCase: FetchTodosUseCase, fetchRecentSearchQueriesUseCase: FetchRecentSearchQueriesUseCase, @@ -77,7 +77,7 @@ final class SearchViewModel: Store { self.state.recentQueries = OrderedSet(fetchRecentSearchQueriesUseCase.execute()) } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -142,7 +142,7 @@ final class SearchViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .cancelSearch: cancelSearch() diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift index 134a561d..07e11c3c 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift @@ -9,22 +9,24 @@ import Foundation import DevLogDomain @Observable -final class AccountViewModel: Store { - struct State: Equatable { - var currentProvider: AuthProvider? - var connectedProviders: [AuthProvider] = [] - var disconnectedProviders: [AuthProvider] = [] - var showAlert: Bool = false - var alertTitle: String = "" - var alertType: AlertType? - var alertMessage: String = "" - var showToast: Bool = false - var toastType: ToastType? - var toastMessage: String = "" - var isLoading: Bool = false +public final class AccountViewModel: Store { + public typealias Provider = AuthProvider + + public struct State: Equatable { + public var currentProvider: AuthProvider? + public var connectedProviders: [AuthProvider] = [] + public var disconnectedProviders: [AuthProvider] = [] + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertType: AlertType? + public var alertMessage: String = "" + public var showToast: Bool = false + public var toastType: ToastType? + public var toastMessage: String = "" + public var isLoading: Bool = false } - enum Action { + public enum Action { case onAppear case linkWithProvider(AuthProvider) case unlinkFromProvider(AuthProvider) @@ -34,31 +36,31 @@ final class AccountViewModel: Store { case updateProviders(currentProvider: AuthProvider?, allProviders: [AuthProvider]) } - enum SideEffect { + public enum SideEffect { case fetch case link(AuthProvider) case unlink(AuthProvider) } - enum AlertType { + public enum AlertType { case linkEmailNotFound case linkEmailMismatch case linkCredentialAlreadyInUse case error } - enum ToastType { + public enum ToastType { case linkSuccess case unlinkSuccess } - private(set) var state: State = .init() + public private(set) var state: State = .init() private let fetchProvidersUseCase: FetchAuthProvidersUseCase private let linkProviderUseCase: LinkAuthProviderUseCase private let unlinkProviderUseCase: UnlinkAuthProviderUseCase private let loadingState = LoadingState() - init( + public init( fetchProvidersUseCase: FetchAuthProvidersUseCase, linkProviderUseCase: LinkAuthProviderUseCase, unlinkProviderUseCase: UnlinkAuthProviderUseCase @@ -68,7 +70,7 @@ final class AccountViewModel: Store { self.unlinkProviderUseCase = unlinkProviderUseCase } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -96,12 +98,12 @@ final class AccountViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetch: Task { do { - let (currentProvider, allProviders) = try await fetchProvidersUseCase.execute() + let(currentProvider, allProviders) = try await fetchProvidersUseCase.execute() send(.updateProviders(currentProvider: currentProvider, allProviders: allProviders)) } catch { send(.setAlert(isPresented: true, type: .error)) @@ -115,7 +117,7 @@ final class AccountViewModel: Store { try await linkProviderUseCase.execute(provider) send(.setToast(isPresented: true, type: .linkSuccess)) - let (currentProvider, allProviders) = try await fetchProvidersUseCase.execute() + let(currentProvider, allProviders) = try await fetchProvidersUseCase.execute() send(.updateProviders(currentProvider: currentProvider, allProviders: allProviders)) } catch { if error.isSocialLoginCancelled { return } @@ -130,7 +132,7 @@ final class AccountViewModel: Store { try await unlinkProviderUseCase.execute(provider) send(.setToast(isPresented: true, type: .unlinkSuccess)) - let (currentProvider, allProviders) = try await fetchProvidersUseCase.execute() + let(currentProvider, allProviders) = try await fetchProvidersUseCase.execute() send(.updateProviders(currentProvider: currentProvider, allProviders: allProviders)) } catch { send(.setAlert(isPresented: true, type: .error)) diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift index c73731e3..6b3a44fc 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift @@ -9,27 +9,27 @@ import Foundation import DevLogDomain @Observable -final class PushNotificationSettingsViewModel: Store { - struct State: Equatable { - var pushNotificationEnable: Bool = false - var viewPushNotificationTime: Date = .init() - var sheetPushNotificationTime: Date = .init() - var showTimePicker: Bool = false - var isLoading: Bool = false - var sheetHeight: CGFloat = .pi - var showSheet: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var pushNotificationHour: Int { +public final class PushNotificationSettingsViewModel: Store { + public struct State: Equatable { + public var pushNotificationEnable: Bool = false + public var viewPushNotificationTime: Date = .init() + public var sheetPushNotificationTime: Date = .init() + public var showTimePicker: Bool = false + public var isLoading: Bool = false + public var sheetHeight: CGFloat = .pi + public var showSheet: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var pushNotificationHour: Int { Calendar.current.component(.hour, from: viewPushNotificationTime) } - var pushNotificationMinute: Int { + public var pushNotificationMinute: Int { Calendar.current.component(.minute, from: viewPushNotificationTime) } } - enum Action { + public enum Action { case fetchSettings case setAlert(Bool) case setLoading(Bool) @@ -42,18 +42,18 @@ final class PushNotificationSettingsViewModel: Store { case rollbackUpdate } - enum SideEffect { + public enum SideEffect { case fetchPushNotificationSettings case updatePushNotificationSettings } - private(set) var state: State = .init() + public private(set) var state: State = .init() private let calendar = Calendar.current private let fetchPushSettingsUseCase: FetchPushSettingsUseCase private let updatePushSettingsUseCase: UpdatePushSettingsUseCase private let loadingState = LoadingState() - init( + public init( fetchPushSettingsUseCase: FetchPushSettingsUseCase, updatePushSettingsUseCase: UpdatePushSettingsUseCase ) { @@ -61,7 +61,7 @@ final class PushNotificationSettingsViewModel: Store { self.updatePushSettingsUseCase = updatePushSettingsUseCase } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -105,7 +105,7 @@ final class PushNotificationSettingsViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchPushNotificationSettings: beginLoading(.delayed) @@ -146,7 +146,7 @@ final class PushNotificationSettingsViewModel: Store { } } -extension PushNotificationSettingsViewModel { +public extension PushNotificationSettingsViewModel { func setAlert( _ state: inout State, isPresented: Bool diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift index aaddbab2..5405c5c0 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift @@ -11,19 +11,21 @@ import DevLogCore import DevLogDomain @Observable -final class SettingViewModel: Store { - struct State: Equatable { - var theme: SystemTheme = .automatic - var dirSize: Int64 = 0 - var isNetworkConnected = true - var isLoading = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertType: AlertType? - var alertMessage: String = "" +public final class SettingViewModel: Store { + public typealias Theme = SystemTheme + + public struct State: Equatable { + public var theme: SystemTheme = .automatic + public var dirSize: Int64 = 0 + public var isNetworkConnected = true + public var isLoading = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertType: AlertType? + public var alertMessage: String = "" } - enum Action { + public enum Action { case networkStatusChanged(Bool) case setAlert(isPresented: Bool, type: AlertType? = nil) case setDirSize(Int64) @@ -36,18 +38,18 @@ final class SettingViewModel: Store { case confirmRemoveCache } - enum SideEffect { + public enum SideEffect { case clearWebPageImageDirectory case deleteAuth case fetchWebPageImageDirSize case signOut } - enum AlertType { + public enum AlertType { case signOut, deleteAuth, error, removeCache } - private(set) var state = State() + public private(set) var state = State() private let deleteAuthuseCase: DeleteAuthUseCase private let signOutUseCase: SignOutUseCase private let networkConnectivityUseCase: ObserveNetworkConnectivityUseCase @@ -58,11 +60,11 @@ final class SettingViewModel: Store { private let loadingState = LoadingState() private var cancellables = Set() - let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String - let appstoreUrl = Bundle.main.object(forInfoDictionaryKey: "APPSTORE_URL") as? String - let policyURL = Bundle.main.object(forInfoDictionaryKey: "PRIVACY_POLICY_URL") as? String + public let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String + public let appstoreUrl = Bundle.main.object(forInfoDictionaryKey: "APPSTORE_URL") as? String + public let policyURL = Bundle.main.object(forInfoDictionaryKey: "PRIVACY_POLICY_URL") as? String - init( + public init( deleteAuthUseCase: DeleteAuthUseCase, signOutUseCase: SignOutUseCase, networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, @@ -82,7 +84,7 @@ final class SettingViewModel: Store { setupThemeMonitoring() } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -115,7 +117,7 @@ final class SettingViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .clearWebPageImageDirectory: Task { diff --git a/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift index ccaef572..234e6bc7 100644 --- a/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift +++ b/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift @@ -10,9 +10,12 @@ import DevLogCore import DevLogDomain @Observable -final class TodayViewModel: Store { +public final class TodayViewModel: Store { + public typealias DueDateVisibility = TodayDisplayOptions.DueDateVisibility + public typealias FocusVisibility = TodayDisplayOptions.FocusVisibility + // TodayView 상단에서 사용자가 선택하는 요약 탭 범위. - enum SectionScope: Hashable, CaseIterable { + public enum SectionScope: Hashable, CaseIterable { case all case focused case overdue @@ -20,7 +23,7 @@ final class TodayViewModel: Store { } // 요약 탭 아래 실제 리스트에 렌더링되는 섹션 분류. - enum SectionCategory: Hashable { + public enum SectionCategory: Hashable { case later case unscheduled case focused @@ -28,32 +31,32 @@ final class TodayViewModel: Store { case dueSoon } - struct SectionContent: Identifiable, Equatable { - var id: SectionCategory { category } - let category: SectionCategory - let title: String - let items: [TodayTodoItem] + public struct SectionContent: Identifiable, Equatable { + public var id: SectionCategory { category } + public let category: SectionCategory + public let title: String + public let items: [TodayTodoItem] } - struct SectionCollection { - var focused: [TodayTodoItem] = [] - var overdue: [TodayTodoItem] = [] - var dueSoon: [TodayTodoItem] = [] - var later: [TodayTodoItem] = [] - var unscheduled: [TodayTodoItem] = [] + public struct SectionCollection { + public var focused: [TodayTodoItem] = [] + public var overdue: [TodayTodoItem] = [] + public var dueSoon: [TodayTodoItem] = [] + public var later: [TodayTodoItem] = [] + public var unscheduled: [TodayTodoItem] = [] } - struct State: Equatable { - var todos: [TodayTodoItem] = [] - var isLoading: Bool = false - var showAlert: Bool = false - var alertTitle: String = "" - var alertMessage: String = "" - var selectedSectionScope: SectionScope = .all - var displayOptions: TodayDisplayOptions = .default + public struct State: Equatable { + public var todos: [TodayTodoItem] = [] + public var isLoading: Bool = false + public var showAlert: Bool = false + public var alertTitle: String = "" + public var alertMessage: String = "" + public var selectedSectionScope: SectionScope = .all + public var displayOptions: TodayDisplayOptions = .default } - enum Action { + public enum Action { case refresh case setAlert(Bool) case setSectionScope(SectionScope) @@ -69,13 +72,13 @@ final class TodayViewModel: Store { case removeTodo(String) } - enum SideEffect { + public enum SideEffect { case fetchTodos case completeTodo(TodayTodoItem) case togglePinned(TodayTodoItem) } - private(set) var state = State() + public private(set) var state = State() private let calendar = Calendar.current private let pageSize = 20 private let upcomingWindowDays = 7 @@ -86,7 +89,7 @@ final class TodayViewModel: Store { private let trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase private let loadingState = LoadingState() - init( + public init( fetchTodosUseCase: FetchTodosUseCase, fetchTodoByIdUseCase: FetchTodoByIdUseCase, upsertTodoUseCase: UpsertTodoUseCase, @@ -102,7 +105,7 @@ final class TodayViewModel: Store { self.state.displayOptions = fetchTodayDisplayOptionsUseCase.execute() } - var sections: [SectionContent] { + public var sections: [SectionContent] { let items = groupedSectionItems(from: displayedTodos) switch state.selectedSectionScope { @@ -160,7 +163,7 @@ final class TodayViewModel: Store { } } - func summaryValue(for scope: SectionScope) -> Int { + public func summaryValue(for scope: SectionScope) -> Int { switch scope { case .all: return displayedTodos.count @@ -173,7 +176,7 @@ final class TodayViewModel: Store { } } - func reduce(with action: Action) -> [SideEffect] { + public func reduce(with action: Action) -> [SideEffect] { var state = self.state var effects: [SideEffect] = [] @@ -191,7 +194,7 @@ final class TodayViewModel: Store { return effects } - func run(_ effect: SideEffect) { + public func run(_ effect: SideEffect) { switch effect { case .fetchTodos: beginLoading(.delayed) diff --git a/Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift index c76f9750..966f997c 100644 --- a/Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift +++ b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowEvent.swift @@ -11,13 +11,13 @@ import DevLogDomain public final class TodoEditorWindowEvent { private let subject = PassthroughSubject() - var submits: AnyPublisher { + public var submits: AnyPublisher { subject.eraseToAnyPublisher() } public init() { } - func submit( + public func submit( value: TodoEditorWindowValue, todo: Todo ) { diff --git a/Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift index ec27f458..8dbf7c58 100644 --- a/Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift +++ b/Application/DevLogPresentation/Sources/Window/TodoEditorWindowValue.swift @@ -21,7 +21,7 @@ public enum TodoEditorWindowValue: Codable, Hashable { self = .create(TodoEditorWindowCategory(todoCategory: todoCategory), source) } - init(todo: Todo) { + public init(todo: Todo) { self = .edit(TodoEditorWindowTodo(todo: todo)) } } @@ -42,7 +42,7 @@ public struct TodoEditorWindowCategory: Codable, Hashable { private let name: String private let colorHex: String - init(todoCategory: TodoCategory) { + public init(todoCategory: TodoCategory) { switch todoCategory { case .system(let systemTodoCategory): self.kind = .system @@ -57,7 +57,7 @@ public struct TodoEditorWindowCategory: Codable, Hashable { } } - var todoCategory: TodoCategory { + public var todoCategory: TodoCategory { switch kind { case .system: let systemTodoCategory = SystemTodoCategory(rawValue: id) ?? .etc @@ -88,7 +88,7 @@ public struct TodoEditorWindowTodo: Codable, Hashable { private let tags: [String] private let category: TodoEditorWindowCategory - init(todo: Todo) { + public init(todo: Todo) { self.id = todo.id self.isPinned = todo.isPinned self.isCompleted = todo.isCompleted @@ -116,7 +116,7 @@ public struct TodoEditorWindowTodo: Codable, Hashable { hasher.combine(id) } - var todo: Todo { + public var todo: Todo { Todo( id: id, isPinned: isPinned, @@ -136,13 +136,13 @@ public struct TodoEditorWindowTodo: Codable, Hashable { } } -struct TodoEditorWindowSubmit: Equatable { - let id = UUID() - let value: TodoEditorWindowValue - let todo: Todo +public struct TodoEditorWindowSubmit: Equatable { + public let id = UUID() + public let value: TodoEditorWindowValue + public let todo: Todo } -extension TodoEditorWindowValue { +public extension TodoEditorWindowValue { func matchesCreate( category: TodoCategory? = nil, source: TodoEditorWindowSource From 5399a1689b45acd784b87da7966076ecebfbffb2 Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:34:54 +0900 Subject: [PATCH 04/10] =?UTF-8?q?refactor:=20UI=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Common/Component/CacheableImage.swift | 4 +- .../Sources/Common/Component/CheckBox.swift | 4 +- .../Common/Component/LoadingView.swift | 4 +- .../Common/Component/LoginButton.swift | 4 +- .../Common/Component/RelativeTimeText.swift | 4 +- .../Sources/Common/Component/Tags.swift | 4 +- .../Sources/Common/Component/Toast.swift | 4 +- .../Common/Component/TodoItemRow.swift | 4 +- .../Common/Component/ToolbarButtons.swift | 12 ++-- .../Common/Component/UIKitTextEditor.swift | 4 +- .../Sources/Common/Component/WebItemRow.swift | 4 +- .../Common/NavigationBarConfigurator.swift | 4 +- .../Common/TodoDetailContentView.swift | 4 +- .../Sources/Common/TodoInfoSheetView.swift | 4 +- .../Common/TodoMarkdownContentView.swift | 4 +- .../DevLogUI/Sources/Common/WebView.swift | 4 +- .../Extension/EnvironmentValues+.swift | 4 +- .../DevLogUI/Sources/Extension/View+.swift | 4 +- .../DevLogUI/Sources/Home/Home/HomeView.swift | 27 ++++--- .../Sources/Home/TodoDetailView.swift | 70 ++++++++++++------- .../Sources/Home/TodoEditorView.swift | 34 +++++---- .../DevLogUI/Sources/Home/TodoListView.swift | 22 +++--- .../Sources/Home/TodoManageView.swift | 4 +- .../DevLogUI/Sources/Login/LoginView.swift | 12 ++-- .../DevLogUI/Sources/Main/MainView.swift | 60 ++++++++++------ .../Sources/Profile/HeatmapView.swift | 22 +++--- .../Sources/Profile/ProfileView.swift | 39 +++-------- .../PushNotificationListView.swift | 13 ++-- .../DevLogUI/Sources/Search/SearchView.swift | 16 ++--- .../Sources/Setting/AccountView.swift | 10 +-- .../PushNotificationSettingsView.swift | 4 +- .../Sources/Setting/SettingView.swift | 4 +- .../DevLogUI/Sources/Setting/ThemeView.swift | 13 ++-- .../DevLogUI/Sources/Today/TodayView.swift | 13 ++-- 34 files changed, 233 insertions(+), 210 deletions(-) diff --git a/Application/DevLogUI/Sources/Common/Component/CacheableImage.swift b/Application/DevLogUI/Sources/Common/Component/CacheableImage.swift index 0ecb0754..f94901db 100644 --- a/Application/DevLogUI/Sources/Common/Component/CacheableImage.swift +++ b/Application/DevLogUI/Sources/Common/Component/CacheableImage.swift @@ -1,12 +1,12 @@ // // CacheableImage.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 11/30/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct CacheableImage: View { @State private var loadedUIImage: UIImage? diff --git a/Application/DevLogUI/Sources/Common/Component/CheckBox.swift b/Application/DevLogUI/Sources/Common/Component/CheckBox.swift index 1354d636..445f9ae5 100644 --- a/Application/DevLogUI/Sources/Common/Component/CheckBox.swift +++ b/Application/DevLogUI/Sources/Common/Component/CheckBox.swift @@ -1,12 +1,12 @@ // // CheckBox.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 6/17/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct CheckBox: View { private let isChecked: Bool diff --git a/Application/DevLogUI/Sources/Common/Component/LoadingView.swift b/Application/DevLogUI/Sources/Common/Component/LoadingView.swift index bd81630a..a304c0bc 100644 --- a/Application/DevLogUI/Sources/Common/Component/LoadingView.swift +++ b/Application/DevLogUI/Sources/Common/Component/LoadingView.swift @@ -1,12 +1,12 @@ // // LoadingView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/16/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct LoadingView: View { var body: some View { diff --git a/Application/DevLogUI/Sources/Common/Component/LoginButton.swift b/Application/DevLogUI/Sources/Common/Component/LoginButton.swift index 7c9c6fe0..1649584a 100644 --- a/Application/DevLogUI/Sources/Common/Component/LoginButton.swift +++ b/Application/DevLogUI/Sources/Common/Component/LoginButton.swift @@ -1,12 +1,12 @@ // // LoginButton.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 4/25/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct LoginButton: View { @State private var logo: Image? diff --git a/Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift b/Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift index 083cefee..4e153d3f 100644 --- a/Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift +++ b/Application/DevLogUI/Sources/Common/Component/RelativeTimeText.swift @@ -1,12 +1,12 @@ // // RelativeTimeText.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 3/25/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct RelativeTimeText: View { let date: Date diff --git a/Application/DevLogUI/Sources/Common/Component/Tags.swift b/Application/DevLogUI/Sources/Common/Component/Tags.swift index 685e6d6b..7a339f81 100644 --- a/Application/DevLogUI/Sources/Common/Component/Tags.swift +++ b/Application/DevLogUI/Sources/Common/Component/Tags.swift @@ -1,12 +1,12 @@ // // Tags.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/6/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct Tag: View { @Environment(\.colorScheme) private var colorScheme diff --git a/Application/DevLogUI/Sources/Common/Component/Toast.swift b/Application/DevLogUI/Sources/Common/Component/Toast.swift index 43f8af56..548b3c8c 100644 --- a/Application/DevLogUI/Sources/Common/Component/Toast.swift +++ b/Application/DevLogUI/Sources/Common/Component/Toast.swift @@ -1,12 +1,12 @@ // // Toast.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/10/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation extension View { func toast( diff --git a/Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift b/Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift index 6aad9508..1ba9792e 100644 --- a/Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift +++ b/Application/DevLogUI/Sources/Common/Component/TodoItemRow.swift @@ -1,12 +1,12 @@ // // TodoItemRow.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/21/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct TodoItemRow: View { @ScaledMetric(relativeTo: .largeTitle) private var labelWidth = CGFloat(34) diff --git a/Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift b/Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift index 0869baeb..3b443bed 100644 --- a/Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift +++ b/Application/DevLogUI/Sources/Common/Component/ToolbarButtons.swift @@ -1,17 +1,21 @@ // // ToolbarButtons.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 3/1/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation -struct ToolbarLeadingButton: ToolbarContent { +public struct ToolbarLeadingButton: ToolbarContent { var action: (() -> Void)? - var body: some ToolbarContent { + public init(action: (() -> Void)? = nil) { + self.action = action + } + + public var body: some ToolbarContent { ToolbarItem(placement: .topBarLeading) { if #available(iOS 26.0, *) { Button(role: .cancel) { diff --git a/Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift b/Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift index 68706d3a..ec06bfb2 100644 --- a/Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift +++ b/Application/DevLogUI/Sources/Common/Component/UIKitTextEditor.swift @@ -1,13 +1,13 @@ // // UIKitTextEditor.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 3/18/26. // import SwiftUI +import DevLogPresentation import UIKit -import DevLogDomain struct UIKitTextEditor: View { @Binding var text: String diff --git a/Application/DevLogUI/Sources/Common/Component/WebItemRow.swift b/Application/DevLogUI/Sources/Common/Component/WebItemRow.swift index f7abbb95..effc8b9f 100644 --- a/Application/DevLogUI/Sources/Common/Component/WebItemRow.swift +++ b/Application/DevLogUI/Sources/Common/Component/WebItemRow.swift @@ -1,12 +1,12 @@ // // WebItemRow.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/24/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct WebItemRow: View { @ScaledMetric(relativeTo: .largeTitle) private var labelWidth = CGFloat(34) diff --git a/Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift b/Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift index 3828dcb4..aae1273f 100644 --- a/Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift +++ b/Application/DevLogUI/Sources/Common/NavigationBarConfigurator.swift @@ -1,12 +1,12 @@ // // NavigationBarConfigurator.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 3/5/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation /// NavigationBar의 배경색을 지정하고 shadowColor를 제거하는 구조체 /// diff --git a/Application/DevLogUI/Sources/Common/TodoDetailContentView.swift b/Application/DevLogUI/Sources/Common/TodoDetailContentView.swift index 2ba8fb53..4e95b080 100644 --- a/Application/DevLogUI/Sources/Common/TodoDetailContentView.swift +++ b/Application/DevLogUI/Sources/Common/TodoDetailContentView.swift @@ -1,13 +1,13 @@ // // TodoDetailContentView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 3/2/26. // import SwiftUI +import DevLogPresentation import MarkdownUI -import DevLogDomain struct TodoDetailContentView: View { let title: String diff --git a/Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift b/Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift index 6f57efba..fc2ae1fd 100644 --- a/Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift +++ b/Application/DevLogUI/Sources/Common/TodoInfoSheetView.swift @@ -1,12 +1,12 @@ // // TodoInfoSheetView.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 3/2/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct TodoInfoSheetView: View { let createdAt: Date diff --git a/Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift b/Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift index cfbdcf65..2c3e883a 100644 --- a/Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift +++ b/Application/DevLogUI/Sources/Common/TodoMarkdownContentView.swift @@ -1,13 +1,13 @@ // // TodoMarkdownContentView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 3/25/26. // import MarkdownUI import SwiftUI -import DevLogDomain +import DevLogPresentation private enum TodoMarkdownSection: Equatable { case markdown(String) diff --git a/Application/DevLogUI/Sources/Common/WebView.swift b/Application/DevLogUI/Sources/Common/WebView.swift index e4657684..17f8b451 100644 --- a/Application/DevLogUI/Sources/Common/WebView.swift +++ b/Application/DevLogUI/Sources/Common/WebView.swift @@ -1,13 +1,13 @@ // // WebView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/23/25. // import SwiftUI +import DevLogPresentation import WebKit -import DevLogDomain struct WebView: UIViewRepresentable { let url: URL diff --git a/Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift b/Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift index 7b8eb91a..34de3489 100644 --- a/Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift +++ b/Application/DevLogUI/Sources/Extension/EnvironmentValues+.swift @@ -1,12 +1,12 @@ // // EnvironmentValues+.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/6/26. // import SwiftUI -import DevLogDomain +import DevLogPresentation extension EnvironmentValues { var safeAreaInsets: EdgeInsets { diff --git a/Application/DevLogUI/Sources/Extension/View+.swift b/Application/DevLogUI/Sources/Extension/View+.swift index 96337143..5446f7a9 100644 --- a/Application/DevLogUI/Sources/Extension/View+.swift +++ b/Application/DevLogUI/Sources/Extension/View+.swift @@ -1,12 +1,12 @@ // // View+.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 11/22/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation extension View { @ViewBuilder diff --git a/Application/DevLogUI/Sources/Home/Home/HomeView.swift b/Application/DevLogUI/Sources/Home/Home/HomeView.swift index ee3040c0..fe982505 100644 --- a/Application/DevLogUI/Sources/Home/Home/HomeView.swift +++ b/Application/DevLogUI/Sources/Home/Home/HomeView.swift @@ -1,12 +1,12 @@ // // HomeView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/7/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct HomeView: View { @Environment(\.openWindow) private var openWindow @@ -14,6 +14,7 @@ struct HomeView: View { @ScaledMetric(relativeTo: .largeTitle) private var labelWidth = CGFloat(34) let coordinator: HomeViewCoordinator let isCompactLayout: Bool + let todoViewModelFactory: TodoViewModelFactory var body: some View { List { @@ -50,7 +51,8 @@ struct HomeView: View { )) { if let selectedCategory = coordinator.viewModel.state.selectedTodoCategory { TodoEditorView( - viewModel: coordinator.makeTodoEditorViewModel(category: selectedCategory) + viewModel: coordinator.makeTodoEditorViewModel(category: selectedCategory), + todoViewModelFactory: todoViewModelFactory ) } } @@ -58,7 +60,10 @@ struct HomeView: View { get: { coordinator.viewModel.state.showSearchView }, set: { coordinator.viewModel.send(.setPresentation(.searchView, $0)) } )) { - SearchView(viewModel: coordinator.makeSearchViewModel()) + SearchView( + viewModel: coordinator.makeSearchViewModel(), + todoViewModelFactory: todoViewModelFactory + ) } .alert( coordinator.viewModel.state.alertTitle, @@ -317,7 +322,7 @@ struct HomeView: View { ForEach(preferences, id: \.id) { item in Button { DispatchQueue.main.async { - openTodoEditor(for: item.category) + openTodoEditor(for: item) } } label: { labelImage( @@ -387,26 +392,20 @@ struct HomeView: View { .contentShape(.rect) } - private func openTodoEditor(for todoCategory: TodoCategory) { + private func openTodoEditor(for item: TodoCategoryItem) { if isiOSAppOnMac { coordinator.viewModel.send(.setPresentation(.contentPicker, false)) openWindow( id: TodoEditorWindowValue.sceneId, - value: TodoEditorWindowValue(todoCategory: todoCategory, source: .home) + value: TodoEditorWindowValue(todoCategory: item.category, source: .home) ) } else { - coordinator.viewModel.send(.tapTodoCategory(todoCategory)) + coordinator.viewModel.send(.tapTodoCategory(item.category)) } } } -enum HomeRoute: Hashable { - case category(TodoCategoryItem) - case todo(TodoIdItem) - case webPage(WebPageItem) -} - private struct RecentTodoRow: View { @ScaledMetric(relativeTo: .largeTitle) private var labelWidth = CGFloat(34) let todo: RecentTodoItem diff --git a/Application/DevLogUI/Sources/Home/TodoDetailView.swift b/Application/DevLogUI/Sources/Home/TodoDetailView.swift index 93d9a62e..d5526880 100644 --- a/Application/DevLogUI/Sources/Home/TodoDetailView.swift +++ b/Application/DevLogUI/Sources/Home/TodoDetailView.swift @@ -1,21 +1,28 @@ // // TodoDetailView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 6/12/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation -struct TodoDetailView: View { - @Environment(\.diContainer) private var container: DIContainer +public struct TodoDetailView: View { @Environment(\.openWindow) private var openWindow @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @State var viewModel: TodoDetailViewModel + let todoViewModelFactory: TodoViewModelFactory + + public init( + viewModel: TodoDetailViewModel, + todoViewModelFactory: TodoViewModelFactory + ) { + self.viewModel = viewModel + self.todoViewModelFactory = todoViewModelFactory + } - var body: some View { + public var body: some View { ZStack { Color(.secondarySystemBackground).ignoresSafeArea() if let todo = viewModel.state.todo, let number = todo.number { @@ -43,12 +50,13 @@ struct TodoDetailView: View { set: { viewModel.send(.setSelectedTodoId($0)) } )) { item in NavigationStack { - TodoDetailView(viewModel: TodoDetailViewModel( - fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - todoId: item.id, - showEditButton: false - )) + TodoDetailView( + viewModel: todoViewModelFactory.makeDetailViewModel( + todoId: item.id, + showEditButton: false + ), + todoViewModelFactory: todoViewModelFactory + ) .toolbar { ToolbarLeadingButton { viewModel.send(.setSelectedTodoId(nil)) @@ -64,16 +72,14 @@ struct TodoDetailView: View { )) { if let todo = viewModel.state.todo { TodoEditorView( - viewModel: TodoEditorViewModel( + viewModel: todoViewModelFactory.makeEditorViewModel( todo: todo, - fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), onUpsertSuccess: { todo in viewModel.send(.setShowEditor(false)) viewModel.send(.setTodo(todo)) } - ) + ), + todoViewModelFactory: todoViewModelFactory ) } } @@ -118,7 +124,13 @@ struct TodoDetailView: View { @ViewBuilder private var sheetContent: some View { if let todo = viewModel.state.todo { - TodoDetailInfoSheetView(todo: todo) { + TodoDetailInfoSheetView( + categoryName: TodoCategoryItem(from: todo.category).localizedName, + isCompleted: todo.isCompleted, + isPinned: todo.isPinned, + dueDate: todo.dueDate, + tags: todo.tags + ) { viewModel.send(.setShowInfo(false)) } } @@ -126,7 +138,11 @@ struct TodoDetailView: View { } private struct TodoDetailInfoSheetView: View { - let todo: Todo + let categoryName: String + let isCompleted: Bool + let isPinned: Bool + let dueDate: Date? + let tags: [String] let onClose: () -> Void private let calendar = Calendar.current @@ -137,20 +153,20 @@ private struct TodoDetailInfoSheetView: View { HStack { Text(String(localized: "todo_category")) Spacer() - Text(TodoCategoryItem(from: todo.category).localizedName) + Text(categoryName) .foregroundStyle(.secondary) } statusRow( title: String(localized: "todo_completed"), - systemImage: todo.isCompleted ? "checkmark.circle.fill" : "circle", - color: todo.isCompleted ? .green : .secondary + systemImage: isCompleted ? "checkmark.circle.fill" : "circle", + color: isCompleted ? .green : .secondary ) statusRow( title: String(localized: "todo_pinned"), - systemImage: todo.isPinned ? "star.fill" : "star", - color: todo.isPinned ? .orange : .secondary + systemImage: isPinned ? "star.fill" : "star", + color: isPinned ? .orange : .secondary ) HStack { @@ -158,7 +174,7 @@ private struct TodoDetailInfoSheetView: View { Spacer() - if let dueDate = todo.dueDate { + if let dueDate { Tag(dueDateText(for: dueDate), isEditing: false) .padding(.vertical, -4) } else { @@ -169,12 +185,12 @@ private struct TodoDetailInfoSheetView: View { } Section(String(localized: "todo_tags")) { - if todo.tags.isEmpty { + if tags.isEmpty { Text(String(localized: "todo_no_tags")) .foregroundStyle(.secondary) .padding(.vertical, 4) } else { - TagList(todo.tags) + TagList(tags) } } } diff --git a/Application/DevLogUI/Sources/Home/TodoEditorView.swift b/Application/DevLogUI/Sources/Home/TodoEditorView.swift index 2d01eeae..20f330d7 100644 --- a/Application/DevLogUI/Sources/Home/TodoEditorView.swift +++ b/Application/DevLogUI/Sources/Home/TodoEditorView.swift @@ -1,6 +1,6 @@ // // TodoEditorView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/31/25. // @@ -8,19 +8,28 @@ import MarkdownUI import OrderedCollections import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation -struct TodoEditorView: View { +public struct TodoEditorView: View { @State var viewModel: TodoEditorViewModel - @Environment(\.diContainer) private var container: DIContainer @Environment(\.dismiss) private var dismiss @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @FocusState private var field: Field? private let calendar = Calendar.current + let todoViewModelFactory: TodoViewModelFactory var onClose: (() -> Void)? - var body: some View { + public init( + viewModel: TodoEditorViewModel, + todoViewModelFactory: TodoViewModelFactory, + onClose: (() -> Void)? = nil + ) { + self.viewModel = viewModel + self.todoViewModelFactory = todoViewModelFactory + self.onClose = onClose + } + + public var body: some View { NavigationStack { ScrollView { LazyVStack(spacing: 10) { @@ -61,12 +70,13 @@ struct TodoEditorView: View { set: { viewModel.send(.setSelectedTodoId($0)) } )) { item in NavigationStack { - TodoDetailView(viewModel: TodoDetailViewModel( - fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - todoId: item.id, - showEditButton: false - )) + TodoDetailView( + viewModel: todoViewModelFactory.makeDetailViewModel( + todoId: item.id, + showEditButton: false + ), + todoViewModelFactory: todoViewModelFactory + ) .toolbar { ToolbarLeadingButton { viewModel.send(.setSelectedTodoId(nil)) diff --git a/Application/DevLogUI/Sources/Home/TodoListView.swift b/Application/DevLogUI/Sources/Home/TodoListView.swift index a8c2ab11..b96f2719 100644 --- a/Application/DevLogUI/Sources/Home/TodoListView.swift +++ b/Application/DevLogUI/Sources/Home/TodoListView.swift @@ -1,17 +1,15 @@ // // TodoListView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/30/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct TodoListView: View { @Environment(NavigationRouter.self) private var router - @Environment(\.diContainer) var container: DIContainer @Environment(\.colorScheme) private var colorScheme @Environment(\.openWindow) private var openWindow @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @@ -19,6 +17,7 @@ struct TodoListView: View { @State private var headerOffset: CGFloat = .zero @State private var isScrollTrackingEnabled = false @State var viewModel: TodoListViewModel + let todoViewModelFactory: TodoViewModelFactory var body: some View { Group { @@ -81,17 +80,14 @@ struct TodoListView: View { set: { viewModel.send(.setShowEditor($0)) } )) { TodoEditorView( - viewModel: TodoEditorViewModel( + viewModel: todoViewModelFactory.makeEditorViewModel( category: viewModel.category, - fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), - trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), onUpsertSuccess: { _ in viewModel.send(.setShowEditor(false)) viewModel.send(.refresh) } - ) + ), + todoViewModelFactory: todoViewModelFactory ) } .toolbar { @@ -350,7 +346,7 @@ struct TodoListView: View { get: { viewModel.state.query.sortTarget }, set: { viewModel.send(.setSortTarget($0)) } )) { - ForEach([TodoQuery.SortTarget.createdAt, .updatedAt], id: \.self) { option in + ForEach([TodoListViewModel.SortTarget.createdAt, .updatedAt], id: \.self) { option in Text(option.title).tag(option) } } label: { @@ -360,7 +356,7 @@ struct TodoListView: View { get: { viewModel.state.query.sortOrder }, set: { viewModel.send(.setSortOrder($0)) } )) { - ForEach([TodoQuery.SortOrder.latest, .oldest], id: \.self) { option in + ForEach([TodoListViewModel.SortOrder.latest, .oldest], id: \.self) { option in Text(option.title).tag(option) } } label: { @@ -396,7 +392,7 @@ struct TodoListView: View { get: { viewModel.state.query.completionFilter }, set: { viewModel.send(.setCompletionFilter($0)) } )) { - ForEach([TodoQuery.CompletionFilter.all, .incomplete, .completed], id: \.self) { option in + ForEach([TodoListViewModel.CompletionFilter.all, .incomplete, .completed], id: \.self) { option in Text(option.title).tag(option) } } label: { diff --git a/Application/DevLogUI/Sources/Home/TodoManageView.swift b/Application/DevLogUI/Sources/Home/TodoManageView.swift index 268c1d52..520c7f04 100644 --- a/Application/DevLogUI/Sources/Home/TodoManageView.swift +++ b/Application/DevLogUI/Sources/Home/TodoManageView.swift @@ -1,12 +1,12 @@ // // TodoManageView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 6/16/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct TodoManageView: View { @State var viewModel: TodoManageViewModel diff --git a/Application/DevLogUI/Sources/Login/LoginView.swift b/Application/DevLogUI/Sources/Login/LoginView.swift index b302eada..f8399a75 100644 --- a/Application/DevLogUI/Sources/Login/LoginView.swift +++ b/Application/DevLogUI/Sources/Login/LoginView.swift @@ -1,19 +1,23 @@ // // LoginView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 12/30/24. // import SwiftUI -import DevLogDomain +import DevLogPresentation -struct LoginView: View { +public struct LoginView: View { @Environment(\.colorScheme) var colorScheme @Environment(\.sceneWidth) var sceneWidth @State var viewModel: LoginViewModel - var body: some View { + public init(viewModel: LoginViewModel) { + self.viewModel = viewModel + } + + public var body: some View { ZStack { VStack { Spacer() diff --git a/Application/DevLogUI/Sources/Main/MainView.swift b/Application/DevLogUI/Sources/Main/MainView.swift index 77287698..bd855c7c 100644 --- a/Application/DevLogUI/Sources/Main/MainView.swift +++ b/Application/DevLogUI/Sources/Main/MainView.swift @@ -1,15 +1,14 @@ // // MainView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/8/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation -struct MainView: View { +public struct MainView: View { @Environment(\.horizontalSizeClass) private var horizontalSizeClass @State private var coordinator: MainViewCoordinator @State private var todoWindowCoordinator: TodoWindowCoordinator @@ -18,26 +17,28 @@ struct MainView: View { @State private var pushNotificationListViewCoordinator: PushNotificationListViewCoordinator @State private var profileViewCoordinator: ProfileViewCoordinator @Binding var selectedTab: MainTab? + private let todoViewModelFactory: TodoViewModelFactory private let windowEvent: TodoEditorWindowEvent - init( - container: DIContainer, + public init( + dependencies: MainViewDependencies, windowEvent: TodoEditorWindowEvent, selectedTab: Binding ) { - self._coordinator = State(initialValue: MainViewCoordinator(container: container)) - self._todoWindowCoordinator = State(initialValue: TodoWindowCoordinator(container: container)) - self._homeViewCoordinator = State(initialValue: HomeViewCoordinator(container: container)) - self._todayViewCoordinator = State(initialValue: TodayViewCoordinator(container: container)) + self._coordinator = State(initialValue: dependencies.coordinator) + self._todoWindowCoordinator = State(initialValue: dependencies.todoWindowCoordinator) + self._homeViewCoordinator = State(initialValue: dependencies.homeViewCoordinator) + self._todayViewCoordinator = State(initialValue: dependencies.todayViewCoordinator) self._pushNotificationListViewCoordinator = State( - initialValue: PushNotificationListViewCoordinator(container: container) + initialValue: dependencies.pushNotificationListViewCoordinator ) - self._profileViewCoordinator = State(initialValue: ProfileViewCoordinator(container: container)) + self._profileViewCoordinator = State(initialValue: dependencies.profileViewCoordinator) + self.todoViewModelFactory = dependencies.todoViewModelFactory self.windowEvent = windowEvent self._selectedTab = selectedTab } - var body: some View { + public var body: some View { Group { if let selectedTab { if isCompactLayout { @@ -132,7 +133,8 @@ struct MainView: View { } content: { PushNotificationListView( coordinator: pushNotificationListViewCoordinator, - isCompactLayout: isCompactLayout + isCompactLayout: isCompactLayout, + todoViewModelFactory: todoViewModelFactory ) .navigationSplitViewColumnWidth(min: 350, ideal: 450, max: nil) } detail: { @@ -141,7 +143,8 @@ struct MainView: View { TodoDetailView( viewModel: pushNotificationListViewCoordinator.makeTodoDetailViewModel( todoId: todoId - ) + ), + todoViewModelFactory: todoViewModelFactory ) .id(todoId) } else { @@ -215,7 +218,8 @@ struct MainView: View { private var homeContentView: some View { HomeView( coordinator: homeViewCoordinator, - isCompactLayout: isCompactLayout + isCompactLayout: isCompactLayout, + todoViewModelFactory: todoViewModelFactory ) } @@ -244,11 +248,15 @@ struct MainView: View { switch homeRoute { case .category(let item): TodoListView( - viewModel: todoWindowCoordinator.makeListViewModel(category: item.todoCategory) + viewModel: todoWindowCoordinator.makeListViewModel(category: item.todoCategory), + todoViewModelFactory: todoViewModelFactory ) .id(item.id) case .todo(let item): - TodoDetailView(viewModel: todoWindowCoordinator.makeDetailViewModel(todoId: item.id)) + TodoDetailView( + viewModel: todoWindowCoordinator.makeDetailViewModel(todoId: item.id), + todoViewModelFactory: todoViewModelFactory + ) .id(item.id) case .webPage(let item): WebView(url: item.url) @@ -311,7 +319,10 @@ struct MainView: View { private func todayDestinationView(_ todayRoute: TodayRoute) -> some View { switch todayRoute { case .todo(let item): - TodoDetailView(viewModel: todoWindowCoordinator.makeDetailViewModel(todoId: item.id)) + TodoDetailView( + viewModel: todoWindowCoordinator.makeDetailViewModel(todoId: item.id), + todoViewModelFactory: todoViewModelFactory + ) .id(item.id) } } @@ -319,14 +330,16 @@ struct MainView: View { private var notificationView: some View { PushNotificationListView( coordinator: pushNotificationListViewCoordinator, - isCompactLayout: isCompactLayout + isCompactLayout: isCompactLayout, + todoViewModelFactory: todoViewModelFactory ) } private var profileView: some View { ProfileView( coordinator: profileViewCoordinator, - isCompactLayout: isCompactLayout + isCompactLayout: isCompactLayout, + todoViewModelFactory: todoViewModelFactory ) } @@ -356,7 +369,10 @@ struct MainView: View { private func profileRegularDestinationView(_ route: ProfileRoute) -> some View { switch route { case .activity(let todoId): - TodoDetailView(viewModel: profileViewCoordinator.makeTodoDetailViewModel(todoId: todoId)) + TodoDetailView( + viewModel: profileViewCoordinator.makeTodoDetailViewModel(todoId: todoId), + todoViewModelFactory: todoViewModelFactory + ) .id(todoId) case .settings: SettingView(viewModel: profileViewCoordinator.settingViewModel) diff --git a/Application/DevLogUI/Sources/Profile/HeatmapView.swift b/Application/DevLogUI/Sources/Profile/HeatmapView.swift index 40082cae..635afea8 100644 --- a/Application/DevLogUI/Sources/Profile/HeatmapView.swift +++ b/Application/DevLogUI/Sources/Profile/HeatmapView.swift @@ -1,17 +1,17 @@ // // HeatmapView.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 3/2/26. // import SwiftUI -import DevLogCore +import DevLogPresentation struct HeatmapView: View { @State private var availableWidth = CGFloat.zero let quarter: HeatmapQuarter - let selectedActivityKinds: Set + let selectedActivityKindItems: Set let selectedDay: HeatmapDay? let onSelectDay: (HeatmapDay) -> Void @@ -28,7 +28,7 @@ struct HeatmapView: View { month: month, maxCount: maxCount, layout: layout, - selectedActivityKinds: selectedActivityKinds, + selectedActivityKindItems: selectedActivityKindItems, selectedDay: selectedDay, onSelectDay: onSelectDay ) @@ -60,13 +60,13 @@ struct HeatmapView: View { private func dayCount(for day: HeatmapDay) -> Int { var value = 0 - if selectedActivityKinds.contains(.created) { + if selectedActivityKindItems.contains(.created) { value += day.createdCount } - if selectedActivityKinds.contains(.completed) { + if selectedActivityKindItems.contains(.completed) { value += day.completedCount } - if selectedActivityKinds.contains(.deleted) { + if selectedActivityKindItems.contains(.deleted) { value += day.deletedCount } return value @@ -114,7 +114,7 @@ private struct MonthCompactHeatmapView: View { let month: HeatmapMonth let maxCount: Int let layout: HeatmapLayout - let selectedActivityKinds: Set + let selectedActivityKindItems: Set let selectedDay: HeatmapDay? let onSelectDay: (HeatmapDay) -> Void private let orderedWeekdays = Array(1...7) @@ -185,13 +185,13 @@ private struct MonthCompactHeatmapView: View { private func dayCount(for day: HeatmapDay) -> Int { var value = 0 - if selectedActivityKinds.contains(.created) { + if selectedActivityKindItems.contains(.created) { value += day.createdCount } - if selectedActivityKinds.contains(.completed) { + if selectedActivityKindItems.contains(.completed) { value += day.completedCount } - if selectedActivityKinds.contains(.deleted) { + if selectedActivityKindItems.contains(.deleted) { value += day.deletedCount } return value diff --git a/Application/DevLogUI/Sources/Profile/ProfileView.swift b/Application/DevLogUI/Sources/Profile/ProfileView.swift index 25727f13..33f36769 100644 --- a/Application/DevLogUI/Sources/Profile/ProfileView.swift +++ b/Application/DevLogUI/Sources/Profile/ProfileView.swift @@ -1,17 +1,17 @@ // // ProfileView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/7/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct ProfileView: View { let coordinator: ProfileViewCoordinator let isCompactLayout: Bool + let todoViewModelFactory: TodoViewModelFactory @FocusState private var focused: Bool var body: some View { @@ -151,7 +151,10 @@ struct ProfileView: View { SettingView(viewModel: coordinator.settingViewModel) .environment(coordinator.router) case .activity(let todoId): - TodoDetailView(viewModel: coordinator.makeTodoDetailViewModel(todoId: todoId)) + TodoDetailView( + viewModel: coordinator.makeTodoDetailViewModel(todoId: todoId), + todoViewModelFactory: todoViewModelFactory + ) case .theme: ThemeView( theme: Binding( @@ -181,7 +184,7 @@ struct ProfileView: View { if let quarter = coordinator.viewModel.state.activityQuarter { HeatmapView( quarter: quarter, - selectedActivityKinds: coordinator.viewModel.state.selectedActivityKinds, + selectedActivityKindItems: coordinator.viewModel.selectedActivityKindItems, selectedDay: coordinator.viewModel.state.selectedDay, onSelectDay: { coordinator.viewModel.send(.selectDay($0)) } ) @@ -223,26 +226,14 @@ struct ProfileView: View { activityKindItem.title, isOn: Binding( get: { - guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { - return false - } - return coordinator.viewModel.state.selectedActivityKinds.contains(activityKind) + coordinator.viewModel.isSelected(activityKindItem) }, set: { _ in - guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { - return - } - coordinator.viewModel.send(.toggleActivityKind(activityKind)) + coordinator.viewModel.toggle(activityKindItem) } ) ) - .disabled({ - guard let activityKind = ActivityKind(rawValue: activityKindItem.rawValue) else { - return false - } - return coordinator.viewModel.state.selectedActivityKinds.count == 1 - && coordinator.viewModel.state.selectedActivityKinds.contains(activityKind) - }()) + .disabled(coordinator.viewModel.isOnlySelected(activityKindItem)) } } label: { Image(systemName: "line.3.horizontal.decrease") @@ -431,11 +422,3 @@ struct ProfileView: View { ) } } - -enum ProfileRoute: Hashable { - case settings - case activity(String) - case theme - case pushNotification - case account -} diff --git a/Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift b/Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift index a33d41d9..f61211f4 100644 --- a/Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift +++ b/Application/DevLogUI/Sources/PushNotification/PushNotificationListView.swift @@ -1,13 +1,12 @@ // // PushNotificationListView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/14/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct PushNotificationListView: View { @Environment(\.colorScheme) private var colorScheme @@ -17,6 +16,7 @@ struct PushNotificationListView: View { @State private var isScrollTrackingEnabled = false let coordinator: PushNotificationListViewCoordinator let isCompactLayout: Bool + let todoViewModelFactory: TodoViewModelFactory private var viewModel: PushNotificationListViewModel { coordinator.viewModel @@ -67,7 +67,10 @@ struct PushNotificationListView: View { } )) { item in NavigationStack { - TodoDetailView(viewModel: coordinator.makeTodoDetailViewModel(todoId: item.id)) + TodoDetailView( + viewModel: coordinator.makeTodoDetailViewModel(todoId: item.id), + todoViewModelFactory: todoViewModelFactory + ) .id(item.id) .toolbar { ToolbarLeadingButton { @@ -241,7 +244,7 @@ struct PushNotificationListView: View { get: { viewModel.state.query.timeFilter }, set: { viewModel.send(.setTimeFilter($0)) } )) { - ForEach(PushNotificationQuery.TimeFilter.availableOptions, id: \.self) { option in + ForEach(PushNotificationListViewModel.TimeFilter.availableOptions, id: \.self) { option in Text(option.title).tag(option) } } label: { diff --git a/Application/DevLogUI/Sources/Search/SearchView.swift b/Application/DevLogUI/Sources/Search/SearchView.swift index 27616391..717d69ae 100644 --- a/Application/DevLogUI/Sources/Search/SearchView.swift +++ b/Application/DevLogUI/Sources/Search/SearchView.swift @@ -1,19 +1,18 @@ // // SearchView.swift -// DevLogPresentation +// DevLogUI // // Created by 최윤진 on 2/12/26. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct SearchView: View { @Environment(\.dismiss) private var dismiss - @Environment(\.diContainer) private var container: DIContainer @State private var router = NavigationRouter() @State var viewModel: SearchViewModel + let todoViewModelFactory: TodoViewModelFactory var body: some View { NavigationStack(path: $router.path) { @@ -21,11 +20,10 @@ struct SearchView: View { .navigationDestination(for: Path.self) { path in switch path { case .todo(let todoId): - TodoDetailView(viewModel: TodoDetailViewModel( - fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - todoId: todoId - )) + TodoDetailView( + viewModel: todoViewModelFactory.makeDetailViewModel(todoId: todoId), + todoViewModelFactory: todoViewModelFactory + ) case .web(let page): WebView(url: page.url) .ignoresSafeArea() diff --git a/Application/DevLogUI/Sources/Setting/AccountView.swift b/Application/DevLogUI/Sources/Setting/AccountView.swift index 87602858..dfbb3159 100644 --- a/Application/DevLogUI/Sources/Setting/AccountView.swift +++ b/Application/DevLogUI/Sources/Setting/AccountView.swift @@ -1,12 +1,12 @@ // // AccountView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/14/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct AccountView: View { @State var viewModel: AccountViewModel @@ -21,7 +21,7 @@ struct AccountView: View { } } Section(String(localized: "account_social_section")) { - let providers = AuthProvider.allCases.filter { $0 != viewModel.state.currentProvider } + let providers = AccountViewModel.Provider.allCases.filter { $0 != viewModel.state.currentProvider } ForEach(providers, id: \.self) { provider in let isConnected = viewModel.state.connectedProviders.contains(provider) HStack { @@ -76,7 +76,7 @@ struct AccountView: View { } } - private func formattedProviderName(_ provider: AuthProvider) -> String { + private func formattedProviderName(_ provider: AccountViewModel.Provider) -> String { let rawValue = provider.rawValue let providerPrefix = rawValue.prefix(1).uppercased() let providerSuffix = rawValue.dropFirst().prefix(while: { $0 != "." }) @@ -84,7 +84,7 @@ struct AccountView: View { } @ViewBuilder - private func providerContent(_ provider: AuthProvider) -> some View { + private func providerContent(_ provider: AccountViewModel.Provider) -> some View { Image(formattedProviderName(provider)) .resizable() .scaledToFit() diff --git a/Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift b/Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift index 3ec43a07..b99898c6 100644 --- a/Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift +++ b/Application/DevLogUI/Sources/Setting/PushNotificationSettingsView.swift @@ -1,12 +1,12 @@ // // PushNotificationSettingsView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/14/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct PushNotificationSettingsView: View { @State var viewModel: PushNotificationSettingsViewModel diff --git a/Application/DevLogUI/Sources/Setting/SettingView.swift b/Application/DevLogUI/Sources/Setting/SettingView.swift index 91bd74e7..103e1efc 100644 --- a/Application/DevLogUI/Sources/Setting/SettingView.swift +++ b/Application/DevLogUI/Sources/Setting/SettingView.swift @@ -1,12 +1,12 @@ // // SettingView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/6/25. // import SwiftUI -import DevLogDomain +import DevLogPresentation struct SettingView: View { @Environment(NavigationRouter.self) private var router diff --git a/Application/DevLogUI/Sources/Setting/ThemeView.swift b/Application/DevLogUI/Sources/Setting/ThemeView.swift index a939fdc7..fbb6d0db 100644 --- a/Application/DevLogUI/Sources/Setting/ThemeView.swift +++ b/Application/DevLogUI/Sources/Setting/ThemeView.swift @@ -1,16 +1,15 @@ // // ThemeView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 5/6/25. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct ThemeView: View { - @Binding var theme: SystemTheme + @Binding var theme: SettingViewModel.Theme var body: some View { List { @@ -18,7 +17,7 @@ struct ThemeView: View { theme = .automatic }) { HStack { - Text(SystemTheme.automatic.localizedName) + Text(SettingViewModel.Theme.automatic.localizedName) .foregroundStyle(Color.primary) Spacer() if theme == .automatic { @@ -30,7 +29,7 @@ struct ThemeView: View { theme = .light }) { HStack { - Text(SystemTheme.light.localizedName) + Text(SettingViewModel.Theme.light.localizedName) .foregroundStyle(Color.primary) Spacer() if theme == .light { @@ -42,7 +41,7 @@ struct ThemeView: View { theme = .dark }) { HStack { - Text(SystemTheme.dark.localizedName) + Text(SettingViewModel.Theme.dark.localizedName) .foregroundStyle(Color.primary) Spacer() if theme == .dark { diff --git a/Application/DevLogUI/Sources/Today/TodayView.swift b/Application/DevLogUI/Sources/Today/TodayView.swift index 7db59ef9..f98e68a3 100644 --- a/Application/DevLogUI/Sources/Today/TodayView.swift +++ b/Application/DevLogUI/Sources/Today/TodayView.swift @@ -1,13 +1,12 @@ // // TodayView.swift -// DevLogPresentation +// DevLogUI // // Created by opfic on 3/6/26. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation struct TodayView: View { let coordinator: TodayViewCoordinator @@ -85,7 +84,7 @@ struct TodayView: View { set: { coordinator.viewModel.send(.setDueDateVisibility($0)) } ) ) { - ForEach(TodayDisplayOptions.DueDateVisibility.allCases, id: \.self) { option in + ForEach(TodayViewModel.DueDateVisibility.allCases, id: \.self) { option in Text(option.title).tag(option) } } @@ -212,11 +211,7 @@ struct TodayView: View { } } -enum TodayRoute: Hashable { - case todo(TodoIdItem) -} - -private extension TodayDisplayOptions.DueDateVisibility { +private extension TodayViewModel.DueDateVisibility { var title: String { switch self { case .all: From a23bf2ab9a37c10781de4114cdf7754a3349941f Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:35:13 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor:=20App=20=EC=A7=84=EC=9E=85=20Vi?= =?UTF-8?q?ew=20=EC=A1=B0=EB=A6=BD=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DevLogApp/Sources/App/DevLogApp.swift | 11 ++-- .../Sources/App/Scene/RootView.swift | 61 ++++++++----------- .../App/Scene/TodoEditorWindowView.swift | 55 +++++------------ 3 files changed, 46 insertions(+), 81 deletions(-) diff --git a/Application/DevLogApp/Sources/App/DevLogApp.swift b/Application/DevLogApp/Sources/App/DevLogApp.swift index 1a2dca6c..437d1306 100644 --- a/Application/DevLogApp/Sources/App/DevLogApp.swift +++ b/Application/DevLogApp/Sources/App/DevLogApp.swift @@ -10,6 +10,7 @@ import DevLogCore import DevLogData import DevLogDomain import DevLogPresentation +import DevLogUI @main struct DevLogApp: App { @@ -25,10 +26,7 @@ struct DevLogApp: App { var body: some Scene { WindowGroup { RootView( - sessionUseCase: container.resolve(ObserveAuthSessionUseCase.self), - networkConnectivityUseCase: container.resolve(ObserveNetworkConnectivityUseCase.self), - systemThemeUseCase: container.resolve(ObserveSystemThemeUseCase.self), - trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), + dependencies: RootViewDependencies(container: container), widgetURLTab: { MainTab(widgetURL: $0) }, windowEvent: windowEvent, pushNotificationTodoIdPublisher: PushNotificationRoute.shared.observe(), @@ -44,7 +42,10 @@ struct DevLogApp: App { if let value = value.wrappedValue { TodoEditorWindowView( value: value, - windowEvent: windowEvent + dependencies: TodoEditorWindowDependencies( + container: container, + windowEvent: windowEvent + ) ) .autocorrectionDisabled() } else { diff --git a/Application/DevLogApp/Sources/App/Scene/RootView.swift b/Application/DevLogApp/Sources/App/Scene/RootView.swift index b74658b2..610c01d0 100644 --- a/Application/DevLogApp/Sources/App/Scene/RootView.swift +++ b/Application/DevLogApp/Sources/App/Scene/RootView.swift @@ -1,18 +1,17 @@ // // RootView.swift -// DevLogPresentation +// DevLog // // Created by opfic on 5/2/25. // import SwiftUI +import DevLogPresentation +import DevLogUI import Combine -import DevLogCore -import DevLogDomain -public struct RootView: View { - @Environment(\.diContainer) var container: DIContainer - @State var viewModel: RootViewModel +struct RootView: View { + @State private var dependencies: RootViewDependencies @State private var selectedRoute: Route? @State private var selectedMainTab: MainTab? private let widgetURLTab: (URL) -> MainTab? @@ -20,48 +19,38 @@ public struct RootView: View { private let pushNotificationTodoIdPublisher: AnyPublisher private let clearPushNotificationRoute: () -> Void - public init( - sessionUseCase: ObserveAuthSessionUseCase, - networkConnectivityUseCase: ObserveNetworkConnectivityUseCase, - systemThemeUseCase: ObserveSystemThemeUseCase, - trackAnalyticsEventUseCase: TrackAnalyticsEventUseCase, + init( + dependencies: RootViewDependencies, widgetURLTab: @escaping (URL) -> MainTab?, windowEvent: TodoEditorWindowEvent, pushNotificationTodoIdPublisher: AnyPublisher, clearPushNotificationRoute: @escaping () -> Void ) { - self._viewModel = State(initialValue: RootViewModel( - sessionUseCase: sessionUseCase, - networkConnectivityUseCase: networkConnectivityUseCase, - systemThemeUseCase: systemThemeUseCase, - trackAnalyticsEventUseCase: trackAnalyticsEventUseCase - )) + self._dependencies = State(initialValue: dependencies) self.widgetURLTab = widgetURLTab self.windowEvent = windowEvent self.pushNotificationTodoIdPublisher = pushNotificationTodoIdPublisher self.clearPushNotificationRoute = clearPushNotificationRoute } - public var body: some View { + var body: some View { ZStack { Color(UIColor.systemGroupedBackground).ignoresSafeArea() - if let signIn = viewModel.state.signIn { + if let signIn = dependencies.viewModel.state.signIn { if signIn { MainView( - container: container, + dependencies: dependencies.mainViewDependencies, windowEvent: windowEvent, selectedTab: $selectedMainTab ) } else { - LoginView(viewModel: LoginViewModel( - signInUseCase: container.resolve(SignInUseCase.self)) - ) + LoginView(viewModel: dependencies.makeLoginViewModel()) } } } - .preferredColorScheme(viewModel.state.theme.colorScheme) - .onAppear { viewModel.send(.onAppear) } - .onChange(of: viewModel.state.signIn) { _, value in + .preferredColorScheme(dependencies.viewModel.state.theme.colorScheme) + .onAppear { dependencies.viewModel.send(.onAppear) } + .onChange(of: dependencies.viewModel.state.signIn) { _, value in guard let value else { return } if value { selectedMainTab = .home @@ -71,7 +60,7 @@ public struct RootView: View { } .onOpenURL { url in guard let mainTab = widgetURLTab(url) else { return } - switch viewModel.state.signIn { + switch dependencies.viewModel.state.signIn { case .some(false): break case .some(true): @@ -80,24 +69,22 @@ public struct RootView: View { break } } - .alert(viewModel.state.alertTitle, isPresented: Binding( - get: { viewModel.state.showAlert }, - set: { viewModel.send(.setAlert($0)) } + .alert(dependencies.viewModel.state.alertTitle, isPresented: Binding( + get: { dependencies.viewModel.state.showAlert }, + set: { dependencies.viewModel.send(.setAlert($0)) } )) { Button(String(localized: "common_close"), role: .cancel) { } } message: { - Text(viewModel.state.alertMessage) + Text(dependencies.viewModel.state.alertMessage) } .sheet(item: $selectedRoute) { route in switch route { case .todoDetail(let todoId): NavigationStack { - TodoDetailView(viewModel: TodoDetailViewModel( - fetchTodoUseCase: container.resolve(FetchTodoByIdUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - todoId: todoId, - showEditButton: false - )) + TodoDetailView( + viewModel: dependencies.makeTodoDetailViewModel(todoId), + todoViewModelFactory: dependencies.mainViewDependencies.todoViewModelFactory + ) .toolbar { ToolbarLeadingButton { selectedRoute = nil diff --git a/Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift b/Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift index fa95eac0..effbf082 100644 --- a/Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift +++ b/Application/DevLogApp/Sources/App/Scene/TodoEditorWindowView.swift @@ -1,66 +1,43 @@ // // TodoEditorWindowView.swift -// DevLogPresentation +// DevLog // // Created by opfic on 5/31/26. // import SwiftUI -import DevLogCore -import DevLogDomain +import DevLogPresentation +import DevLogUI -public struct TodoEditorWindowView: View { - @Environment(\.diContainer) private var container: DIContainer +struct TodoEditorWindowView: View { @State private var windowScene: UIWindowScene? private let value: TodoEditorWindowValue - private let windowEvent: TodoEditorWindowEvent + private let dependencies: TodoEditorWindowDependencies - public init( + init( value: TodoEditorWindowValue, - windowEvent: TodoEditorWindowEvent + dependencies: TodoEditorWindowDependencies ) { self.value = value - self.windowEvent = windowEvent + self.dependencies = dependencies } - public var body: some View { + var body: some View { Group { - switch value { - case .create(let windowCategory, _): - TodoEditorView( - viewModel: TodoEditorViewModel( - category: windowCategory.todoCategory, - fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), - trackAnalyticsEventUseCase: container.resolve(TrackAnalyticsEventUseCase.self), - onUpsertSuccess: upsert - ), + TodoEditorView( + viewModel: dependencies.makeEditorViewModel( + value: value, onClose: closeWindow - ) - case .edit(let windowTodo): - TodoEditorView( - viewModel: TodoEditorViewModel( - todo: windowTodo.todo, - fetchPreferencesUseCase: container.resolve(FetchTodoCategoryPreferencesUseCase.self), - fetchReferenceItemsUseCase: container.resolve(FetchReferenceItemsUseCase.self), - upsertTodoUseCase: container.resolve(UpsertTodoUseCase.self), - onUpsertSuccess: upsert - ), - onClose: closeWindow - ) - } + ), + todoViewModelFactory: dependencies.todoViewModelFactory, + onClose: closeWindow + ) } .background { WindowSceneReader { windowScene = $0 } } } - private func upsert(_ todo: Todo) { - windowEvent.submit(value: value, todo: todo) - closeWindow() - } - private func closeWindow() { guard let windowScene else { return } UIApplication.shared.requestSceneSessionDestruction( From 3e09509a8185c9d635131d3d32cfb29e27188f29 Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:48:54 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20ViewModel=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project.pbxproj | 192 ++++++------------ .../{Setting => }/AccountViewModel.swift | 0 .../ViewModel/{Home => }/HomeViewModel.swift | 0 .../{Login => }/LoginViewModel.swift | 0 .../ViewModel/{Main => }/MainViewModel.swift | 0 .../{Profile => }/ProfileViewModel.swift | 0 .../PushNotificationListViewModel.swift | 0 .../PushNotificationSettingsViewModel.swift | 0 .../ViewModel/{Root => }/RootViewModel.swift | 0 .../{Search => }/SearchViewModel.swift | 0 .../{Setting => }/SettingViewModel.swift | 0 .../{Today => }/TodayViewModel.swift | 0 .../{Home => }/TodoDetailViewModel.swift | 0 .../{Home => }/TodoEditorViewModel.swift | 0 .../{Home => }/TodoListViewModel.swift | 0 .../{Home => }/TodoManageViewModel.swift | 0 16 files changed, 60 insertions(+), 132 deletions(-) rename Application/DevLogPresentation/Sources/ViewModel/{Setting => }/AccountViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Home => }/HomeViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Login => }/LoginViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Main => }/MainViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Profile => }/ProfileViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{PushNotification => }/PushNotificationListViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Setting => }/PushNotificationSettingsViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Root => }/RootViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Search => }/SearchViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Setting => }/SettingViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Today => }/TodayViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Home => }/TodoDetailViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Home => }/TodoEditorViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Home => }/TodoListViewModel.swift (100%) rename Application/DevLogPresentation/Sources/ViewModel/{Home => }/TodoManageViewModel.swift (100%) diff --git a/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj b/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj index 1117f7e9..ebc2034c 100644 --- a/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj +++ b/Application/DevLogPresentation/DevLogPresentation.xcodeproj/project.pbxproj @@ -10,9 +10,7 @@ 03CF7E696626224FFE93FFDD /* TodoReferenceItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B8F3DEEF6527F9FBCBDCD5A /* TodoReferenceItem.swift */; }; 053BC20B9244F93FFE9E6FA7 /* UserTodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10169ED43745C8286BAA560A /* UserTodoCategoryItem.swift */; }; 09A7C0CA26E4129EBADE0928 /* TodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE04D300F1054596E630CF48 /* TodoCategoryItem.swift */; }; - 0A25E266F29F6ACD7E6154EE /* PushNotificationListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */; }; 0C65DE6F8B9FB06F8D121D1E /* TodoViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D87C5787A3E9EAD0CC10A3D /* TodoViewModelFactory.swift */; }; - 0DA6A035B08B2E1FA91A5CCA /* TodoEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */; }; 116BB487A24975CAAD4AC940 /* MarkdownUI in Frameworks */ = {isa = PBXBuildFile; productRef = 56A49A4AE77CECF9ABEC6861 /* MarkdownUI */; }; 173C43896990D2469CB29D6B /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38030D2CAA016ABB3D0C396B /* Store.swift */; }; 26ED8F658B02153735BD8692 /* Color+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852D34A35C60375D1D9F9566 /* Color+Hex.swift */; }; @@ -21,39 +19,42 @@ 2C9840C424A0D3C85D1001C9 /* TestSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5156DCFD77B78CAEE004CDDD /* TestSupport.swift */; }; 2DB84D2FBEA0653D48DF614F /* HeatmapDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70B652BF58D45805A57ECCE0 /* HeatmapDay.swift */; }; 336D5F52E964A099E10AECFF /* TodoListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB658B8B1246F4399493FE3 /* TodoListItem.swift */; }; - 34151EB8B72D12C8D373F567 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */; }; 34AFBED9DAEBD1F4E4A2DB2B /* TodoIdItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08ACC3D94A90881383764E6C /* TodoIdItem.swift */; }; + 34DFDBE6AC68454DD2A9B548 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 179B4DC72A2C2994456F609A /* LoginViewModel.swift */; }; 35639553522A1CEFDCF455D7 /* TodoEditorWindowValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9206293A713E904877705C2 /* TodoEditorWindowValue.swift */; }; - 38BA6B9310BB45F46683D105 /* TodoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */; }; + 35649E3226AD3D47FB9D2C59 /* RootViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91689B5FE51289C142DFD6BC /* RootViewModel.swift */; }; 3D0FB9275F7BC7D914D8EC55 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F895EDEF78B5D98FB2A38 /* NavigationRouter.swift */; }; 3F8512559CCF262222ACCAE2 /* RootViewDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7A86BE16165EE865C2CCB1 /* RootViewDependencies.swift */; }; 41A5C4626505C6BF0643E43B /* MainTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290DE2215D7061AC10A057D8 /* MainTab.swift */; }; 4BE7032EE7146793A5C58A94 /* ActivityKindItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09CC8A2FCF1577B150A08D83 /* ActivityKindItem.swift */; }; + 4C1B42EE18ECF68DE71DBE47 /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 482E7887408590D8E856673B /* MainViewModel.swift */; }; + 4E725B56D14497FA73132F9F /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91B75A48E6680752B9DE82C9 /* HomeViewModel.swift */; }; + 4ED29B9BB4B0F12363BFB927 /* TodoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAD6E606DC53732CA7DECB2D /* TodoDetailViewModel.swift */; }; 5357B7DBEC07C590B8C70E20 /* TodayRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1E4F3FA850AB900BD0837A /* TodayRoute.swift */; }; - 5529852916250307CEDF2210 /* RootViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */; }; - 5DDA91AD574C37E26C667F24 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */; }; + 5DCFBD39AF6AC33B30265D73 /* PushNotificationListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACD429F304D34C5345FCD425 /* PushNotificationListViewModel.swift */; }; 5E9F72DE540DFEC1518CDDAE /* RecentTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A6CF5AAB9CCEAB35FB10A8 /* RecentTodoItem.swift */; }; 65BFE2061C37BC86E811266E /* SystemTodoCategoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0CBB0EEB3B15A4BE2EF9641 /* SystemTodoCategoryItem.swift */; }; - 6E428FE9D2F09F9696B4BB52 /* SettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */; }; + 6DCE29BCA008EFF51A476D7D /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D3F311FECBA18B5EE105FD2 /* SearchViewModel.swift */; }; 6F7ED28364309E79840E1B1A /* DeleteWebPageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37323FDF36DF44C549A71A85 /* DeleteWebPageTests.swift */; }; - 7BAB031CACEE7F60CC0A14D9 /* TodoListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */; }; + 7B3DB4474B7B6C2E948A277C /* PushNotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC66A467D5E3A2EB391E90DE /* PushNotificationSettingsViewModel.swift */; }; 91A04437CA63E957BDD1A060 /* TodayTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B2119664DB4FDF4A18FFE /* TodayTodoItem.swift */; }; 92DAE6E67927B3014F7FB18A /* PushNotificationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C7A0A3DE0AB6D5E4DD116B /* PushNotificationItem.swift */; }; - 99EFDC252204B10E9D40C261 /* PushNotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */; }; - A638A1BE16A54E3211622438 /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 694B2D575BBBC41B71834329 /* AccountViewModel.swift */; }; + 94358125409F95AD6FEE75F6 /* TodoListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECABD5E04C07111C89C7DDB3 /* TodoListViewModel.swift */; }; A641ED77789933A35718DC56 /* ProfileRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2DDC14187D2E0615DBF2A5E /* ProfileRoute.swift */; }; A7605511964265827B06E268 /* ProfileViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15BF430A0A932B943CE74B1 /* ProfileViewCoordinator.swift */; }; A93B2FC0C15576DDAD9F1772 /* DevLogCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70A888BE16FA57ED1309E014 /* DevLogCore.framework */; }; - AAB8401E0FE7598F54D43BFD /* TodoManageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */; }; AC7102A1D35CB1817BD885E8 /* TodoEditorWindowEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF251D17AB6A6BE27E94F83F /* TodoEditorWindowEvent.swift */; }; + AD05101B81F4D267A87AC7A7 /* SettingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776EC7BA6989C8AEE6BBB558 /* SettingViewModel.swift */; }; AD97294A20E386D840EADDDB /* MainViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD678C679B9975DFD646F8FE /* MainViewCoordinator.swift */; }; + ADFE22BA856BD7974978B222 /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81D2699575F2C695C72E294D /* AccountViewModel.swift */; }; AECD97E6C980B7940A3112E4 /* Error+SocialLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B6F1C309AC57614AD630F79 /* Error+SocialLogin.swift */; }; B11D48231BFAFAA422C7CB30 /* DevLogPresentation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D36A4E11056749B1D5DEF446 /* DevLogPresentation.framework */; }; - B947B17E4DFD433FD61EDEBF /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD96AE666281D6C27D81F773 /* HomeViewModel.swift */; }; + C2358524334557A83CFE10DE /* TodoEditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED515F28865033FBA78DCAB6 /* TodoEditorViewModel.swift */; }; C26C5A74B162EF0866093F6E /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = F44AF3158F945047473FA5E7 /* OrderedCollections */; }; - C5FD25074C105C9F278C71E6 /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */; }; + C28BB5DECB3AA31ED031D90C /* TodoManageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE61156B04A85F894BD7D2 /* TodoManageViewModel.swift */; }; C9553B4DC3249D9EC36473AC /* HomeViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 600892295632C397ECDD8AF4 /* HomeViewCoordinator.swift */; }; CB6204EC0FB8557D7FAF7174 /* HeatmapActivityItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E174814D9FFAFC79746E1902 /* HeatmapActivityItem.swift */; }; + CD9C0B62EAAB0FB928703250 /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08332CE6C5C2F9DC7B78278D /* ProfileViewModel.swift */; }; CDD5185569899FF1F600DD08 /* PushNotificationListViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7822B9271036D58AB46DB3 /* PushNotificationListViewCoordinator.swift */; }; D73622D51033A4BAF3B68DAC /* HeatmapMonth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD8C6D9E12E040F7B612FB1 /* HeatmapMonth.swift */; }; D7D6E761D1C930C71E445FC6 /* TodoWindowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04907C8B1F51AC9D8A164F02 /* TodoWindowCoordinator.swift */; }; @@ -61,11 +62,10 @@ D878C47DE4B2E1A9525FBCBF /* LoadingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14DA5CF22287DA889A033F8E /* LoadingState.swift */; }; DA951ACBCB7C625E36B2E709 /* HomeRoute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82BEFB32E7D34AB261823961 /* HomeRoute.swift */; }; DC04D254D882504D1F00F609 /* TodayViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92080C40972043791AC990C /* TodayViewCoordinator.swift */; }; - DC2E2AB959A0EB7A28344690 /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4870173271638E9190A3E93B /* MainViewModel.swift */; }; DCD8775B3F51592DD956952F /* HeatmapQuarter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 573AD2720FA89362FF4C4CEF /* HeatmapQuarter.swift */; }; + E1AC015EB5592C1F39C252BB /* TodayViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA69EA219374DD1E040CBA4B /* TodayViewModel.swift */; }; E95BB5F53AE62F152798567D /* DevLogDomain.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 950469A44DFD1834A6BFC4B2 /* DevLogDomain.framework */; }; F62CD09589BE8D580A4197B3 /* MainViewDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6320220D0E377BC611B291CA /* MainViewDependencies.swift */; }; - FB83D3B1D387EB6E5E3F76BA /* ProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C773450E521557929ED525E /* ProfileViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -103,49 +103,48 @@ /* Begin PBXFileReference section */ 04907C8B1F51AC9D8A164F02 /* TodoWindowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoWindowCoordinator.swift; sourceTree = ""; }; + 08332CE6C5C2F9DC7B78278D /* ProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; 08ACC3D94A90881383764E6C /* TodoIdItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoIdItem.swift; sourceTree = ""; }; 09CC8A2FCF1577B150A08D83 /* ActivityKindItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityKindItem.swift; sourceTree = ""; }; 0B8F3DEEF6527F9FBCBDCD5A /* TodoReferenceItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoReferenceItem.swift; sourceTree = ""; }; - 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewModel.swift; sourceTree = ""; }; 0EB658B8B1246F4399493FE3 /* TodoListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListItem.swift; sourceTree = ""; }; 10169ED43745C8286BAA560A /* UserTodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserTodoCategoryItem.swift; sourceTree = ""; }; 14DA5CF22287DA889A033F8E /* LoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingState.swift; sourceTree = ""; }; 160AF2C6625745DEFB4DB23C /* DevLogPresentationTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DevLogPresentationTests-Info.plist"; sourceTree = ""; }; + 179B4DC72A2C2994456F609A /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; 1B6F1C309AC57614AD630F79 /* Error+SocialLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+SocialLogin.swift"; sourceTree = ""; }; 290DE2215D7061AC10A057D8 /* MainTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTab.swift; sourceTree = ""; }; - 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModel.swift; sourceTree = ""; }; - 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewModel.swift; sourceTree = ""; }; - 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModel.swift; sourceTree = ""; }; 34C7A0A3DE0AB6D5E4DD116B /* PushNotificationItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationItem.swift; sourceTree = ""; }; - 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailViewModel.swift; sourceTree = ""; }; 37323FDF36DF44C549A71A85 /* DeleteWebPageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteWebPageTests.swift; sourceTree = ""; }; 38030D2CAA016ABB3D0C396B /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = ""; }; - 4870173271638E9190A3E93B /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; - 4C773450E521557929ED525E /* ProfileViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewModel.swift; sourceTree = ""; }; + 482E7887408590D8E856673B /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; 4CD8C6D9E12E040F7B612FB1 /* HeatmapMonth.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapMonth.swift; sourceTree = ""; }; 4D87C5787A3E9EAD0CC10A3D /* TodoViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoViewModelFactory.swift; sourceTree = ""; }; 4E7A86BE16165EE865C2CCB1 /* RootViewDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewDependencies.swift; sourceTree = ""; }; 5156DCFD77B78CAEE004CDDD /* TestSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSupport.swift; sourceTree = ""; }; 573AD2720FA89362FF4C4CEF /* HeatmapQuarter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapQuarter.swift; sourceTree = ""; }; 587B2119664DB4FDF4A18FFE /* TodayTodoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayTodoItem.swift; sourceTree = ""; }; - 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageViewModel.swift; sourceTree = ""; }; 600892295632C397ECDD8AF4 /* HomeViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewCoordinator.swift; sourceTree = ""; }; 62A6CF5AAB9CCEAB35FB10A8 /* RecentTodoItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentTodoItem.swift; sourceTree = ""; }; 6320220D0E377BC611B291CA /* MainViewDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewDependencies.swift; sourceTree = ""; }; - 694B2D575BBBC41B71834329 /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = ""; }; 6AC3FF6088F0D784788A2E07 /* DevLogPresentationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DevLogPresentationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorViewModel.swift; sourceTree = ""; }; 70A888BE16FA57ED1309E014 /* DevLogCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 70B652BF58D45805A57ECCE0 /* HeatmapDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapDay.swift; sourceTree = ""; }; + 776EC7BA6989C8AEE6BBB558 /* SettingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewModel.swift; sourceTree = ""; }; + 7D3F311FECBA18B5EE105FD2 /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; + 81D2699575F2C695C72E294D /* AccountViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewModel.swift; sourceTree = ""; }; 82BEFB32E7D34AB261823961 /* HomeRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeRoute.swift; sourceTree = ""; }; 852D34A35C60375D1D9F9566 /* Color+Hex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Hex.swift"; sourceTree = ""; }; + 87EE61156B04A85F894BD7D2 /* TodoManageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageViewModel.swift; sourceTree = ""; }; 8C76C1FD0B57BC6E736F16F9 /* TodoEditorWindowDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowDependencies.swift; sourceTree = ""; }; + 91689B5FE51289C142DFD6BC /* RootViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewModel.swift; sourceTree = ""; }; + 91B75A48E6680752B9DE82C9 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; 950469A44DFD1834A6BFC4B2 /* DevLogDomain.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogDomain.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A05BB3C999F4A364401871C5 /* DeletePushNotificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeletePushNotificationTests.swift; sourceTree = ""; }; ACA48428342FE3040FE708BE /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; + ACD429F304D34C5345FCD425 /* PushNotificationListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewModel.swift; sourceTree = ""; }; AD7822B9271036D58AB46DB3 /* PushNotificationListViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationListViewCoordinator.swift; sourceTree = ""; }; - B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = ""; }; - BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListViewModel.swift; sourceTree = ""; }; + BA69EA219374DD1E040CBA4B /* TodayViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewModel.swift; sourceTree = ""; }; BAD66EB3834CFD3D64831511 /* DevLogPresentation-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "DevLogPresentation-Info.plist"; sourceTree = ""; }; C0CBB0EEB3B15A4BE2EF9641 /* SystemTodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemTodoCategoryItem.swift; sourceTree = ""; }; C8D191AD793EE0AC702B1539 /* WebPageItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebPageItem.swift; sourceTree = ""; }; @@ -155,13 +154,14 @@ D36A4E11056749B1D5DEF446 /* DevLogPresentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogPresentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D92080C40972043791AC990C /* TodayViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewCoordinator.swift; sourceTree = ""; }; D92F895EDEF78B5D98FB2A38 /* NavigationRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; - DD96AE666281D6C27D81F773 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = ""; }; DE04D300F1054596E630CF48 /* TodoCategoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoCategoryItem.swift; sourceTree = ""; }; E174814D9FFAFC79746E1902 /* HeatmapActivityItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeatmapActivityItem.swift; sourceTree = ""; }; E2DDC14187D2E0615DBF2A5E /* ProfileRoute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRoute.swift; sourceTree = ""; }; - E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsViewModel.swift; sourceTree = ""; }; - EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; + ECABD5E04C07111C89C7DDB3 /* TodoListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoListViewModel.swift; sourceTree = ""; }; + ED515F28865033FBA78DCAB6 /* TodoEditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorViewModel.swift; sourceTree = ""; }; F9206293A713E904877705C2 /* TodoEditorWindowValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoEditorWindowValue.swift; sourceTree = ""; }; + FAD6E606DC53732CA7DECB2D /* TodoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoDetailViewModel.swift; sourceTree = ""; }; + FC66A467D5E3A2EB391E90DE /* PushNotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationSettingsViewModel.swift; sourceTree = ""; }; FD678C679B9975DFD646F8FE /* MainViewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewCoordinator.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -199,14 +199,6 @@ path = Structure; sourceTree = ""; }; - 18C9CF72DAC34ECA7E31E748 /* Today */ = { - isa = PBXGroup; - children = ( - 2D2C6A5CFECB43CC4BC43985 /* TodayViewModel.swift */, - ); - path = Today; - sourceTree = ""; - }; 27063F597048D820F9883728 /* Common */ = { isa = PBXGroup; children = ( @@ -335,26 +327,6 @@ path = Derived; sourceTree = ""; }; - 737FAF490D9B7B4331080E45 /* Profile */ = { - isa = PBXGroup; - children = ( - 4C773450E521557929ED525E /* ProfileViewModel.swift */, - ); - path = Profile; - sourceTree = ""; - }; - 7D6CA57DBD171C456BFEE533 /* Home */ = { - isa = PBXGroup; - children = ( - DD96AE666281D6C27D81F773 /* HomeViewModel.swift */, - 34CE41386C91A76A6966D72A /* TodoDetailViewModel.swift */, - 6D1730241C5CDFDEE209A401 /* TodoEditorViewModel.swift */, - BA2FEBAD2A9A960BFF01A4C5 /* TodoListViewModel.swift */, - 5D60DD2C50359031AC632226 /* TodoManageViewModel.swift */, - ); - path = Home; - sourceTree = ""; - }; 80795F4F20E81C1E84803EB8 /* Support */ = { isa = PBXGroup; children = ( @@ -405,14 +377,6 @@ path = Tests; sourceTree = ""; }; - CA2593D720DA024EF27E514A /* Login */ = { - isa = PBXGroup; - children = ( - B4E74A3C5F7D898253389D05 /* LoginViewModel.swift */, - ); - path = Login; - sourceTree = ""; - }; CBE2F0C6D1C3C09A2123FB42 /* Profile */ = { isa = PBXGroup; children = ( @@ -424,15 +388,21 @@ CD4F7027F750752F2BD6484D /* ViewModel */ = { isa = PBXGroup; children = ( - 7D6CA57DBD171C456BFEE533 /* Home */, - CA2593D720DA024EF27E514A /* Login */, - F7D309730F31660066D7246C /* Main */, - 737FAF490D9B7B4331080E45 /* Profile */, - DC9C55D162DD068D635BA358 /* PushNotification */, - D62728F4D18FC50778C86BF9 /* Root */, - F75E3F153FDD92A392CE9F77 /* Search */, - FAC2309E83621894414350E6 /* Setting */, - 18C9CF72DAC34ECA7E31E748 /* Today */, + 81D2699575F2C695C72E294D /* AccountViewModel.swift */, + 91B75A48E6680752B9DE82C9 /* HomeViewModel.swift */, + 179B4DC72A2C2994456F609A /* LoginViewModel.swift */, + 482E7887408590D8E856673B /* MainViewModel.swift */, + 08332CE6C5C2F9DC7B78278D /* ProfileViewModel.swift */, + ACD429F304D34C5345FCD425 /* PushNotificationListViewModel.swift */, + FC66A467D5E3A2EB391E90DE /* PushNotificationSettingsViewModel.swift */, + 91689B5FE51289C142DFD6BC /* RootViewModel.swift */, + 7D3F311FECBA18B5EE105FD2 /* SearchViewModel.swift */, + 776EC7BA6989C8AEE6BBB558 /* SettingViewModel.swift */, + BA69EA219374DD1E040CBA4B /* TodayViewModel.swift */, + FAD6E606DC53732CA7DECB2D /* TodoDetailViewModel.swift */, + ED515F28865033FBA78DCAB6 /* TodoEditorViewModel.swift */, + ECABD5E04C07111C89C7DDB3 /* TodoListViewModel.swift */, + 87EE61156B04A85F894BD7D2 /* TodoManageViewModel.swift */, ); path = ViewModel; sourceTree = ""; @@ -449,14 +419,6 @@ path = Routing; sourceTree = ""; }; - D62728F4D18FC50778C86BF9 /* Root */ = { - isa = PBXGroup; - children = ( - 2AE3B8B9E69DB7026FD689C9 /* RootViewModel.swift */, - ); - path = Root; - sourceTree = ""; - }; D68750D8827585A7F938F99E /* Project */ = { isa = PBXGroup; children = ( @@ -468,14 +430,6 @@ name = Project; sourceTree = ""; }; - DC9C55D162DD068D635BA358 /* PushNotification */ = { - isa = PBXGroup; - children = ( - 0CD17A131349789D4F216FEE /* PushNotificationListViewModel.swift */, - ); - path = PushNotification; - sourceTree = ""; - }; E58AB79C6479D3AAF6226813 /* WebPage */ = { isa = PBXGroup; children = ( @@ -501,32 +455,6 @@ path = Protocol; sourceTree = ""; }; - F75E3F153FDD92A392CE9F77 /* Search */ = { - isa = PBXGroup; - children = ( - EE8D95FD8FEFB1971672FD03 /* SearchViewModel.swift */, - ); - path = Search; - sourceTree = ""; - }; - F7D309730F31660066D7246C /* Main */ = { - isa = PBXGroup; - children = ( - 4870173271638E9190A3E93B /* MainViewModel.swift */, - ); - path = Main; - sourceTree = ""; - }; - FAC2309E83621894414350E6 /* Setting */ = { - isa = PBXGroup; - children = ( - 694B2D575BBBC41B71834329 /* AccountViewModel.swift */, - E5791BDB07C20103DD93FEBE /* PushNotificationSettingsViewModel.swift */, - 2CF3B817B16DC4EA28CAAED3 /* SettingViewModel.swift */, - ); - path = Setting; - sourceTree = ""; - }; FF7A52F8B2FCBBE98267FD8D /* Shared */ = { isa = PBXGroup; children = ( @@ -677,21 +605,21 @@ 03CF7E696626224FFE93FFDD /* TodoReferenceItem.swift in Sources */, 053BC20B9244F93FFE9E6FA7 /* UserTodoCategoryItem.swift in Sources */, 277C3C6802370B2DB28EA92A /* WebPageItem.swift in Sources */, - B947B17E4DFD433FD61EDEBF /* HomeViewModel.swift in Sources */, - 38BA6B9310BB45F46683D105 /* TodoDetailViewModel.swift in Sources */, - 0DA6A035B08B2E1FA91A5CCA /* TodoEditorViewModel.swift in Sources */, - 7BAB031CACEE7F60CC0A14D9 /* TodoListViewModel.swift in Sources */, - AAB8401E0FE7598F54D43BFD /* TodoManageViewModel.swift in Sources */, - 34151EB8B72D12C8D373F567 /* LoginViewModel.swift in Sources */, - DC2E2AB959A0EB7A28344690 /* MainViewModel.swift in Sources */, - FB83D3B1D387EB6E5E3F76BA /* ProfileViewModel.swift in Sources */, - 0A25E266F29F6ACD7E6154EE /* PushNotificationListViewModel.swift in Sources */, - 5529852916250307CEDF2210 /* RootViewModel.swift in Sources */, - 5DDA91AD574C37E26C667F24 /* SearchViewModel.swift in Sources */, - A638A1BE16A54E3211622438 /* AccountViewModel.swift in Sources */, - 99EFDC252204B10E9D40C261 /* PushNotificationSettingsViewModel.swift in Sources */, - 6E428FE9D2F09F9696B4BB52 /* SettingViewModel.swift in Sources */, - C5FD25074C105C9F278C71E6 /* TodayViewModel.swift in Sources */, + ADFE22BA856BD7974978B222 /* AccountViewModel.swift in Sources */, + 4E725B56D14497FA73132F9F /* HomeViewModel.swift in Sources */, + 34DFDBE6AC68454DD2A9B548 /* LoginViewModel.swift in Sources */, + 4C1B42EE18ECF68DE71DBE47 /* MainViewModel.swift in Sources */, + CD9C0B62EAAB0FB928703250 /* ProfileViewModel.swift in Sources */, + 5DCFBD39AF6AC33B30265D73 /* PushNotificationListViewModel.swift in Sources */, + 7B3DB4474B7B6C2E948A277C /* PushNotificationSettingsViewModel.swift in Sources */, + 35649E3226AD3D47FB9D2C59 /* RootViewModel.swift in Sources */, + 6DCE29BCA008EFF51A476D7D /* SearchViewModel.swift in Sources */, + AD05101B81F4D267A87AC7A7 /* SettingViewModel.swift in Sources */, + E1AC015EB5592C1F39C252BB /* TodayViewModel.swift in Sources */, + 4ED29B9BB4B0F12363BFB927 /* TodoDetailViewModel.swift in Sources */, + C2358524334557A83CFE10DE /* TodoEditorViewModel.swift in Sources */, + 94358125409F95AD6FEE75F6 /* TodoListViewModel.swift in Sources */, + C28BB5DECB3AA31ED031D90C /* TodoManageViewModel.swift in Sources */, AC7102A1D35CB1817BD885E8 /* TodoEditorWindowEvent.swift in Sources */, 35639553522A1CEFDCF455D7 /* TodoEditorWindowValue.swift in Sources */, ); diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/AccountViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Setting/AccountViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/AccountViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/HomeViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Home/HomeViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/HomeViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/LoginViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Login/LoginViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/LoginViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/MainViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Main/MainViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/MainViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/ProfileViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Profile/ProfileViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/ProfileViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/PushNotificationListViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/PushNotification/PushNotificationListViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/PushNotificationListViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/PushNotificationSettingsViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Setting/PushNotificationSettingsViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/PushNotificationSettingsViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/RootViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Root/RootViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/RootViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/SearchViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Search/SearchViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/SearchViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/SettingViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Setting/SettingViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/SettingViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/TodayViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Today/TodayViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/TodayViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/TodoDetailViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Home/TodoDetailViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/TodoDetailViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/TodoEditorViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Home/TodoEditorViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/TodoEditorViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/TodoListViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Home/TodoListViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/TodoListViewModel.swift diff --git a/Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift b/Application/DevLogPresentation/Sources/ViewModel/TodoManageViewModel.swift similarity index 100% rename from Application/DevLogPresentation/Sources/ViewModel/Home/TodoManageViewModel.swift rename to Application/DevLogPresentation/Sources/ViewModel/TodoManageViewModel.swift From b4c83411296daa976e1d01d68f47fb4370649329 Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 10:51:14 +0900 Subject: [PATCH 07/10] =?UTF-8?q?chore:=20DevLogUI=20CI=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EA=B2=BD=EB=A1=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 129e39d2..e73678a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,6 +85,7 @@ jobs: Application/DevLogInfra/DevLogInfra.xcodeproj \ Application/DevLogPersistence/DevLogPersistence.xcodeproj \ Application/DevLogPresentation/DevLogPresentation.xcodeproj \ + Application/DevLogUI/DevLogUI.xcodeproj \ Widget/DevLogWidgetCore/DevLogWidgetCore.xcodeproj \ Widget/DevLogWidgetExtension/DevLogWidgetExtension.xcodeproj From 4ac3c7029c267abd6cb2bb09645aafddb39b3efc Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:05:04 +0900 Subject: [PATCH 08/10] =?UTF-8?q?docs:=20=EC=95=84=ED=82=A4=ED=85=8D?= =?UTF-8?q?=EC=B3=90=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/App.png | Bin 306884 -> 0 bytes docs/DevLog.drawio | 182 +-------------------------------------------- docs/graph.png | Bin 0 -> 87281 bytes 4 files changed, 2 insertions(+), 182 deletions(-) delete mode 100644 docs/App.png create mode 100644 docs/graph.png diff --git a/README.md b/README.md index cd5c25b4..c42bd41e 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ MVVM을 기반으로 하되, ViewModel 상태 관리에는 MVI 형태의 단방 diff --git a/docs/App.png b/docs/App.png deleted file mode 100644 index 1980a0a2da7c34af7f6746377e18fd4a67bc5b8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306884 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 + @@ -565,186 +565,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/graph.png b/docs/graph.png new file mode 100644 index 0000000000000000000000000000000000000000..a71c0bd12568b86ccf149527f3c3cf84e1a0c4b9 GIT binary patch literal 87281 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

)PY$<+Paa^6Q-4cnsqw8r25=*fZdE0FNgNsP*Dv zF%JWI06~*)LC1Kht_&|N3zZXytuY9)htAtnM2gnO+jgh@NM-)laMB+ezE3chfo*f*%P{Od`5=S}qZbg9IBt_bC!s4jm=}az>%Q|7g6vMw_ z*_6j`J9vnyK0RdmPsYML)oaf=Kh?26ya}S~!>n9EAq+h7AY76GThE99XqO}NSpe^7 z?x|ni*%8l4Dp$Y7KQD;(j7(J+>D+d=S}T$D-lmb!zyiFj57uV`P4ylA_6r4zsGnH+{8IyzO`{&eq7aKKc6~c38w)hQ|;+A}#nzInvc%^WN+A)sOYb2F4KQd@g|?A zn(0!x9Wf%W`$Mcrw`g_0JNr<>trM9t7Ja495!g<0{fQWH>j3Id`r6t@s@d3H6O|Z4 zYLzQHl+PSUUaY(B`#kXe66;ja@8PeH829=kPA2s{Hs@`k7k8M13g zoX`=zRCY!EClxlQk6EvJEXtQGoWX_@%KJsz`prbh;P=b$Z@ZP19({7KNn`);GGXY+ zBJ1|Wigyx{-SV$SzDJjwUi)@r#%cC2kC9zvuD37$OACQn#uiPL`2q*q-*gq((U0@3 zR-Mw=*FQ+A`LV^k*Oogv{N-53hyQhU>8m-_4V`?K@`bunMT;bgza)wN`Ri6k!MdGG z`eFuuMM|j&N z>+K}O8&-hxQOoVSs;>0UzLHG&#^bfEo;la8{N77K=rCq^fjM29&$ht+kqfMl{rj2yItJ5j8lEhtU#ea%04wWH)C+X;(f3S?vDVvcPe=hut)0+<~Uz z%wtMSIGAXM^*qbi?o?3z_O@r|*CxYgQZ-eAs*TjI6H&1&%*A#kyw0q${HEPQr><>h z40v`04r^}~YduQ-yi}J+yAu;U5ST+PN`Q`0Ka534TlDl*T4Cu2AJ+LYwgUT0vV4Cn z8Sm*FdL#IMSb&I$_iY?;%c=JV&PI>8rX0hA47!Id9f8Uv_&Qtm(1mS3=ce?$<=A?q z&dAM2cgK3h6m!npSdHR}TQ48;a6Qh!c51z-yDr%Cv(5RnLG7bYzT6J^XV1_y;yU`` ziK(SVg?stzdX+>&sjlK?P%k~enw3y8AV%8+Q>Q%bTm>{lSkQB@Q=Tm_laK*XWVg*D zdXZxu3ZgdWXS&{6!cdE@X^P;zLw zW}+yLKE-%)&Ch@wx12sd-OdwZ=JXRePv>#B-tH)#o0QW2yE6fYS#vfsU~2bq+;v!M9NxH-GCR z#x8{;7a!h9@_cpQ%%+Kp{N)Gdz@h~`!{r|btIrwbTG1@_sa*P~AZy+IzIw#Uig*3~ ze@eaEl&_PDPINvIJi1&dDob?>e4SiK6F{Yk8tnyLK4*QU=SfTFuMsnqe`c!IT8S^@ z3t4wmPP!HT^*DVxw|r{DFd}zV?SQJ+rhD73#s}n8!~XkHy_j05E?17YCimX{ZJnfg z?Lj7K`6$cub48wvf6wL;U$nd;r`mD-LdP>fjkx90*Dp)!dQ9~P??&4LimXnA@vZ&y zc%WeBm$r_je12CWX_RsBbImV1-$l92*+c(Y4t(%qWs}T9>eSp*@l&(Ts9#Vu@>ScZ zM=aIhS*tfCKh9ZCsx3~yZ`r)&M7T@lzj$)>_n#`h ze-w26BlWSKBUV6C3IcGpIa+i(duiYEb!eqZmO||*;hTz%&1rEiIxA{F= zI`6SwL)yaH(ctRgDk*iVNm^qP4K_Ilv)+> z^2k4#sgd6ybK^se7i{8eRu=`m*1oPK>%89qCnBnQi|IV~OsxltFa6#JXldwj5olED?v;`A+Lt{&@Rb12;xekdt5pj+yliqIM zZvEqXnBz^iW83BFw?1(yNiwGFoZik4N20+da6*MWvC7@SC`j$G&`{d5ES%-=CCkB9 z@~A^*-O=!2Y46l?bSct${zef=nbQlc#huH)tW2Y?fABw>%)L6fex};BOS3RA@Pvi~ zmOk?GHNB_rmOx~Gb113Q3Fpnbn!L&ho_%RC{W-d_+i>RZwivp%)^;=U-V^@+%YJCJ z^{%I%I4FAHz;*|KD%t2J+ocbnOWU8kyI}qeJ1e52>rXx)zK4qB#YGd z3k#F8%J~#Ntm+W~6Pq9CAMrn&dd<>%jNB}*B3Nx#ZaST1sW44aviEbBEpA@xTe@qK zieiW(zcH%~i6{iX>V00=u|nmy6})tw6BX&j7~sh;aV$4KzVPeDWKq$*AZ&SBxv~s68*|6_-6}m=%A=xBjaB87W_pa>Gm9umPeu zZrYQ6V?eIeV$;)H{IKQfUqiY+jXjQklyK{(pQi$$7KJC9G_)0=-GLkCA ze;dulQd3E(f%NOA*L|gSsi`1dV2661iyBdPyAs^a?2mY(~WHzHB( z2JU;8#>rqy9U@-LpKOx--S?90-b89_F?je+n-{|2U79y4rw-^OFnB;;umGc5+u0?N1LC%2`kDe_(k@?E+s zk36;$t>V|HP>`?mY0-M|u`R55?zi(>lK3nD+7baQL0Y@|TsSTZ@(O=llnM!2G$XIV z#GsO&D(4ZOf;_=mb|HPu_GQz7jkXl!sReo=!Mhdh}lJ zhsXOCw4I(2O9qYLG=-M3pg>#H8xbdyDaL)~_Yf4mxrfKc&w%bs2=@Yq*kHX3Km{`v z8XmJx&3FOh{S*~~S0$A2-1QorBKcN4Og@5(PKfwH`ibZ`@fro%Qd8FZVY=MJ?XHo{ z1Tm7<@}|F$XiWWn_&Mt|4iU7qhihDukI%D%?F2@BCCuDG`PpGtdN(Ln9`GL2`-*Kb zLAhiJckf2w5ja5O>I5B$k&!W0;MuZKE%5wpQG1_;LpDZ0RJ8NMD{4OAG(q}l#d2@7 zTL%m~0@MO045ursg9PqM>fX))0y}-OqovQ^5)c!>?lP|b7{T+0?m~+RC7Ghi6PRLX zX=&NN$veE_$^C??g~%zPveWD)?^|ORnNxw$2ms?31N0R(jUbE>pOHZ@vlJ8#3LHAL z0}5#^0MFA_rbLBz;v<=(DV}-U*3So1Xde*O(V!MmX#{6EqNxwXPX(`ql(+LZS>(X& z;cEcb`ovW)#-=ym?|^%=6=UlEwEc5AFe4&|TLF?#ssBz-Jj^tkr;-3eZ~Pz3Cxl=O z=|^V?NJ%k*7l5NW?C6)9V4%gPr9~3SD}CEW9s^@+B(UscBoAn@kdEM{O<1+HwJmF0 z*ooFqgcgglCovpQC>G3$5CNgs9~^fBC<=9ne&R=4{Kl`(qM4i)7y=S|13F$S;L`du z-e8O^cJ9le1m9M{`!L?kEanV>1|n@x5<&)vNeHzr1I2*H^w*#0gl-`)<-o#Inh&$q&(UzQ<0Nr*!=K;HmN3b)4jO1bmD>rCuxewLR4#ihfXl{cVfKPz9N z7|0g$^zYgBhgDT8Kp;(G7X+9|e9tlC9oNd8o+9(0*rBs8V5GZ|_YbXhpn%eIaFU~; z@V6DxglfQLk?%2T1}&UN>B^Vj@~6MLMZfQ(4+6k`2Qly^1c87&9w^!b8$VX{y3cgR zRpwA{K{R&5ZWQ?icR!&JY3WI_p^v@yaB}V%mGV*9@bi7#_j~O~nZ4`h>Vd=R1PKv1 zmQVd&euOtTL4?yPq?k)Jn9NWR$Y+m9RN#Nt*%u%2WHz(y(C|X@_Y+jJ7lu7Qiv)eW zxliG?_VgM9D?gVU%c1k-zL%$nULmBES`c#tm}vY2 zh|cGL#e=^QQS@`alyzA(N`-5$2DP-`^*T}8GBIUH*JNAOa^}A0%4>&jOJmBfh2$xX zC_*MXr0J=)@kb*hOh7Ee&};BQdn7w}Nc@<>Vf5nnMhCD{f|3B0EhqFbvc9Cq$pUnL z^7?mn#vP+kU$>Y0JJ6&ZU=&@FY18i-vuu?F=dO(-6akKPs0^x$+SdCU*(xx6&W zMKF%Bq_Be32n-84PDI!w6meBuXOYry%ATUZ+$z4T}%(qxMkrQN=+HkZZzG)9+J2% zDe$Cf>MdF0E>6Ang@=1N$XS>}n7AktNbynP&vz{>Cz*Op?P4Ki(|P#;|GIIa>{L@$ zA2Sn4Nf|O{VVV9+py`(1jYDc#2beiu`s-|S{?<@cPT^9@$6d%bA%QvkJbzf>oF!n_!T_m2k;@s9vk;J7P7)9T55)h~8BJ?z>mWPJbCKXl5Zzzg z2rPS?t{AD4xqtY@L;3UC^H-Ao1zN|8(v8)G%>@1RjWl;ro5_+V4a72Wm7LWg7ts2Y zbN1uH@uHMK)9x>VVMZ(~WD)UG9B2Rd-*d42LFR3HEaz;~TQ1tm1s5AniT$=K6~@SXTl>Q)K6XB4LPg`;N+flbmV|6O~9Y6Yg}fQmo6o; z9t`CnEsQ>4#VIfS^yeoY!l^xgLsS5ySUTV)02Ww1r@X^&g>3x#x-ICqY&hS(xr}i{ zwJ&PJXD|xF0&Hw-0;01V1MS+c3!}3864j2GM&2^LUUNk}&o4Z9f1>QWpMl0*G{Ju4 zPg3Lxzy0m(zal_u?k@;YE);rea^-wPSD5b9Q&$kOP^~(eZ^D8 zKtwoNhgDx6WD%>Z11Sexj_k}6WPi9t(5&S~QiM3oPZFpSI~Trk3RSjM%4i;2*!haR zlk;L$d>v0{tddH;<8`@gIhMHIzPeZyYQ&Sb8%FH&m!h?)^L6+a=+m9v)EM0h2pBZ7 zuVJ2}&)}nHr`w3{+G#BDktrhBSS&HVYbIWQ#yBKYGv8G45Trlc4=Jl+NH($RcOl}! z`$r6MDnB@p%qncZuM^pIsufKpiO)PW*0z)0E{V>O*>BG|$Z`RAKo`_P^RS(~MrYo{ z1}j&qM}jIOky>>d6Rnt@Hc7j3`8+8;f|KUw%(TU>+=;p~S&4PNyPiK|3zp(8@sV>k8C}+saopNYxC^56E|jx<9NT4kzU^wvvgZvOzC;X@!EM&KrQA{P~`K| zEa6(@!D31A`n$kJqG8y&xBrks&6i9lyaMvm>rT?mqLFH2Ai)SL0=d~F5FT(sxR}+x zs!SNi;8YJomXM7!`4Ell zeid6t)#r%KrhHtz3JL*6sQu$$Fxi@5Di{p;p4jgx+R27wUleLc@uO+YMDS#PIo_^uh< z0A3|cp#-(v9LI}XA@GoATJ(NXXy;A}u$z#P1M3Gm=)T%C#+I{$hB6L(YT(vEj}}T0 zdoA>n9Yi2dy`tfy1!MWub2eZ;6Ypuzr5)pOW^V2;{XYWlA*Y%Kl9^y29(`|xCYznl z=Uqh7jC>{I=zBUU5DzI+4LS^&f@n%Dq5!n#01>#8$iL3L*_rw105qcs27!X-RPfRF zlPl4L9s){)7NRfEaP6yFR9nkr2ij~hKwc4t0j^I&a5k!|#iS!5OIc(uOT-F1%%%ao zB4qE$_r!hx1@J1ottz}0t!L?;l!LE_f@V9oY2ffPJRJF&PBU=qk`j>YUZ#AraR|&|G@oPZr*T0OoGH2F|V9r9MW> z$7T^!I08z52)Hs|-gHrihgz31u*YMIKPFHQtR7NHT0Ce*K-_|hOGPgRq&;whKYo1# zWvEI(gh6Sff}F6+Hyy3>8zuiR`fb6)rUF{ug!+T(;RgQQM1gR;?8GDoRiHniwh9GH zf6Lt+ke3L6ve-t0Vf|Pvgqk49(LQ_LbD#&Tzi49om8q&i)F!o_z(CXUALIo0i^!Bv z6p-&>q1JuPoQP8?n&$u`xEZ@ej%GxI>aP|xeH>^gsH;*C+F&$4-Xm`FM#?6Fi~g3%5&hripS-yCx3-(p=HmRQuk!NSlDD^)8k@d8 zQTbH&!MEpUh6=32f-N`QsWqiBEjKOW^l0P-d7!^8cWZs?9Ihbh~?9T^$W0W5=O?n?aEI z>W@8^k1~mZhlhvIi8Yu11khUrQchx7qNp#f@=T&EjrDl+=n=twXJKKPSXhW|XjrQ` zX~F*AS+zq54`o+ZS4DO8GvY%50|Z4XK_4O%N)?R~iPwC62~aj9ovU-D4N`I8&EwtOqA%8@l!A(iPS<|u67+a!(Rm>5qU*M(RbPknOxCv$9ul$EiB>0qT0&x? zmaC6C1hOQv~M+b)hJcNVSf3Xo)^>b}k&F;t! zr6U&ikgmVXP~ow&vm;bGurrMB8}Uh4(FoSUj>6SI!^FWs5K2uHXV0F6WLcmWZzvft zgknT@{y%ghUS9h1i))#g9nyoT`fTo`6>QEd@8xmG2ojESiwfpv02)-dJjX-`f?OWO zre=o3L~HfA{t93XCHU@goK`sa7!$4VxHw(NC%_tX(MI27ue`ly+}#;Tgk{mp&M%Vk@*L3mQHM$_ z47^B?eSMb@pPo*ynz;?|%6BHk`RKn*L-VN<`U0U~n7)Z^lZJ7E_P@V>V1IN7#1RT? zuWDhLXnm8^RtA#GU~vfKMhR_Sz*WWZCzWd(HQ3e8J6-p^Vbe&jwzhabAU_>LW{AT2yi zXI*jM7wuOn@BzK`jGlTN6%h?l-aKA^=(7h{)p0 zwf=?P-RjDurrY~RhT?Yu_6^z?8xvxEfk3wr>7l=xKo(zwgW0Wac6SnSCL5$klM(eS zdV=RVi!S4N6Z(UXE_{du-qfUvu&Tkzb^s@FWo^y$#ij4nH8r5x>nV5G&@(VF1DXqI z0R<%`0$W=xY;K87XE|A*hB*WrQ>lf7g^A#B)z?>Ykmnn=7H;KXYfK=dz=@L*$*DF9 zZ0Amg;wLaOx$5IXK(GmkX~}n-pSBjBnxrBT(rO_glmIstT8yo$p4!}4g`W}^p#kB- zg*A%QBoYn9mcBldMeCvYxjC`HXd7`pK0c^i(qnIXT)wOYX{<#(c4E&%`b6T@MKf~_ zz^^ff&_H-bVICS3v}I9m87f3Npo~e57F(j_LWq(~+Tvm) z(xGE7a-6#rrY-dG<&ge{oMJO1r3kj{y9Cv{xL19BeL}eJorxKTAO&JFk!=txN<1}a z>;-#0SciAxL6{i+$CS>bI0=mgp#ujVzvG)}725%?2qJ(HP86_p!n5V9$*Mw-94NEp z(T(L*hf*a3G4z#<@_E3_vVQCy11u)!c~lhe9;bpM@@PVU zY*7JngtJb-V9`Li_v!IMG%p}@7#I`70PUqPES%zNZ0fqY)R2upj_Z}UZAyWW=#Iic zN9M-nRYDllEAQg;>Q(7|`*Qz!A7{61^kGMAAfV#}JrUagPrj(y!>L%u+L{~eqi`I1 zlIC1RdX>I)eO>FcBx#DeNDc#$#caWeGLvjo+2p<6K9Wy9HW6g(|`UU2f zltdv=IpHWI{2p-hWWPCLapdgY#A`#P1CTi;vOP5PsnIb`iW%ShKP*52-~Ca`pj*9< zf$97PVFD=dLt2$+=s4^C%0u*+!m(FTRh7e+Zw;|J>_`o0Y!j*PJI@rCViXxr&2A>d z@K7Jr*4OvPK9hFQ-9v}02b=of!GlEBgMRWmPl-Vy=AxvB%=epEa#S-|HfTdsFED&U zIB@PPhA1{4$@txM_kS~si!p$55#r$zmpU@AK(TYEip=ztBj4QC+ex6;F}?``LwpMN zB=K-_kE$v^8q|pW*|<<5^np9<35n3T`T73XHZzndG|=ZIN>S+aFd&Y;OW@SmQ)D>V z;mJ!lsbYND+}=)*OAu1h@VZ;Z#`vH`dpzy*b^IXFz(R#nclmQ5x-Z10k$6>`1Pj45 z{d<*X9URCK^n%e&eI1)KfU4f!$!W{Yn>Q&aDILI8m$+iNh@!&*=ah^&Ka%%-Ka73X;YcQ+s$xw*npC!a>6(uSr=l-JHs6C0OfwPgNx?r_BNDh7fFiqoH* zB_h}>Pk(xP8fKRK_7Ei55Xt%kF}YVrpeLAAJdk8k&$J%niyz*pF0y%rG6Kqc~{$aj};Fu`AkRtMsN{g`s9 z#5#y4mNquISy?1No^&y|A@Yx!`(7bD0vG%t&mWAlvGDtdAkrc7%-&A4&eW8+VijBC| zRt@NsaUk-v_8oo}og1LYoNVo-@kp`fS;Wn4-K zAC|u9p&(n+9AluTH+$rZO9<@yA064 zKd8{=F+Q38*!jYx`k;%1+$Q0v4EZLggG73z>%;Sl5(!-Xd4ufo@;F3OVy7VV!bH*5~u^Tm3ye45Y~8uC56Y!`JwnjsB-3~U*88S zygH5hLTC+y;h=2r`A#PjcQ@>6Ik2Q5a=Wnl8eqpL2@`6o0c#wL^h*^ZzUAKl!t7HN6SI1 zetTASc1l#cm~>3y)2fBZ;&+UW1G?{GQ#!(Ul?OFPWH_vg9xL=j7(9)2O3s zaSm6D$Vk|!5gA0%*p{wBehnHZ@JHfUn#SIKhIMT2qj;dLu*zliWX7XM^2mBxKyGt> zEs*58ZpV)-JglHV1clr=-JfEy(*Td2f(kQ3M@I+FnpSMXtow2VfapKjv2cWwlaq+9P{I&}0l~S> zpLuAR2tiD>2}}}D&Co0e#muiiHXp%+l#-Gn0P-3G_kRDH8aYCwPTABd=+>80P^rWn zX<#+s1r*+yO~+MM{yCpSjQWW_48aP(fIN*@n$LTC2~P<)GX+8j8)a6($%B?EZnN%YsQ{@qj@YQfK9@FM1S zf}8N#ZS?uBhlSS#rlKJZ(Yxs9eMVh_aCRE#1g(=NGtt<%=fzf#Mxd%>`%$mo8lj`7{1!b2GfM($gxT zps47uLaZ=p{1>sno?lH`Jl2$qE))|30|Vh!a4RXvT)Sw_Wu$5sA?tz5C+cp|gZy#- z$^Tl-SivI|R#H+T3^!c9l5w{crhc)l?K&k3t0an?($dmf50CA*v^=hoQ(k`b>F*`w zcP3AtBN;u6xoiZ2$LfzCkg8WqQW{5Fh=z0#%~pLrT`q`;$--p_+EiUQSzp}9xOdO+ z<*Qe;Bw3dMv5@HR$Ov-s^S>Kq|M;*Mb!15N@zkXcO-H|d|K5d~X8Z{Rx#H2UjK!-# zc#1HS$d9l1l3!53LfR=Sd&`ThhR`S?J{_UbS=XUB0^iOOpr(dG?Fc}Fiwfxao%}8} zN|Vrgu(qy_1xNcDAlI*BbB$4m5%-U-UtjE+HvTdpElIpUI0>Oqa^LjMDznhd=~te- z;EEL`&Pxiz0io5C*XrRJ2EqXaxuh`GHAw&;f-t2iIK2s7Qs`gbtZ)X(;@OKAM+BYB zMbKLy_eYt23&~63pUug(uslfE<)PO92xtZyt3@OHs8|3cs~zA7MEPoleYTk0SS0^qit7vU(`;8Qz(P4Gr`89(Iqse}5Yy z1FvJV*N}DVL4h?Kxs|w-6mk-iONg}3`ulIwP>@&Q40z|s8TzyO(qLK1$KPmxOrvhX zVH@`F;XWvDI_sLIp#7B%F*c}*=JU-&4L-19MRHYpX_gUzg^<1`GLPN64YH?^8muIM;3azDgyjB!rAqWEDxutn6e&LfIrEAt77CREuqK?$;cilDin!_ z|9SWR{_kSPK_R}EF}TU=Fk|peR@SFsN4rs6 z14o?L;k=b0xDM+xmUf4pzX(0U5eS8zpA4=ug%9o?RGx3Jwt5)2DgMr6ykz?G+7)2P z!IPQbUZT({!v7;1*RjMI*euwrO*2aOSloYqWguNB8ZN@(f^$y;zVgt)*thR0P7Hh_Se(BP1bq$I4$yxnb7Rmx!N zLrV;;unD2t-P;?T71{#rx4J+=nM5qx-1SD9E(-&lB~#AGg(Y5!81)6%OWeE`zJK0| zNE@_eihL4yO-f8oZH2QRX5axjiK1Ik8>FZzSjrmSq7-&@jUVC14ZqD5UiO45fTP@_287SKwV_ z-9-)19)Hz(g%H*=eAv@&$kbendOIi4i-b&iY5htMX2|!q0v$;~L?IqSAkoeN>m+FS z#KZ*Ju0KO6@0PI#n^iqQQX_u+Imc1JAs+M1$J;tPJ$}s9Y2u(jYXJ)gt(n zuNq_H<0BE6+C!2ZK=I(EZI2bPqMPAC5CX>9(-YA(Tzkncdz0?4Haki@pV1S~!Jpvs z0)@Rx;w0JX1WQkFUhh%!LpOUCb>f!xwzj>*LK(<|+YirgT~8FD4=CYN%hE>y6o4vn z_(bls&2fArWbQx}?(=V%pl&qp9>5U3Ol~$001mgSFP{BctiH}lh7rgoc3qfeo_W|Q z>GmrCshgDSiW@)GJqdp6+kBPE4yWqe0<#{Op+;_9X^FN6O2`m%=7* zj+_vWHi8zV8vK`)B(|q!V7n!G=2P8y9Pb(%Q`jJ=s59~Hn

_RG?%z7(OdeSK?fb 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ν_);g%@q=DFF6p;6~682d|Qh2j@j;X2Cv+4HoYHC*UZfp zt~?&mX&wum>RN3!>l2CaPJA#su{J-t)=}4adroHh!!=&2Tdzlsn^ok+r{z9av1lh3JUEQN5lDLi z1~UZ3%jxsyBb^2OOgicL`=id0@d-Az`%sdiaMI4z4<6L>JI@Z%>q_;_@0^dJOw|drpA4i?RdM-q^H8gMYtDzo|5S8> z@5<#!`t|`tB+5a+!V)panfb;? z2p>Bpk0<1C;|8hxG1Nwi)xN$xUS3|L3nt>e-s_cQtbp_?D2t)*4&@7{Fxg#4`*Zxh zf(YeY&T!-Bn-6@zsNy(}Lt*IVT*hc_AkL zvuKyh`K;2(;^@Yvrdr~!2uEG$7BHB_i)={rl-R4jiHz}Jj0T(0Qz7Xk99H6fWCo2bfvwXXFk)- z#73cp3%h1iTrEEbVAxofPS+>GyX&an4XV`ukHQ9Jbk{L=X}#rw3jP`&;g+bXa-ZjpJTKC@6;kdTH-Fb?x*nWHkqJA(K4?(ca@I+(#+YT~^N2cVUQztN- zzH9FT;rCZTbP)3?NHm}#^Me%B1Vn0)*%6xa_w!$?z9Zs6D8pey0|ZK(A7dO9N@cW`Is4Xew<`Su+RGC=AAWRQ*V_) z(}MCo(_OpRzjh7@-N@(ueljN7$&K<>>K3|}eN^qszbl_#*c^m2Pmj0`=0R*D<#CR8 zdzW;Yf4^!iE;pOp-RNytiq>6#g2$t2b2x$O+}1UCMjpM=y1Dh)D9MW`#=hsyToogA^S0XH43P#p{; zNGqfQ00jC#B3LFX2*A%}8C6No=mH}>s_g7WJ1-4ZjL-@2fF@uYIc(6d7nym!fHYAC zlo2{DtVx9JO`-A&n>)Y5ICY=!T#= zO2kZilg9%R%Wt$*J7p56r~-Iue7)t!wX&!brEwZeaI*XyMskYEo<9pVeRX=8e|+g< z4n4CuBD&+Z_4T0>uFIaTH8MY4@}w!MZ>BI_revy=@tOTkF{9qhvvysvN8ilAD1%$!8F zA;KDmFf7rt{2i#HhQEHL-nDBN8IHj~1_|v4;Iu|Ww@|JM*?ba$tg`mgr-vl8=kSJP z$+$~yx>Y_7oa!h+a#4_+<7J^A1|v++V^a1(WKHFpIJk1>1w!M$#q@{`l`oeE5E_s4 z-k?8la2tKp_fcU7D)x#f0xT9C8#LmP^x~DR?Jaj;yY(NhZyjX`dsExTsI`wDWKJ1= zQcAledvKlb4LE~PIml6VbG)@bp>{8;Yy2eL(2a&wO+*XpFAnDZ78c`?H@8n|iv-fs zicbzzaN@WN8=?mQ- znHD9JS@H3E{=xQkTXK$n*0|pV6+G(M)6hSY(DuI>HfjuG*5l7yU-@$#KxlH7(yQ%z z4~JsJhKzSZAddX@qSudAym$!Oxed1z>VtTDDNgA{-jxr&xizy)-TYx?GHvZsUrZS6N5xBAcdFXCR+35!oD}FhiVATgI|z)PFX0* zX!_3b<4oRj1_lNbGJ}o?iHoQt5h61-Iaymze{VX1>AJMEOB|`-;0QCOm zM^f&L&<(x;Aa)MZ4!!M6ekK$MrCfk{hmcl?vL4YEqTJJfLdf!8vWXW`a1s!}7Tm$- z6t?X@0f2BnKYy?@eRSs}|2nm`l&xm6+XtTt$~~ENW%`*)mAQ-SleprZ=5GZtnT;>7 z3xjMHskyTe+@%}}=+c`%LeSd#`1_lYVK`iXeP|F-+7ay+D7rv!aRnEFv_)-qw@6EY z;LiT%&}kYraeC-}-r#WpYzhOzH}u+fD?D3dF&1V|G&tdn*N`Bv_KD1O;TeiKGaCOV za;?8VV@LZD*_GmpJDwc0syU^2EQT#70&^TsFBMbc3dcn2gO#$aUd^dPyQ zhmec}S=4gSo{8b})m2whKv?;y(o+IMBDdMHFBBtohsDP~nJc{JLrb7d2xg(eqXj8M ziss$|CI=ejByYez?k?qekRfZ47PkB7-qu^&7X;QJ2H=jV1Sy3C_(`Z z`2%1;n|K}jnDN(}V}J}$KJ0rWXLxAN+X@<0zQHb5@5K(l;LK)+5X9vkWpfw@cPpy0(Ht6 z8YU=LhQrQ*$Rp!KtnPsC9>pKlg`VgHm!Tq{a54ckf*AP^1wBDCuYt+9*JOOa>6`YK zuU-7gn19%nUhngVKiAW513xPfc^_K+Q)=SrUZVY7pi#5uoM{TVwal^=n30Ul~ z#Kav$TZY;fI1nVF7z#ZF_7S!QNl}k0AxlTmxd|hB0vDhARB#$cX`^N)AqmMPtH0+8 zcu*q5fL)&20~sKR!My#?+1b;WvL$P%5z{{W`_l4S-;8WC`iYnlGI8>| z_&y(NK|};{OxPEAY!OJeH+gtL`5f=3&~5ZL?Nl?_lKs=H8!iJV5uX}XT)G{| zx0{m^*vMS~p+ro8AA}Fp7E;HP4d(&k*ag3hJ7Ab$r_6yd)@Y~T%S;N_?0v$5s&*M` z5&s!rX2ajVhoD+Nz4u%*!*ghZi0TKEG9)ZRTnvh&1W}Q^NCLd0QeV6ndUY_D;Z5Dr z7qb@GNk&%jlCjhqXQi$8@Y$Vb%$Q5J*mWRXY24`MmXx)K(>hh$tCe0`0n`XAI$%i9j=X}VP?0mcX`-?f7T z-qPblbO1T9=SLSZx(NvbtOW%vt*y1|&ueBOt=wZ3ql2cIFg9+#zMKZQ;6sc(h%W-l z2pL>)GO-0-=ij&H+luk*NMvGi2rJyzsw$R4o;?4)c4D=(#Z+){U~5Ur*gnOOeycbu z>npw)={@JlerT3{({bxFNQt%LebpRp<(!!u@ycOTS;PJ=Rmxkxqm@-BLp1w?cAZE{ zoE)tgWo;Gf{{5f+W~sS}vR-@{WsnVQ1|K%)VUAU>;ujreWdw{WSuygW7(+?iiBWZr zbFBT@j3DMQG!G*TU!*3zJl<0vPHpRc*WK9a9z0hi!qmq%=p_80}9G6r?2nW zQ}_9rOR3dMiK~BHKG}UXsQxTp+oW3CaiJFf(9A4paO}~&p|1xjm>2gQlMOe&ohBl$ zT)K~oEuw<~+vHXsnRquBUzS()+sAw1I@d)-ndc#Yz6J3IGDdVbc&({$Z(wMQPL`<) z(#qAm3rt_Lz*Ig*Cod!sNag0@Dm{4owMs3r#*1D{!Lr;P?n_I`yhKw&j6jK!6Crzt z)67UaJqJfC2FczN><39^335fapjM?e(a8j?aM#RSFZ5h?ChrbXP~8f*V|dRYho^3{ zNxFpLw2e+rzbB(c$Te&RbQF+hN)uTy*zfv|j-#!uc7;9Q+76=Bg8vX1fWUuR8b(GD zh7NFv#iET2e-t63tjscXGgfKx@`vHCPaAsDYU|F_)};;Gtlz!sL_B>i_Z~HcWySjD zNeV|6mskHWtn@!RrgB`|X`9Bp?n!FY?U_q`)i6`(D0G>f8UHC)03OX-@?hho35W-5p}{S zY&`0_yJJwseD2ndeT}xy&mzIq4y*){LJY#(<70OqM|;l0n5Xh z!)h;&OMeZnmOXgrq24_->bc07Wt)5Wp~`}ml@OByjo$B{zup+wl{hpR=1pS1(J0(V1V5xI_|T55Q?hs0XFKWj2wui4H*ek)wfS@k zE*s=xqPQAOk1;gG(M0CIi|$vv^Z>?|nXzgZh6l+=BO!+~mE0D3ERMvgfEIb*o=$%T z`63l1<5S&&l(y~r;T}fZk5m#QVGhCx9li*i3$D8Z^xwQOiu6|7 zpQQ3c4lNAf&sd>$T#zhy{RMR~s^ut@V8R%Z7;qWg#?0a$O2PR5wE(;n%lSPh{31{i znTfD4BQxPAfih}pPv64nvwucFf7DIxHlN-L0VvtE@(dp%yA zAvGKi0~Eq|z8lS^4fuHbK)#^h=`nE%Xy~|_SK-%gIR@R&O-J66VjxkNTvf5L5kQY) zibqS=O9=`ZqbT99z?$#UF(UTIbPNpg=gx)sh;sUz5*_lIUi$MV|N5u`I+!mX(zoLF zIys)%k&X_5v=1UIWDFgHH`jF!Vep8E+E83Qzzny47bm+QhNKVSUz)(e+t+s08nQ(A z8IXlbznM7pnjQ3?^4J)0G(zEC@%5zK07OlM$l}Vp59oop|^M_(D~1 z6!MtA3o}jdXJ$3{Ae*g~{cmKHggxScg^>N;kS8?>2E-O{aU@UQzetc>5FJ(d?~i)K zAid~ncT4;D80xBoX`_s%24xRO&yM+uFVB58$SWw2NjAO zlGBIB@xaS1)zU?Fa3O*#M?Bde+6dK5;JtfM(ffR9M-Cr&8ORF8|03qU(7~r6^5dI}m!|m(L(GLq zjusTkR&ZFs^!eeREW`}>(hHk+@OV~&^ZcU5u94ICQD5TZlO+<5pj9x~PJwToiXVi@ z@mcJJEI{Fh6EaDj5KlTO=P_QDh9SsD(w=dcW7TF>d(?Q_pO60hM?~hKJL4>Z;dgof)UhPWOi4GiPa#5 zR)(H=t}5&0GZc~e?u)i~e5y!kq){V>hlF`RAxD2yE+5AAGlSG0Og5wLGX7#*ZeEpG zVPAYvdfl>-_TB94Eq!)X&6_zqNRP^9upPZ6rpF*l+Vm51f`vHw`zpEuT!fG#(4L>K zaC0*B{Cxo?7L5pC5UHl)z=a%Er{WAc(9@vWAKqm>4ol||@?RL;4K=G?ADJA($fu&Q6poUd7iZI{Ujd zr|>{g8ai4^r3^h5yWs~fZy~U>j^b>fXD;L73(IL!ak3{&k8*!k$?M)lPyYs(KRG}c z+Ta!z{?KkN6@>=y2CzzU6?Umh5`(FYv&&mmI|zvh1yVVxzNLW#mm>2kS3W=wiKsO7 zA$|L{Yj9+@!2VG#$i8@JaZ%^iUcMU59h(X!!N%Xnp{#!fgTBOEM^U69yQb`5(Np~u3o2G5SjG(m4!v`%_r zP-YeuA&!AERI^IqL)_mlrYlGPf%hZR3H!Ymq2rm`bM~8~IJ)U3)IBW_NMWte7JyVu zi_W-TEfPPnTwv-^(B7O#^Mmq+{9*jMD%b_mnYT*L-;=f8 zxse|Oup|b)axf>;uIO;^Q!F4^Ah=6v`G5L>cJcFirIuB4La`iXkmt zcf7bG9d{CIV8Y^Mi^<-k9CM`{3HetuloE2EQS{dV+c@=bKTL zJMk`iQ67&0d8FspzK6f(D4e-%MB`JN+>9}6K^{3U*ZCjbYw=LnVodz8-3&9$CRntz zKs>vJhDIPv%sJ&tU)fDTun?R=LSe@TTvDt1)Ya83M&1Mh>v(`}gQ#nPwCWEz1>A`Y z3#*0`r2<~)6zt7m987Qwkh(`O+Z?o8@cX|L<_R?QTvs{IB_9^KyU&MmhVcO-=q%X&yiGhFwr9d5)MX}WxVQC z=#k$)mWToQ`4g$NDP>nEPdYvFG&-07EU%wO#B2w+0+O%=aSP++{rjU3{hBjZ4ux3dnx?cE$Bu@HI0pnX$}`CX0f8R5+YH7MEki>aAgn2?k*>UA5B z)*%iC7yyZBepPn}(|Ba!#;qa&uX6PJcSGZAYl~HD=@=tKOZ5n!`z$`rmx=yj*yV=^ zn>Pw!UJ-Az4&7}J_QGQdZ{y#aYM6iij-(-ppU?u|mS%FbAd8v({o5SU#*o9`lF4Ty z)3x~~vQQ(o0xHGGR^z-gQpgnic5sJi&=0?zpASyq1u%*U4q};!ZlCu;j@Ip>JrEQE ze*ZyD>rdU&R<66sz7!_Pbnj zF~ba7umHelLZ}g7{&gv>Rw-LEod8;Bt==b|7N-E!YRl zj#RcQ_`^LFR{>v!96panMiRdVq(iS!3qf(dAMP)RF<>&EdKg_fd2$;*2i_CBjARjM z<~+Dm1qB5^<{7o3i=D!-eC4m{z?2&6Vlr8Y2ZiYGd3(Cc8MZA6UVp7HZgC2+2V>zr z(@hHjME8Z~pN!x~haZ=}L-sxF*5MS(uw6e1%s>5ov9 z@4ezd~p-_E;-kG?8?-PTdaY0S`RH(beHQ=?$=_523dKtjHWbqJ0^2FA8Za?&H8p2EEGS z=!l5dC|^|Zh+tJriX`xc82zj)=ACOD^p^oH8HS=AKSB|cV}L!=@U|`ECjLD+$pc$# zQ%+gM)nl^zgzMY^*a%xd>`272aHXzoPnUvVclYXi;#xjh6k?T?muHvI?D-95OGvHb z*fTJJK-qfNTHeGQFBSm=1T^t~Lu{2A>?OXI1f~c2JV}~o#Mn;6z`@>KOQX2yC_;&1 z4;hPWLS#Y{2sjZ9Hz{vHtFswo(8>fzA~Bxu!F9vT2H^r!J1nsR1bZm>Uh8>?2@tq0s@9=cbt5Kt{#%eLV$fx>b9af5X1B$l4cT| zegAi9rNh?>d}WuGmkXh9BsmaYDa)`z9G3!!;fd0s<%#KO6^y~+HgFv~7L5dgeA?-6 zXgt<@e2}zq7Es>-^E?)s!{B?n%i0`_3n?!^5}^zml(efgEudv(#qV%B0p}FZ%%mf( zUhvtqV-l$wr76P69u!lxkng$9y*o&zKY`s$pd>jIc0mz01AycAAFD-_ybD%F*ztLR9b9IY0cEk%gM2|5K;SpOkp zkK;(;nMnQ=12fow@8N<~^be1iDX?qvQ(pp*f(9SFHc~dkrIZB z!cnq($Tg5a>(+pvzl`P%9-I{z0++Yfr`*VWe( zKOD%&G3q!PcrXE<^hZyjKd_1;U@uX}y+__SgUd8Gy|T{^!tTTFEtkNh#)3=>A3k zCUB7saWf8s%m2!}S_n6XI(2FOnz!`xWVM{kjJ1ZOT#WH2!wNl>UxO*0(YD>9hX(-*l@uam>J{HdQM{1WA6(c4v|twyTQ7i@N+^oKUx-a!xzKxG@TF$xM6WP6Rz5P^Vaw#h2z&#ymQbPH%u| zA)BloJ|LUH#I>2hDx+5~UuNM-e4gtE8kQm{DXE1RV7vUED=k25O+OEx+i(};XJbFPFXEEIlz*og1}3^;_PG!v)s=C>1vJSz33T&k%k-$3_L-2%7RJ2bOUUKqW%5- z*Q2>EoO?bkc^o*BIZ)DVwwvyrZhj=z(QZEQ+O!}G(U~7F4Tc0a%GdC<&MTy9RKWC| z@95F_K5e^rR(0YPoHae#duQM{6LR*4Wn7*wJx*T@L70YaA_W- zwaoMA=|c|BGvealXY!t6zOOJoIhhHEvM%)M(HU0cE!wlA4XI-3w z_nVFUccqo1?DNm!*ET5ia%6m|8ygxFRTHKEdm;Ojw7DCJKkT^6DjsDHr2YR68CLU% zx#i<;aGQv=pq|tGu7_J#DBCtz^~8VhCNVhzmx z0mi`>`7RBc4$}Li?TRmT;a+Ir;zWmrhQVz1>L9zi1yGlWR&oLy&V$kccd4OGB??exwI0#cHM9_*ToC35<8i}3@vFL8%aLf)u zlW`8Egr@jowQV3WFu$6O3hKC`dR&IpR~+jmX(A>pnJF$^>P4E%!Q|3r!wcV0RohCm zA{R53#u0Dpf$JMpDh%_85lJ7r`|6781q6=itH*E+QRpc1reiHsHfp9kiY|PkeaFX2 zc!cAd$&Cq3!N=zmK3OHLk6j~sh1=km+IhI$lb1iwLnS!W}96yApfHNk5@!eZn7 zH%x`pbP!G{@Ev4be!R{yt{%7|1QkiBCJ%6NnH2Wex=W{G1|xhwdSivtQQm_9CP^oP zeLfUG(GZKt68O9P%V$wapmzpS!`;1jF|T`cd|V!KJ~ZF&y;g9aNhypEVs135O0W=r z4zDB}IkLMo8D+_m8(U~0uE0DnzUP2av2|MoDjamz#9k9K!_gS2!S*p$Qpr+X?@+_l zFNl2f=sk>u5ljS0b(x)+KoEP(jBHTtU^Otz#mOS735c^^aS2$)`PCRF0T3(MM!9x2 zv!ei0GANDa3&%D;NB$!Tw>gwswS!cC`grGm)|4LttQy}FW#`9ZRT8MfT zH3LSZj>I>Ylxyd8AH6Z5Lhy)RZk}F-ugwmk3?WW*EG)`+RKRUt!j~A3>vTR46m!KG zULRVSF$KUv9>_Bo*^>csNKjVH5gX&vgstP^}?}{_G zP5;QlYLl+6Xo55VOwp+HaD~pPg*cObTU6)}K{X+da6kWKrNOVunoCmh5sJeCs6ilb z4(hTd0F2}Gr*MK%(bC?EjEqb@%YgIt-Iww>XZ32W3%&+07xFiNHjPF)L{Ogi@`1wr ztqtA-1_;W`1Vd|#s~Z~pNtK445mqZgOf)6isDY0V3=Z_zq{Y;Z%V=_YWcLGkd5d7e zsvrKi`ARBc2fCA?2R~|?*@aa*$S^Pxza-gS0k6<>dcn#+`;cMFMiME$;fFW#gQK%sZbPd$Bg9!5+3;- zfL3GS2?Yb(>HJbe945E}NL75a6#0N)fe6?GToA?WB+m5Sqepi=R*Nz7di3t{2tHjJ zN`s{fe>Yq#v1LOF-DFHEXsj@)Vd!ZFHG-O2s;p#Yg7!jioeY8mGgMWA4^?8RZUZU};1x-U6W+P3SBsR!c# zN|Y>Ag3Rm+o+_>n_L1?*qxSBBH_mB;7AfKgbopHbU>ukxQP3 zBiB#&m4u@FGZu|+pK`?BCrIQRD1Go?(E~mjl?1&9kzEiNuIH%uqBKeQy4%ntxjJ{; zu>9}WC(wt^g6I@4rLUI0d;=Z1R*qI6@XaHLr(jDw8_aMdT)>6i@K6^~t+f;}Ezr&H zv9XL(z}K_F95&{)lR$@~Uk^nwv^&n#GlUN60^B4+8*2rEK}?xY*Lx3L0$rZ)IXLFwL#j{iTO%VPDBJ}v zSzCWK2(5z6p&1j6AM3CZg89@`>^Ct$o`sWsu5NBuS|#RZXJ2KG-oR+98kiJx1S9BS zUS^t+W|m}QDUl0#-RB{`K z`JzhnYTyP5`9RdH8PbNR0L z$reZkuw6sVL76%>_TmAq%yFxkjde{O+aliu_?Jo8+U7n~QTs#B9}*dPG}o4$X!IZf zz$hkAvl0*R!IuYD?JPq>LME`sl_WaICP%(~I}1GC+$etybaWli6*9Yq#{gK8I<-9j zd^tkk0aUDTWKlY|3y~E>>g-PdPu2L=L{|yo=-}SHw}9Dw$TO;vSTKGJ8(pBJNl_&8 zL9%s7-78;RO^q8sCw!uSGqr*n0>8Td`y7{PiXbhAx9>}Soq|ht20XPL&9_SY*V!H4 zW_R5FhW1Mdz3VqV3NcqV7}Q>-JZ`b=rp2~{`(0l3$Oe}M`^_p$Cdb74sclf*@MBNw zo?k=5aqf9(!Dnih4#y-WWWRmu8M6TrljGfnuO67LSr+oXOt7x9dvQv+^gl1toPA9+ zyv#wJH1ZkDbmyl_tYU-49Hp!-vIO!jpkUBbQm$|^Os+}FynLMlWW1J42B0R(N^h+i%I+YvN~a2RcsL%A1l3qpbG3NZe1lR^bc zBKpg`LsVGhQVood#CgRX90!E?BATx2tZSPRX=FUEk?}A@ctBLyjkl4Zn`b;-qft-M ziesDI&1Uuw{WC_Tuglh4l8w(V*vC9fdFed5;E=LUy1jl}t}gva(93Tu1>KJNl~+bJ zWf(={|J(mUC3~dv>4nI@+v3^)LG`}4b`}AL%|m_(Ml8Ny-C&_fTts?Mh=6?{K_Bo4 zs%BXvS1`x-Wp!*wMh>FFl^G+WMFh>pH(mlmtsZ>M^I_zm`hkqHyU_eFB7Qx(M6jx|nYYp5x935!3v%rE5MC{jCh zR#Z)1FR=9Te&KqBKUQq+`=1Nx*>vVyj1K(aSq8h6x)~E)oI0IjT(&ruCA;QpR+$z*XWPR^sX!J(h!G&8uPov83Y5f+b1#JgwRX zpdPyjFkXHSp!4M)oVbQp!KPZmrx56fv*Rl~!8fU=aAr160nCBkG7cx^Isid^BMTv> zEbV73Cs%%MKylhM+mC|T<@%R%^yi*E4Y~DqQ?F=eM^;?IS97PH8!d9f5f4)WN-vKZ zr$t{=e755C=52pP)+go^M&Dv^m3=DLm3+N4bmmg^sjHbxqHh^S6(iIosW|O z&KB)-zp&F?_4-oW{i6j7!{Hh+HU|#$RGqYKVL9aao92gU$~D;y*9OnL8+b9~#R_#2 zro!hw-y9sDDkht5Kx8<7?|%mwF=(-qFCE6IQ85#5KXg!YANA}&o(Ah5XWNZuEH@Cz zew>q97XTxgeEYCL$e#P-1F29x;d*7Qd-rc# zUl7_E^Kd@#)ssjCUb}4^p;e3rXC0RNWVmdHW^#wWUiR+4Ou1wCOkNk4)O3k$i@XHI zfbFq&X(G$kk!P$Hy0~|pp9u~-kkPA?S^nz887Sf|J>U1ebf47xk3BZBymt2^48?Pz zK4xjCssDBmx9+FvxS;&)xz1pbZq26|apaK!zer2G=RDshEzB8+$TfYyFC7_$qytYmG$mj&zL}TmHH+df$nocV| zqb^0yT_B^Ma=)qD_Nj-<{`dbeC{KqzF8`yWbVfy^r^4mt$Z(2D+g-yQ3CABSueoR4 z5bcTiyLs6xLqg!;h|PiSB{#fr`{;OqLaBgtX%@V~&!f{_sDa4Q2 z+=fh;Q6sscYu}C=M=@iUG@9?r!*0FV`a7FJ}-;x1>>lM>}eCF z&!6_sDA<=Sv3{!6`gnh)6=Ki_eWBYo?p-Z?ZCdf4yM2l0kpAQ3qEM-q;>aXsz#K6GizU7viVxU|b|J+c;s?2PPc%|D5#t36wcM=< z`}Pb7vRlRKgFZ~Q`r1{+>KXqYn3m_C;yU?hcM%DK5Y{}0R?JcS^PwkUy*8pGyQ81C z-SYt$B++5u{)2f{RwDU7NCpG?%j@4_(48z57PDHGl#tt3!TA;;X(8%PrBm1HKrctO(*`5 zfWhd#lK89m5Y3zq4eBU+7pnM({094cL@ZKd!hF3=WLrAD z_~Y%UVR~#TXN2CxLq-D(CIu+MM%@B5?3~nb|NfAWx3@P?jrFHcZh>J2L1d2vPP9=V z5YP%7;BTtLMk$6fcB@M`ZXvw-_~^77(JG@1+=qZqc0qBgI@tCb7xut+$HqA+`2WgY z1R|)h#Ii2o56IBdTe{Z3dFb2VfVdI46g=zkw52p@?3xu zLZVLZFtlZN2;}ejKwPrz_?<`_Vbk&f@+23x{2vb@h$cuBgfP@qEv2&rQDl zpwg|Sf&Zy!mfjg1?O~~W5IHzbDz)K3r|Yjl-;ao9zUqxW0Zb_uUA>& z!3Yuo@1TWdxe?vx0rl}WzWuwaU1(Q}e`_6nc4TE<#BW7no4U@IuIEEuI=`moR4(09 zp@LYFIUEejbGt;UqJ$4<(O++mgj_pn@ zvnvyK88@k`roPL%>=i%Jvdih0>qqBPo*Tx4zbUEd{Ib4iFLkY>`?9dB#wL?B=S-)H zs@%-8M>kyC!(zE;OWm!hb-Qanz6{lDep-WSK!Xo&j8TVV*PH6{68(2??^v8v-rw=4 zVTR>~oy19jtw)c3|3)M2)-I-KS@y1n@~C2&{jrPWmEizy$LEu2YaXmVuS#PhZD}(8 zUuvrFPanGb>wN}&YQdMCobwLDHm_%P`xYt?EVSn;ZteR0efT* zmz^}J?)ber(PAEF^37zcUZ^gQj!HvE^ENHP`1!@N$n^5@@859odGJrU53RViG`_4Shb~&OEVA_qKOdU%PIEXUKWlsPAbs0dG5!B5>{`R2T-WflRC`xT(l`ql zG?=1HLdZ_o2!(P=h+#@=rdWfCG>ha^mh-6$D`d!OFeBtNl;axbp^1@U#wj)AG*~(8 z_pAM5|J(EHyWV-Pnd|+&_j$hOzTf+Ko(CTmou$XqKgUO_INS}0j1$TE5H?_4flVzw zbvzr%wNle*Ys;I#$*f$i7kkUPMt$DcExbLrIZBniU2;%lu>hc8C#ZYbd^{28jM!Mw3&R=kwT$&B947K;Q z-i^~u@(lucd$Bn$42LwTA2z&QD>p@0GcsDn3l0iy@}?-Z!(}EXnPm8~(ale#41Sm@ zv}uwv0d7%-S$3DN9Zp{vs3BYx4{dteWAdtA&*b6SH1_K<9^LK#$%>w6R_Fs4X-p^F zZ#akgcEsctJ=RX=H!&P|r0JZl(R%02p96jBq9O!>UDV(`3Ki`6ZAAc|0a+lK%|8|e>&SiPR87lu>=zzA z-N=Be)dwmqt%qtOElAlt6KE$nry;suOtv}PeW6Z3Cb^xuh8OkFWpYT>ge41O+?@RS zy~Ibx;!bXV&jCHXO=NyMTqtrogU;B#Qkk$~lde#sSoM)Zp7P+TKz|xrf7BSbAKLNq z2i39<#~S-$JH5mZ|3KXN`1!cOR@uh23x;xwgrW67oK$-+r`UCSEJl5dpg9t~YJoP~ zshlKIqbLo(yG;o?{oOs0fA5iz-NEgBcF>K8#h-mOH@CrlYzIrzeqP|=YwRR{#5iOo z{8Jh)m(xHF3r~dZzw%NfaBjO;_*I76h9sgeus0q@91y)v?_SYE3yo zIw8fI&tLRLs$8tf%C6E$ZNe9Ea>z$e`rBmNW<3U`zc5-6sq#fX1HHS|vsy`}uSxNb z)1m<8tb0eH&&WTSpE8@3&@NJq?ZjHLUZ%6(sJW zPnDfq3d#19Sqs{$q}4OtFhgD^W`#G41Fw~AY_l0KYRw68aFO$y21ZJ}VJ#=JgPln3 zZ^*Iibx>7BX{Oh%s!TaV@~l&8eMvPo=qDSRWX%^rX-n^k1=Vn@H*UDp?WfHemgx>M zp%Uk{(DrRD-lj^iDo}YWx*x`NlqBU=-`Kb|A6k`=oET$3UyXg_%&_du1*+im zUQCB$Q5c?mpTD`!ibVeWVC=`Uj8Xe_G>X`QGxS#`+DbV+3pb$^6*v|guNvR;+NCYcv$QVZL|Wd# zkTxQpwSX5;$MAlxS>d}fD(I|xq$Id#>DstsP|!02@62;`E-m+mv8c1 zj|#58q3SE$c~_mU#cn;P)xs&hY?`T1u4oZj#B13j-sWxEfMRWJ zTMojjEqn}R1^A5l;;2lEePxDabk7RRSVC=ZzyRJgSLrD5k+a&YIFGrw^J1;WJNqqz zP#VIVnysiade{W1#t<&@Xm#*HYeW5yEhh%y{d~)sLw8iP>`zT{Z`HqlXEvlGESCxB zZ>wft7D?I$hBc<&ZFN(n+4i6Is+D&zUVJ3}PcF`H@(H1*Wu(~E>vmD-4xA~LHr9% z0ju0^07WI=ukAam?m__`7>_lz`|+*>*Ajt{U;jRyp9J)WX5zjTXKR02Ebo$If8j(}1yz!827_pRx0-5Si*?|@pp?GJ`}RB_KTgfnX-$AI z=>W@GLtB0N`2;|5Q$-U3KgNP!n;njYuh*F5Ml86+1CvP3+8?J8-y+evdd1xPCB!iC z{Aq~oT8q&jg;V?DnazC=p_Vj~8w+EqW^MHdD10krpyZaGh5OkZ> zy&;ON7#vT6>ZI9##0NzWE&$aykTURqSL^*Sd*LGK8*WBH^`Ku>4k zyCK)am{P^m^Y56VISJ#u!mosie0GGr*t}loYL4x=H;o$-^!~2SNG~4(Ycn2nN@?`D zOz}J^lqzLrJ79Hf2Hl;Maf6YUQPNSL?3v1vltQ`S_07hvqvl=5NxPO{HyH!EwqI-hWlT>LDd`cm*&a&#sI39~2=2LUh) zWDN!c1c@{a4Jjb8(f|Yi{3M)lcLz;7p|+4<3OH7WN;HFFH$V;t+V#*GU}Sz-0dfLS x9q|9z{TvNu-~Y2A+27KC*ZN^afK8wxww1=OV`Xk Date: Tue, 2 Jun 2026 11:13:36 +0900 Subject: [PATCH 09/10] =?UTF-8?q?docs:=20DevLogUI=20=EC=95=84=ED=82=A4?= =?UTF-8?q?=ED=85=8D=EC=B3=90=20=ED=95=98=EB=84=A4=EC=8A=A4=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devlog-architecture-harness/SKILL.md | 5 +++-- .../references/devlog-architecture-flow.md | 18 +++++++++++++----- AGENTS.md | 8 +++++--- README.md | 3 ++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.hermes/skills/devlog-architecture-harness/SKILL.md b/.hermes/skills/devlog-architecture-harness/SKILL.md index a26d4a8e..3fed85c9 100644 --- a/.hermes/skills/devlog-architecture-harness/SKILL.md +++ b/.hermes/skills/devlog-architecture-harness/SKILL.md @@ -74,8 +74,9 @@ Ask the user before editing when: - Core vs Domain ownership is unclear. - A shared type is being moved only because multiple modules need access. - Firebase/Auth/Firestore/Functions/Messaging-specific logic would leave Infra. -- WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, or App. -- Presentation would depend on Data, Infra, Persistence, or App. +- WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, UI, or App. +- Presentation would depend on UI, Data, Infra, Persistence, or App. +- UI would depend on Domain, Core, Data, Infra, Persistence, or App. - Data would gain concrete SDK or storage implementation details. - The Presentation `Store` flow or reducer responsibility would change. - A compile fix requires relaxing the intended architecture. diff --git a/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md index a3bb838e..d3380be7 100644 --- a/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md +++ b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md @@ -73,7 +73,8 @@ flowchart TD ```mermaid flowchart TD App["DevLogApp\nComposition root\nApp lifecycle\nAssembler wiring"] - Presentation["DevLogPresentation\nSwiftUI views\nViewModels\nCoordinators\nUI state"] + UI["DevLogUI\nSwiftUI views\nReusable components\nView composition"] + Presentation["DevLogPresentation\nStore\nViewModels\nCoordinators\nUI state"] Domain["DevLogDomain\nEntities\nRepository protocols\nUse cases"] Data["DevLogData\nRepository implementations\nDTOs\nMappers\nService/store protocols"] Infra["DevLogInfra\nFirebase\nSocial login\nNetwork\nLink metadata\nMessaging"] @@ -83,6 +84,7 @@ flowchart TD WidgetExtension["DevLogWidgetExtension\nWidgetKit UI\nProviders\nTimelines"] App --> Presentation + App --> UI App --> Domain App --> Data App --> Infra @@ -90,6 +92,8 @@ flowchart TD App --> Core App --> WidgetCore + UI --> Presentation + Presentation --> Domain Presentation --> Core @@ -114,13 +118,14 @@ flowchart TD | Layer | Owns | Allowed direction | Ask before | | --- | --- | --- | --- | | `DevLogCore` | DI primitives, logger, shared value/query types, widget snapshot values | No DevLog layer dependency | Moving domain entities into Core | -| `DevLogDomain` | entities, repository protocols, use cases | Core only | Adding Data, Infra, Persistence, Presentation, App, Widget UI, or SDK dependency | +| `DevLogDomain` | entities, repository protocols, use cases | Core only | Adding Data, Infra, Persistence, Presentation, UI, App, Widget UI, or SDK dependency | | `DevLogData` | repository implementations, DTOs, mappers, data protocols | Domain, Core | Adding concrete Firebase, WidgetKit, storage, or platform implementation details | | `DevLogInfra` | Firebase, social login, network, metadata, messaging implementations | Data, Core | Moving SDK-specific behavior out of Infra | | `DevLogPersistence` | local stores, image cache, widget snapshot persistence | Data, Core, WidgetCore | Moving domain logic or remote SDK behavior into Persistence | -| `DevLogPresentation` | UI, view models, coordinators, presentation state | Domain, Core | Adding Data, Infra, Persistence, or App dependency | +| `DevLogPresentation` | Store, view models, coordinators, presentation state | Domain, Core | Adding UI, Data, Infra, Persistence, or App dependency | +| `DevLogUI` | SwiftUI views, reusable UI components, view composition | Presentation | Adding Domain, Core, Data, Infra, Persistence, or App dependency | | `DevLogApp` | composition root, lifecycle, assembler wiring | Concrete app layers | Moving feature logic into App | -| `DevLogWidgetCore` | widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, or App dependency | +| `DevLogWidgetCore` | widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, UI, or App dependency | | `DevLogWidgetExtension` | WidgetKit rendering and timeline plumbing | WidgetCore | Calling app/domain services directly | ## Presentation Store flow @@ -159,6 +164,7 @@ flowchart TD Shared{"Moved only because shared?"} NewDependency{"New module dependency?"} ExternalSDK{"External SDK crosses layer?"} + UIBoundary{"UI sees Domain/Core/Data/Infra/Persistence/App?"} WidgetBoundary{"WidgetCore sees app/domain/data?"} BuildShortcut{"Build fix relaxes boundary?"} ScopeDrift{"Outside current task scope?"} @@ -173,7 +179,9 @@ flowchart TD NewDependency -->|Yes| Ask NewDependency -->|No| ExternalSDK ExternalSDK -->|Yes| Ask - ExternalSDK -->|No| WidgetBoundary + ExternalSDK -->|No| UIBoundary + UIBoundary -->|Yes| Ask + UIBoundary -->|No| WidgetBoundary WidgetBoundary -->|Yes| Ask WidgetBoundary -->|No| BuildShortcut BuildShortcut -->|Yes| Ask diff --git a/AGENTS.md b/AGENTS.md index ffe89dec..b2e49876 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,13 +43,14 @@ Treat this repository as an Xcode workspace-based modular iOS app. There is no r ### Current layer map - `Application/DevLogCore`: shared app primitives such as DI, logging, query/value types, display options, and widget snapshot value types. Core is shared, but shared access alone is not enough reason to move domain entities into Core. -- `Application/DevLogDomain`: entities, repository protocols, use case protocols, and use case implementations. Domain may depend on Core. Domain must not depend on Data, Infra, Persistence, Presentation, App, Widget extension UI, Firebase SDKs, or storage implementations. +- `Application/DevLogDomain`: entities, repository protocols, use case protocols, and use case implementations. Domain may depend on Core. Domain must not depend on Data, Infra, Persistence, Presentation, UI, App, Widget extension UI, Firebase SDKs, or storage implementations. - `Application/DevLogData`: repository implementations, DTOs, mappers, data-layer protocols for external services/stores, and widget sync coordination. Data may depend on Domain and Core. Data should not gain direct Firebase, GoogleSignIn, WidgetKit, or concrete storage implementation details unless the user explicitly approves the boundary change. - `Application/DevLogInfra`: Firebase, social login, network, link metadata, messaging, and platform service implementations. Infra may depend on Data and Core. Firebase/Auth/Firestore/Functions/Messaging-specific behavior belongs here unless the user approves another boundary. - `Application/DevLogPersistence`: local persistence, user defaults, image store, and widget snapshot persistence/updating. Persistence may depend on Data, Core, and WidgetCore when needed for snapshot persistence. -- `Application/DevLogPresentation`: SwiftUI views, view models, coordinators, UI state structures, and presentation-only helpers. Presentation may depend on Domain and Core. It must not depend on Data, Infra, Persistence, or App. +- `Application/DevLogPresentation`: Store, view models, coordinators, UI state structures, and presentation-only helpers. Presentation may depend on Domain and Core. It must not depend on UI, Data, Infra, Persistence, or App. +- `Application/DevLogUI`: SwiftUI views, reusable UI components, and view composition. UI may depend on Presentation. It must not depend on Domain, Core, Data, Infra, Persistence, or App. - `Application/DevLogApp`: composition root, app lifecycle, app delegate, app-level routing, and assembler wiring. App may import concrete layers to assemble the dependency graph. -- `Widget/DevLogWidgetCore`: widget snapshot models, factories, keys, app-group constants, and widget-only pure helpers. WidgetCore may depend on Core. It must not depend on Domain, Data, Infra, Persistence, Presentation, or App without explicit user approval. +- `Widget/DevLogWidgetCore`: widget snapshot models, factories, keys, app-group constants, and widget-only pure helpers. WidgetCore may depend on Core. It must not depend on Domain, Data, Infra, Persistence, Presentation, UI, or App without explicit user approval. - `Widget/DevLogWidgetExtension`: WidgetKit UI, widget providers, entries, timelines, and extension resources. It should consume WidgetCore outputs rather than app/domain services directly. - `Firebase/functions`: TypeScript Cloud Functions. Deploy updated functions one by one separately. @@ -68,6 +69,7 @@ Ask the user before editing when any of these are true: - A type could plausibly live in both Core and Domain. - A shared type is being moved only because multiple modules need access to it. - A new target dependency would make a lower-level module know a higher-level module. +- UI would start depending on Domain, Core, Data, Infra, Persistence, or App. - A build fix would be achieved by loosening an architecture boundary. - Firebase, GoogleSignIn, AuthenticationServices, UserNotifications, LinkPresentation, Network, WidgetKit, or storage implementation details would move to another layer. - A repository protocol, service protocol, assembler, or DI ownership boundary would change. diff --git a/README.md b/README.md index c42bd41e..d2d39de9 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,8 @@ SwiftUI_DevLog/ │ ├── DevLogData/ # Repository 구현, DTO, Mapper, Data 계층 Protocol │ ├── DevLogInfra/ # Firebase, 소셜 로그인, 네트워크, 메타데이터 서비스 구현 │ ├── DevLogPersistence/ # UserDefaults, 이미지 저장소, 위젯 스냅샷 영속성 처리 -│ └── DevLogPresentation/ # SwiftUI 화면, ViewModel, Store, Coordinator +│ ├── DevLogPresentation/ # ViewModel, Store, Coordinator, 화면 상태 +│ └── DevLogUI/ # SwiftUI 화면, 재사용 UI 컴포넌트 ├── Widget/ │ ├── DevLogWidgetCore/ # 위젯 스냅샷 모델, Factory, App Group 상수 │ └── DevLogWidgetExtension/ # WidgetKit UI, Provider, Timeline From 18855f66a693f813239a7b1349090f1a349cf8be Mon Sep 17 00:00:00 2001 From: opficdev <162981733+opficdev@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:52:39 +0900 Subject: [PATCH 10/10] =?UTF-8?q?chore:=20DevLogUI=20Core=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hermes/skills/devlog-architecture-harness/SKILL.md | 2 +- .../references/devlog-architecture-flow.md | 5 +++-- AGENTS.md | 4 ++-- Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj | 4 ++++ Application/DevLogUI/Project.swift | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.hermes/skills/devlog-architecture-harness/SKILL.md b/.hermes/skills/devlog-architecture-harness/SKILL.md index 3fed85c9..8dd3d477 100644 --- a/.hermes/skills/devlog-architecture-harness/SKILL.md +++ b/.hermes/skills/devlog-architecture-harness/SKILL.md @@ -76,7 +76,7 @@ Ask the user before editing when: - Firebase/Auth/Firestore/Functions/Messaging-specific logic would leave Infra. - WidgetCore would depend on Domain, Data, Infra, Persistence, Presentation, UI, or App. - Presentation would depend on UI, Data, Infra, Persistence, or App. -- UI would depend on Domain, Core, Data, Infra, Persistence, or App. +- UI would depend on Domain, Data, Infra, Persistence, or App. - Data would gain concrete SDK or storage implementation details. - The Presentation `Store` flow or reducer responsibility would change. - A compile fix requires relaxing the intended architecture. diff --git a/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md index d3380be7..42373d5f 100644 --- a/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md +++ b/.hermes/skills/devlog-architecture-harness/references/devlog-architecture-flow.md @@ -93,6 +93,7 @@ flowchart TD App --> WidgetCore UI --> Presentation + UI --> Core Presentation --> Domain Presentation --> Core @@ -123,7 +124,7 @@ flowchart TD | `DevLogInfra` | Firebase, social login, network, metadata, messaging implementations | Data, Core | Moving SDK-specific behavior out of Infra | | `DevLogPersistence` | local stores, image cache, widget snapshot persistence | Data, Core, WidgetCore | Moving domain logic or remote SDK behavior into Persistence | | `DevLogPresentation` | Store, view models, coordinators, presentation state | Domain, Core | Adding UI, Data, Infra, Persistence, or App dependency | -| `DevLogUI` | SwiftUI views, reusable UI components, view composition | Presentation | Adding Domain, Core, Data, Infra, Persistence, or App dependency | +| `DevLogUI` | SwiftUI views, reusable UI components, view composition | Presentation, Core | Adding Domain, Data, Infra, Persistence, or App dependency | | `DevLogApp` | composition root, lifecycle, assembler wiring | Concrete app layers | Moving feature logic into App | | `DevLogWidgetCore` | widget data contracts and pure snapshot logic | Core | Adding Domain, Data, Infra, Persistence, Presentation, UI, or App dependency | | `DevLogWidgetExtension` | WidgetKit rendering and timeline plumbing | WidgetCore | Calling app/domain services directly | @@ -164,7 +165,7 @@ flowchart TD Shared{"Moved only because shared?"} NewDependency{"New module dependency?"} ExternalSDK{"External SDK crosses layer?"} - UIBoundary{"UI sees Domain/Core/Data/Infra/Persistence/App?"} + UIBoundary{"UI sees Domain/Data/Infra/Persistence/App?"} WidgetBoundary{"WidgetCore sees app/domain/data?"} BuildShortcut{"Build fix relaxes boundary?"} ScopeDrift{"Outside current task scope?"} diff --git a/AGENTS.md b/AGENTS.md index b2e49876..2d0cf39b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,7 +48,7 @@ Treat this repository as an Xcode workspace-based modular iOS app. There is no r - `Application/DevLogInfra`: Firebase, social login, network, link metadata, messaging, and platform service implementations. Infra may depend on Data and Core. Firebase/Auth/Firestore/Functions/Messaging-specific behavior belongs here unless the user approves another boundary. - `Application/DevLogPersistence`: local persistence, user defaults, image store, and widget snapshot persistence/updating. Persistence may depend on Data, Core, and WidgetCore when needed for snapshot persistence. - `Application/DevLogPresentation`: Store, view models, coordinators, UI state structures, and presentation-only helpers. Presentation may depend on Domain and Core. It must not depend on UI, Data, Infra, Persistence, or App. -- `Application/DevLogUI`: SwiftUI views, reusable UI components, and view composition. UI may depend on Presentation. It must not depend on Domain, Core, Data, Infra, Persistence, or App. +- `Application/DevLogUI`: SwiftUI views, reusable UI components, and view composition. UI may depend on Presentation and Core. It must not depend on Domain, Data, Infra, Persistence, or App. - `Application/DevLogApp`: composition root, app lifecycle, app delegate, app-level routing, and assembler wiring. App may import concrete layers to assemble the dependency graph. - `Widget/DevLogWidgetCore`: widget snapshot models, factories, keys, app-group constants, and widget-only pure helpers. WidgetCore may depend on Core. It must not depend on Domain, Data, Infra, Persistence, Presentation, UI, or App without explicit user approval. - `Widget/DevLogWidgetExtension`: WidgetKit UI, widget providers, entries, timelines, and extension resources. It should consume WidgetCore outputs rather than app/domain services directly. @@ -69,7 +69,7 @@ Ask the user before editing when any of these are true: - A type could plausibly live in both Core and Domain. - A shared type is being moved only because multiple modules need access to it. - A new target dependency would make a lower-level module know a higher-level module. -- UI would start depending on Domain, Core, Data, Infra, Persistence, or App. +- UI would start depending on Domain, Data, Infra, Persistence, or App. - A build fix would be achieved by loosening an architecture boundary. - Firebase, GoogleSignIn, AuthenticationServices, UserNotifications, LinkPresentation, Network, WidgetKit, or storage implementation details would move to another layer. - A repository protocol, service protocol, assembler, or DI ownership boundary would change. diff --git a/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj b/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj index 5e4a830e..7ff00ded 100644 --- a/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj +++ b/Application/DevLogUI/DevLogUI.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 07DC30D6EE53D3FEB18D4560 /* WebItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99F78B3C0ACB40D516459405 /* WebItemRow.swift */; }; 1F194D9E0C40F9C8D0BBFD81 /* CacheableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211DFAB11C0329E438E5D600 /* CacheableImage.swift */; }; + 35A74D1DFFD61848769F68B9 /* DevLogCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6127A27F1781E689752EA11A /* DevLogCore.framework */; }; 3BC362E7B3729B9B766D0E82 /* TodoItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 529B9370AF656D07E6CF9C75 /* TodoItemRow.swift */; }; 3CD4C5F7BA6AE10FD96EED2D /* PushNotificationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD11529C090F3011129AC4A3 /* PushNotificationListView.swift */; }; 436190F41C9108F6D4936027 /* TodoInfoSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19FC36435309F9D84B455253 /* TodoInfoSheetView.swift */; }; @@ -75,6 +76,7 @@ 56823A0901F960041578908A /* AccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountView.swift; sourceTree = ""; }; 5AF9DFAB631D9D4BFE8D5891 /* TodoManageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodoManageView.swift; sourceTree = ""; }; 6056412772C2E91882B9C3D3 /* EnvironmentValues+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+.swift"; sourceTree = ""; }; + 6127A27F1781E689752EA11A /* DevLogCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DevLogCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6B63ED91862D0C29DCF3ACA6 /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = ""; }; 77A2025370CB07568F045A6E /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = ""; }; 80338B4AC83F0BC401B73C81 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; @@ -105,6 +107,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 35A74D1DFFD61848769F68B9 /* DevLogCore.framework in Frameworks */, AC8A6800BA486E5B49DF24D3 /* DevLogPresentation.framework in Frameworks */, FD6C0E913FFA9988FFCF8419 /* MarkdownUI in Frameworks */, 9D8ECA3815FA283133EBFE93 /* OrderedCollections in Frameworks */, @@ -234,6 +237,7 @@ B94A7F98803FFD2D526DC3F0 /* Products */ = { isa = PBXGroup; children = ( + 6127A27F1781E689752EA11A /* DevLogCore.framework */, D26E37F394F95F6AA0B184A4 /* DevLogPresentation.framework */, CA0F9AEA78082777BD930922 /* DevLogUI.framework */, ); diff --git a/Application/DevLogUI/Project.swift b/Application/DevLogUI/Project.swift index 6691decc..77807d7a 100644 --- a/Application/DevLogUI/Project.swift +++ b/Application/DevLogUI/Project.swift @@ -7,6 +7,7 @@ let project = Project.devlogFramework( versionXcconfigPath: "../Shared/Version.xcconfig", packages: DevLogPackages.presentationPackages, dependencies: [ + .project(target: "DevLogCore", path: "../DevLogCore"), .project(target: "DevLogPresentation", path: "../DevLogPresentation"), ] + DevLogPackages.presentationPackageDependencies, hasTests: false

- App Architecture + App Architecture