diff --git a/Projects/Feature/Feature/Sources/AppView.swift b/Projects/Feature/Feature/Sources/AppView.swift index 67a3827..b9ba3b9 100644 --- a/Projects/Feature/Feature/Sources/AppView.swift +++ b/Projects/Feature/Feature/Sources/AppView.swift @@ -18,35 +18,36 @@ import ComposableArchitecture public struct AppView: View { @Bindable var store: StoreOf - + public init(store: StoreOf) { self.store = store } public var body: some View { - Group { - if let splashStore = store.scope(state: \.splash, action: \.splash) { - SplashView(store: splashStore) - .zIndex(0) - } else if let onboardingStore = store.scope(state: \.onboarding, action: \.onboarding) { - NavigationStack { - OnboardingView(store: onboardingStore) - .zIndex(1) - } - } else if let homeStore = store.scope(state: \.home, action: \.home) { - NavigationStack { - HomeView(store: homeStore) - .zIndex(2) + ZStack { + Group { + if let splashStore = store.scope(state: \.splash, action: \.splash) { + SplashView(store: splashStore) + .zIndex(0) + } else if let onboardingStore = store.scope(state: \.onboarding, action: \.onboarding) { + NavigationStack { + OnboardingView(store: onboardingStore) + .zIndex(1) + } + } else if let homeStore = store.scope(state: \.home, action: \.home) { + NavigationStack { + HomeView(store: homeStore) + .transition(.opacity.animation(.easeInOut)) + .zIndex(2) + } + } else { + Global.Color.black // MARK: - DB정보 없고 오프라인일때 Dialog 띄우기 + .zIndex(3) } - } else { - Global.Color.black // MARK: - DB정보 없고 오프라인일때 Dialog 띄우기 - .zIndex(3) } - } - .transition(.opacity) - .animation(.easeInOut, value: store.home == nil) - .fullScreenCover(isPresented: $store.isLoading) { - LoadingView() + if store.isLoading { + LoadingView() + } } .fullScreenCover( item: $store.scope( @@ -64,10 +65,6 @@ public struct AppView: View { ) { store in NetworkErrorView(store: store) } - .transaction(value: store.isLoading) { transaction in - // TODO: 11.25 로딩 이외 다른 fullScreen들도 disabled됨 - transaction.disablesAnimations = true - } .onLoad { store.send(.onLoad) } diff --git a/Projects/Feature/HomeFeature/Sources/Home/HomeCore.swift b/Projects/Feature/HomeFeature/Sources/Home/HomeCore.swift index f1d3fd9..cb8c994 100644 --- a/Projects/Feature/HomeFeature/Sources/Home/HomeCore.swift +++ b/Projects/Feature/HomeFeature/Sources/Home/HomeCore.swift @@ -33,19 +33,19 @@ public struct HomeCore { var selectedCategory: PomodoroCategory? var selectedCat: SomeCat? - - var isNetworkConnected: Bool = false - + + var isNetworkConnected: Bool = true + var toast: DefaultToast? var dialog: DefaultDialog? - + var catRiv: RiveViewModel = Rive.catHomeRiv(stateMachineName: "State Machine_Home") - + @Presents var categorySelect: CategorySelectCore.State? @Presents var timeSelect: TimeSelectCore.State? - @Presents var focusPomodoro: FocusPomodoroCore.State? @Presents var myPage: MyPageCore.State? - + @Presents var pomodoro: PomodoroCore.State? + public init() {} } @@ -68,8 +68,8 @@ public struct HomeCore { case syncCategory case categorySelect(PresentationAction) case timeSelect(PresentationAction) - case focusPomodoro(PresentationAction) case myPage(PresentationAction) + case pomodoro(PresentationAction) } @Dependency(UserDefaultsClient.self) var userDefaultsClient @@ -91,26 +91,26 @@ public struct HomeCore { .ifLet(\.$timeSelect, action: \.timeSelect) { TimeSelectCore() } - .ifLet(\.$focusPomodoro, action: \.focusPomodoro) { - FocusPomodoroCore() - } .ifLet(\.$myPage, action: \.myPage) { MyPageCore() } + .ifLet(\.$pomodoro, action: \.pomodoro) { + PomodoroCore() + } } private func core(_ state: inout State, _ action: Action) -> EffectOf { switch action { case .binding: return .none - + case .task: return .run { send in for await isConnected in networkTracking.updateNetworkConnected() { await send(._fetchNetworkConnection(isConnected)) } } - + case .onLoad: return .run { send in if self.userDefaultsClient.boolForKey(isHomeGuideCompletedKey) == false { @@ -162,7 +162,7 @@ public struct HomeCore { return .none case .playButtonTapped: - state.focusPomodoro = .init() + state.pomodoro = .init() return .none case .catTapped: @@ -177,11 +177,11 @@ public struct HomeCore { state.catRiv.reset() state.catRiv.setInput(selectedCat.rivInputName, value: true) return .none - + case let ._fetchNetworkConnection(isConnected): state.isNetworkConnected = isConnected return .none - + case .syncCategory: return .run { send in try await self.pomodoroService.syncCategoryList( @@ -221,7 +221,9 @@ public struct HomeCore { return .none case .timeSelect(.presented(.bottomCheckButtonTapped)): - guard let mode = state.timeSelect?.mode else { return .none } + guard let mode = state.timeSelect?.mode, + state.timeSelect?.isTimeChanged == true + else { return .none } var message: String switch mode { case .focus: @@ -246,9 +248,9 @@ public struct HomeCore { case .myPage: return .none - case let .focusPomodoro(.presented(.saveHistory(focusTimeBySeconds, restTimeBySeconds))), // FocusPomodoro - let .focusPomodoro(.presented(.restWaiting(.presented(.saveHistory(focusTimeBySeconds, restTimeBySeconds))))), // RestWaiting - let .focusPomodoro(.presented(.restWaiting(.presented(.restPomodoro(.presented(.saveHistory(focusTimeBySeconds, restTimeBySeconds))))))): // RestPomodoro + case let .pomodoro(.presented(.focusPomodoro(.saveHistory(focusTimeBySeconds, restTimeBySeconds)))), // FocusPomodoro + let .pomodoro(.presented(.restWaiting(.saveHistory(focusTimeBySeconds, restTimeBySeconds)))), // RestWaiting + let .pomodoro(.presented(.restPomodoro(.saveHistory(focusTimeBySeconds, restTimeBySeconds)))): // RestPomodoro guard let selectedCategoryID = state.selectedCategory?.id else { return .none } if focusTimeBySeconds >= 60 { return .run { _ in @@ -266,18 +268,11 @@ public struct HomeCore { return .none } - case .focusPomodoro(.presented(.restWaiting(.presented(.goToHomeByOver60Minute)))): - state.focusPomodoro = nil + case .pomodoro(.presented(.restWaiting(.goToHomeByOver60Minute))): state.dialog = focusEndDialog() return .none - case .focusPomodoro(.presented(.goToHome)), - .focusPomodoro(.presented(.restWaiting(.presented(.goToHome)))), - .focusPomodoro(.presented(.restWaiting(.presented(.restPomodoro(.presented(.goToHome)))))): - state.focusPomodoro = nil - return .none - - case .focusPomodoro: + case .pomodoro: return .none } } diff --git a/Projects/Feature/HomeFeature/Sources/Home/HomeView.swift b/Projects/Feature/HomeFeature/Sources/Home/HomeView.swift index 53425af..a506720 100644 --- a/Projects/Feature/HomeFeature/Sources/Home/HomeView.swift +++ b/Projects/Feature/HomeFeature/Sources/Home/HomeView.swift @@ -148,11 +148,11 @@ public struct HomeView: View { } .navigationDestination( item: $store.scope( - state: \.focusPomodoro, - action: \.focusPomodoro + state: \.pomodoro, + action: \.pomodoro ) ) { store in - FocusPomodoroView(store: store) + PomodoroView(store: store) } .navigationDestination( item: $store.scope( diff --git a/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeItem.swift b/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeItem.swift new file mode 100644 index 0000000..10a83b2 --- /dev/null +++ b/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeItem.swift @@ -0,0 +1,29 @@ +// +// TimeItem.swift +// HomeFeature +// +// Created by devMinseok on 12/30/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import Foundation + +public struct TimeItem: WheelPickerData { + let minute: Int + + init(minute: Int) { + self.minute = minute + } + + public var id: Int { + return minute + } + + var title: String { + return String(format: "%02d:00", minute) + } + + var data: Int { + return minute + } +} diff --git a/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeSelectCore.swift b/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeSelectCore.swift index 56a451d..05200f6 100644 --- a/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeSelectCore.swift +++ b/Projects/Feature/HomeFeature/Sources/TimeSelect/TimeSelectCore.swift @@ -28,6 +28,15 @@ public struct TimeSelectCore { public init(mode: Mode) { self.mode = mode } + + var isTimeChanged: Bool { + switch mode { + case .focus: + return selectedCategory?.focusTimeMinutes != selectedTime?.minute + case .rest: + return selectedCategory?.restTimeMinutes != selectedTime?.minute + } + } } public enum Action { @@ -93,12 +102,13 @@ public struct TimeSelectCore { return .none case .bottomCheckButtonTapped: - return .run { [ - mode = state.mode, - selectedTime = state.selectedTime, - selectedCategory = state.selectedCategory - ] send in - if let selectedCategoryID = selectedCategory?.id, + let mode = state.mode + let selectedCategory = state.selectedCategory + let selectedTime = state.selectedTime + let isTimeChanged = state.isTimeChanged + return .run { send in + if isTimeChanged, + let selectedCategoryID = selectedCategory?.id, let selectedTime = selectedTime?.minute { let selectedTimeDuration = DateComponents(minute: selectedTime).to8601DurationString() var request: EditCategoryRequest @@ -110,7 +120,8 @@ public struct TimeSelectCore { request = EditCategoryRequest(focusTime: nil, restTime: selectedTimeDuration) } - try await self.pomodoroService.changeCategoryTime( + // TODO: - 오프라인 대응 필요 + try? await self.pomodoroService.changeCategoryTime( apiClient: self.apiClient, categoryID: selectedCategoryID, request: request @@ -140,23 +151,3 @@ public struct TimeSelectCore { return result.reversed() } } - -public struct TimeItem: WheelPickerData { - let minute: Int - - init(minute: Int) { - self.minute = minute - } - - public var id: Int { - return minute - } - - var title: String { - return String(format: "%02d:00", minute) - } - - var data: Int { - return minute - } -} diff --git a/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroCore.swift b/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroCore.swift index c7ea6be..de6546b 100644 --- a/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroCore.swift +++ b/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroCore.swift @@ -39,7 +39,6 @@ public struct FocusPomodoroCore { var selectedCat: SomeCat? var catRiv: RiveViewModel = Rive.catFocusRiv(stateMachineName: "State Machine_Focus") var pushTriggered: Bool = false - @Presents var restWaiting: RestWaitingCore.State? public init() {} @@ -72,7 +71,7 @@ public struct FocusPomodoroCore { case saveHistory(focusTimeBySeconds: Int, restTimeBySeconds: Int) case timer(TimerCore.Action) - case restWaiting(PresentationAction) + case _moveToRestWaiting(RestWaitingCore.State) } @Dependency(PomodoroService.self) var pomodoroService @@ -91,10 +90,8 @@ public struct FocusPomodoroCore { Scope(state: \.timer, action: \.timer) { TimerCore() } + Reduce(self.core) - .ifLet(\.$restWaiting, action: \.restWaiting) { - RestWaitingCore() - } } private func core(state: inout State, action: Action) -> EffectOf { @@ -155,15 +152,18 @@ public struct FocusPomodoroCore { await send(.setupLiveActivity) await send(.setupPushNotification) await send(.timer(.start)) + await send(.timer(.tick)) } case .takeRestButtonTapped: - state.restWaiting = RestWaitingCore.State( + let restWaitingState = RestWaitingCore.State( source: .focusPomodoro, focusedTimeBySeconds: state.focusedTime, overTimeBySeconds: state.overTimeBySeconds ) - return .none + return .run { send in + await send(._moveToRestWaiting(restWaitingState)) + } case .endFocusButtonTapped: return .run { [focusedTime = state.focusedTime] send in @@ -253,11 +253,10 @@ public struct FocusPomodoroCore { case .timer(.tick): guard let goalDatetime = state.goalDatetime else { return .none } - let timeDifference = timeDifferenceInSeconds(from: Date.now, to: goalDatetime) - if state.focusTimeBySeconds == 0 { - if state.overTimeBySeconds == 3600 { // 60분 초과시 휴식 대기화면으로 이동 + if state.focusTimeBySeconds <= 0 { + if state.overTimeBySeconds >= 3600 { // 60분 초과시 휴식 대기화면으로 이동 return .run { [state] send in await send(.timer(.stop)) // task가 cancel을 해주지만 일단 action 중복을 방지하기 위해 명시적으로 stop let restWaitingState = RestWaitingCore.State( @@ -265,7 +264,7 @@ public struct FocusPomodoroCore { focusedTimeBySeconds: state.focusedTime, overTimeBySeconds: state.overTimeBySeconds ) - await send(.set(\.restWaiting, restWaitingState)) + await send(._moveToRestWaiting(restWaitingState)) } } else { state.overTimeBySeconds = -(timeDifference) @@ -278,17 +277,8 @@ public struct FocusPomodoroCore { case .timer: return .none - case .restWaiting(.presented(.restPomodoro(.presented(.goToFocus)))): - state.restWaiting = nil - return .none - - case .restWaiting: + case ._moveToRestWaiting: return .none } } - - func timeDifferenceInSeconds(from startDate: Date, to endDate: Date) -> Int { - let difference = Int(endDate.timeIntervalSince(startDate)) - return difference - } } diff --git a/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroView.swift b/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroView.swift index ab88e25..45f1382 100644 --- a/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroView.swift +++ b/Projects/Feature/PomodoroFeature/Sources/FocusPomodoro/FocusPomodoroView.swift @@ -42,11 +42,11 @@ public struct FocusPomodoroView: View { VStack(spacing: Alias.Spacing.xLarge) { store.catRiv.view() .setTooltipTarget(tooltip: PomodoroDialogueTooltip.self) + .frame(width: 240, height: 240) .onTapGesture { store.send(.catTapped) } - .frame(width: 240, height: 240) - + VStack(spacing: .zero) { HStack(spacing: Alias.Spacing.xSmall) { DesignSystemAsset.Image._20Focus.swiftUIImage @@ -89,14 +89,6 @@ public struct FocusPomodoroView: View { } .background(Alias.Color.Background.primary) .tooltipDestination(tooltip: .constant(store.dialogueTooltip)) - .navigationDestination( - item: $store.scope( - state: \.restWaiting, - action: \.restWaiting - ) - ) { store in - RestWaitingView(store: store) - } .task { await store.send(.task).finish() } diff --git a/Projects/Feature/PomodoroFeature/Sources/Helper/Helper.swift b/Projects/Feature/PomodoroFeature/Sources/Helper/Helper.swift index 8e4f783..097ceef 100644 --- a/Projects/Feature/PomodoroFeature/Sources/Helper/Helper.swift +++ b/Projects/Feature/PomodoroFeature/Sources/Helper/Helper.swift @@ -13,3 +13,8 @@ func formatTime(from seconds: Int) -> String { let remainingSeconds = seconds % 60 return String(format: "%02d:%02d", minutes, remainingSeconds) } + +func timeDifferenceInSeconds(from startDate: Date, to endDate: Date) -> Int { + let difference = Int(endDate.timeIntervalSince(startDate)) + return difference +} diff --git a/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroCore.swift b/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroCore.swift new file mode 100644 index 0000000..8954904 --- /dev/null +++ b/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroCore.swift @@ -0,0 +1,78 @@ +// +// PomodoroCore.swift +// PomodoroFeature +// +// Created by devMinseok on 12/30/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import ComposableArchitecture + +@Reducer +public struct PomodoroCore { + @ObservableState + public struct State: Equatable { + var focusPomodoro: FocusPomodoroCore.State = .init() + var restWaiting: RestWaitingCore.State? + var restPomodoro: RestPomodoroCore.State? + + public init() {} + } + + public enum Action { + case focusPomodoro(FocusPomodoroCore.Action) + case restWaiting(RestWaitingCore.Action) + case restPomodoro(RestPomodoroCore.Action) + } + + public init() {} + + @Dependency(\.dismiss) var dismiss + + public var body: some ReducerOf { + Scope(state: \.focusPomodoro, action: \.focusPomodoro) { + FocusPomodoroCore() + } + Reduce(self.core) + .ifLet(\.restWaiting, action: \.restWaiting) { + RestWaitingCore() + } + .ifLet(\.restPomodoro, action: \.restPomodoro) { + RestPomodoroCore() + } + } + + private func core(state: inout State, action: Action) -> EffectOf { + switch action { + case let .focusPomodoro(._moveToRestWaiting(restWaitingState)): + state.restWaiting = restWaitingState + return .none + + case .focusPomodoro(.goToHome), + .restWaiting(.goToHome), + .restPomodoro(.goToHome), + .restWaiting(.goToHomeByOver60Minute): + return .run { _ in + await self.dismiss() + } + + case .focusPomodoro: + return .none + + case let .restWaiting(._moveToRestPomodoro(restPomodoroState)): + state.restPomodoro = restPomodoroState + return .none + + case .restWaiting: + return .none + + case .restPomodoro(.goToFocus): + state.restPomodoro = nil + state.restWaiting = nil + return .none + + case .restPomodoro: + return .none + } + } +} diff --git a/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroView.swift b/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroView.swift new file mode 100644 index 0000000..a8de059 --- /dev/null +++ b/Projects/Feature/PomodoroFeature/Sources/Pomodoro/PomodoroView.swift @@ -0,0 +1,41 @@ +// +// PomodoroView.swift +// PomodoroFeature +// +// Created by devMinseok on 12/30/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +import DesignSystem + +import ComposableArchitecture + +public struct PomodoroView: View { + @Bindable var store: StoreOf + + public init(store: StoreOf) { + self.store = store + } + + public var body: some View { + ZStack { + if let store = store.scope(state: \.restPomodoro, action: \.restPomodoro) { + RestPomodoroView(store: store) + .transition(.opacity.animation(.easeInOut)) + .zIndex(2) + } else if let store = store.scope(state: \.restWaiting, action: \.restWaiting) { + RestWaitingView(store: store) + .transition(.opacity.animation(.easeInOut)) + .zIndex(1) + } else { + FocusPomodoroView( + store: store.scope(state: \.focusPomodoro, action: \.focusPomodoro) + ) + .transition(.opacity.animation(.easeInOut)) + .zIndex(0) + } + } + } +} diff --git a/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroCore.swift b/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroCore.swift index bcd7f31..5916014 100644 --- a/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroCore.swift +++ b/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroCore.swift @@ -122,6 +122,7 @@ public struct RestPomodoroCore { await send(.setupLiveActivity) await send(.setupPushNotification) await send(.timer(.start)) + await send(.timer(.tick)) } case .focusAgainButtonTapped: @@ -246,13 +247,11 @@ public struct RestPomodoroCore { return .none case .timer(.tick): - // date 처이 계산 guard let goalDatetime = state.goalDatetime else { return .none } - let timeDifference = timeDifferenceInSeconds(from: Date.now, to: goalDatetime) - if state.restTimeBySeconds == 0 { - if state.overTimeBySeconds == 1800 { // 30분 초과시 휴식 대기화면으로 이동 + if state.restTimeBySeconds <= 0 { + if state.overTimeBySeconds >= 1800 { // 30분 초과시 휴식 대기화면으로 이동 return .run { [state] send in await send(.timer(.stop)) // task가 cancel을 해주지만 일단 action 중복을 방지하기 위해 명시적으로 stop await send(.saveHistory(focusTimeBySeconds: state.focusedTimeBySeconds, restTimeBySeconds: state.restTimeBySeconds)) @@ -290,9 +289,4 @@ public struct RestPomodoroCore { databaseClient: self.databaseClient ) } - - func timeDifferenceInSeconds(from startDate: Date, to endDate: Date) -> Int { - let difference = Int(endDate.timeIntervalSince(startDate)) - return difference - } } diff --git a/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroView.swift b/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroView.swift index eac3af7..cb9b381 100644 --- a/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroView.swift +++ b/Projects/Feature/PomodoroFeature/Sources/RestPomodoro/RestPomodoroView.swift @@ -40,10 +40,10 @@ public struct RestPomodoroView: View { VStack(spacing: Alias.Spacing.xLarge) { store.catRiv.view() .setTooltipTarget(tooltip: PomodoroDialogueTooltip.self) + .frame(width: 240, height: 240) .onTapGesture { store.send(.catTapped) } - .frame(width: 240, height: 240) VStack(spacing: .zero) { HStack(spacing: Alias.Spacing.xSmall) { diff --git a/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingCore.swift b/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingCore.swift index f5a8e54..0374a0d 100644 --- a/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingCore.swift +++ b/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingCore.swift @@ -20,17 +20,16 @@ import ComposableArchitecture public struct RestWaitingCore { @ObservableState public struct State: Equatable { + let restWaitingEndDate = Date().addingTimeInterval(3600) let source: Source let focusedTimeBySeconds: Int let overTimeBySeconds: Int var selectedCategory: PomodoroCategory? var changeFocusTimeByMinute: Int = 0 - var timer: TimerCore.State = .init(interval: .seconds(3600), mode: .continuous) + var timer: TimerCore.State = .init(interval: .seconds(1), mode: .continuous) var toast: DefaultToast? - @Presents var restPomodoro: RestPomodoroCore.State? - public init( source: Source, focusedTimeBySeconds: Int, @@ -64,7 +63,7 @@ public struct RestWaitingCore { case saveHistory(focusTimeBySeconds: Int, restTimeBySeconds: Int) case timer(TimerCore.Action) - case restPomodoro(PresentationAction) + case _moveToRestPomodoro(RestPomodoroCore.State) } public enum Source { @@ -85,9 +84,6 @@ public struct RestWaitingCore { TimerCore() } Reduce(self.core) - .ifLet(\.$restPomodoro, action: \.restPomodoro) { - RestPomodoroCore() - } } private func core(state: inout State, action: Action) -> EffectOf { @@ -130,9 +126,10 @@ public struct RestWaitingCore { return .none case .takeRestButtonTapped: + let restPomodoroState = RestPomodoroCore.State(focusedTimeBySeconds: state.focusedTimeBySeconds) return .run { [state] send in try await applyChangeFocusTime(state: state) - await send(.set(\.restPomodoro, RestPomodoroCore.State(focusedTimeBySeconds: state.focusedTimeBySeconds))) + await send(._moveToRestPomodoro(restPomodoroState)) } case .endFocusButtonTapped: @@ -152,15 +149,17 @@ public struct RestWaitingCore { return .none case .timer(.tick): - return .run { [state] send in - await send(.saveHistory(focusTimeBySeconds: state.focusedTimeBySeconds, restTimeBySeconds: 0)) + guard state.restWaitingEndDate <= Date() else { return .none } + let focusedTimeBySeconds = state.focusedTimeBySeconds + return .run { send in + await send(.saveHistory(focusTimeBySeconds: focusedTimeBySeconds, restTimeBySeconds: 0)) await send(.goToHomeByOver60Minute) } case .timer: return .none - case .restPomodoro: + case ._moveToRestPomodoro: return .none } } diff --git a/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingView.swift b/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingView.swift index 6a1e770..7f5bd1e 100644 --- a/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingView.swift +++ b/Projects/Feature/PomodoroFeature/Sources/RestWaiting/RestWaitingView.swift @@ -108,14 +108,6 @@ public struct RestWaitingView: View { } .background(Alias.Color.Background.primary) .toastDestination(toast: $store.toast) - .navigationDestination( - item: $store.scope( - state: \.restPomodoro, - action: \.restPomodoro - ) - ) { store in - RestPomodoroView(store: store) - } .task { await store.send(.task).finish() }