diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeView.swift b/Application/DevLogPresentation/Sources/Home/Home/HomeView.swift index 45b19ddb..3627f29d 100644 --- a/Application/DevLogPresentation/Sources/Home/Home/HomeView.swift +++ b/Application/DevLogPresentation/Sources/Home/Home/HomeView.swift @@ -82,9 +82,6 @@ struct HomeView: View { .font(.caption) .multilineTextAlignment(.center) } - .onAppear { - coordinator.viewModel.send(.onAppear) - } .overlay { if coordinator.viewModel.state.isAppending { LoadingView() diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift b/Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift index 1508b86c..477d4d44 100644 --- a/Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift +++ b/Application/DevLogPresentation/Sources/Home/Home/HomeViewCoordinator.swift @@ -45,6 +45,10 @@ final class HomeViewCoordinator { ) } + func loadInitialData() { + viewModel.send(.loadInitialData) + } + func makeTodoManageViewModel() -> TodoManageViewModel { TodoManageViewModel(viewModel.state.preferences) } diff --git a/Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift b/Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift index ed634c75..11cb785b 100644 --- a/Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift +++ b/Application/DevLogPresentation/Sources/Home/Home/HomeViewModel.swift @@ -38,7 +38,7 @@ final class HomeViewModel: Store { } enum Action { - case onAppear + case loadInitialData case networkStatusChanged(Bool) case setPresentation(Presentation, Bool) case setAlert(isPresented: Bool, type: AlertType? = nil) @@ -145,7 +145,7 @@ final class HomeViewModel: Store { switch action { case .networkStatusChanged(let isConnected): state.isNetworkConnected = isConnected - case .onAppear, .setPresentation, .setAlert, .setToast, .refreshWebPages, + case .loadInitialData, .setPresentation, .setAlert, .setToast, .refreshWebPages, .tapTodoCategory, .orderTodoCategory, .addTodo, .updateWebPageURLInput, .addWebPage, .deleteWebPage, .undoDeleteWebPage: effects = reduceByView(action, state: &state) @@ -274,7 +274,7 @@ private extension HomeViewModel { // swiftlint:disable cyclomatic_complexity func reduceByView(_ action: Action, state: inout State) -> [SideEffect] { switch action { - case .onAppear: + case .loadInitialData: return [.fetchTodoCategoryPreferences, .fetchRecentTodos, .fetchWebPages] case .refreshWebPages: return [.fetchWebPages] diff --git a/Application/DevLogPresentation/Sources/Main/MainView.swift b/Application/DevLogPresentation/Sources/Main/MainView.swift index ed8a86c0..b9dc7471 100644 --- a/Application/DevLogPresentation/Sources/Main/MainView.swift +++ b/Application/DevLogPresentation/Sources/Main/MainView.swift @@ -15,11 +15,11 @@ struct MainView: View { @State private var homeViewCoordinator: HomeViewCoordinator @State private var todayViewCoordinator: TodayViewCoordinator @State private var profileViewCoordinator: ProfileViewCoordinator - @Binding var selectedTab: MainTab + @Binding var selectedTab: MainTab? init( container: DIContainer, - selectedTab: Binding + selectedTab: Binding ) { self._coordinator = State(initialValue: MainViewCoordinator(container: container)) self._homeViewCoordinator = State(initialValue: HomeViewCoordinator(container: container)) @@ -30,15 +30,22 @@ struct MainView: View { var body: some View { Group { - if isCompactLayout { - tabView - } else { - sidebarView + if let selectedTab { + if isCompactLayout { + tabView + } else { + sidebarView(for: selectedTab) + } } } .onAppear { coordinator.mainViewModel.send(.onAppear) } + .onChange(of: selectedTab) { _, newValue in + if newValue == .home { + homeViewCoordinator.loadInitialData() + } + } .alert( coordinator.mainViewModel.state.alertTitle, isPresented: mainAlertPresented @@ -55,37 +62,37 @@ struct MainView: View { .tabItem { tabLabel(.home) } - .tag(MainTab.home) + .tag(MainTab.home as MainTab?) todayView .tabItem { tabLabel(.today) } - .tag(MainTab.today) + .tag(MainTab.today as MainTab?) notificationView .tabItem { tabLabel(.notification) } .badge(coordinator.mainViewModel.state.unreadPushCount) - .tag(MainTab.notification) + .tag(MainTab.notification as MainTab?) profileView .tabItem { tabLabel(.profile) } - .tag(MainTab.profile) + .tag(MainTab.profile as MainTab?) } } @ViewBuilder - private var sidebarView: some View { + private func sidebarView(for selectedTab: MainTab) -> some View { switch selectedTab.mainTabSplitStyle { case .detailOnly: NavigationSplitView { mainSidebar } detail: { - selectedTabView + selectedTabView(for: selectedTab) } case .contentDetail: switch selectedTab { @@ -138,7 +145,7 @@ struct MainView: View { NavigationSplitView { mainSidebar } detail: { - selectedTabView + selectedTabView(for: selectedTab) } } } @@ -155,7 +162,7 @@ struct MainView: View { } @ViewBuilder - private var selectedTabView: some View { + private func selectedTabView(for selectedTab: MainTab) -> some View { switch selectedTab { case .home: homeView diff --git a/Application/DevLogPresentation/Sources/Root/RootView.swift b/Application/DevLogPresentation/Sources/Root/RootView.swift index 58a46cc4..81c34307 100644 --- a/Application/DevLogPresentation/Sources/Root/RootView.swift +++ b/Application/DevLogPresentation/Sources/Root/RootView.swift @@ -14,7 +14,7 @@ public struct RootView: View { @Environment(\.diContainer) var container: DIContainer @State var viewModel: RootViewModel @State private var selectedRoute: Route? - @State private var selectedMainTab = MainTab.home + @State private var selectedMainTab: MainTab? private let widgetURLTab: (URL) -> MainTab? private let pushNotificationTodoIdPublisher: AnyPublisher private let clearPushNotificationRoute: () -> Void @@ -56,16 +56,22 @@ public struct RootView: View { .preferredColorScheme(viewModel.state.theme.colorScheme) .onAppear { viewModel.send(.onAppear) } .onChange(of: viewModel.state.signIn) { _, value in - guard value == false else { return } - selectedMainTab = .home + guard let value else { return } + if value { + selectedMainTab = .home + } else { + selectedMainTab = nil + } } .onOpenURL { url in guard let mainTab = widgetURLTab(url) else { return } switch viewModel.state.signIn { case .some(false): - selectedMainTab = .home - case .some(true), .none: + break + case .some(true): selectedMainTab = mainTab + case .none: + break } } .alert(viewModel.state.alertTitle, isPresented: Binding( diff --git a/Application/DevLogPresentation/Tests/WebPage/DeleteWebPageTests.swift b/Application/DevLogPresentation/Tests/WebPage/DeleteWebPageTests.swift index 2af51c17..45c54902 100644 --- a/Application/DevLogPresentation/Tests/WebPage/DeleteWebPageTests.swift +++ b/Application/DevLogPresentation/Tests/WebPage/DeleteWebPageTests.swift @@ -45,7 +45,7 @@ struct DeleteWebPageTests { networkConnectivityUseCase: observeNetworkConnectivityUseCaseSpy ) - homeViewModel.send(.onAppear) + homeViewModel.send(.loadInitialData) await waitUntil { !homeViewModel.state.webPages.isEmpty } @@ -97,7 +97,7 @@ struct DeleteWebPageTests { networkConnectivityUseCase: observeNetworkConnectivityUseCaseSpy ) - homeViewModel.send(.onAppear) + homeViewModel.send(.loadInitialData) await waitUntil { !homeViewModel.state.webPages.isEmpty }