diff --git a/app/renderer/src/components/Layout.tsx b/app/renderer/src/components/Layout.tsx index 32b78fc3..960a6381 100644 --- a/app/renderer/src/components/Layout.tsx +++ b/app/renderer/src/components/Layout.tsx @@ -6,28 +6,20 @@ import React, { useRef, } from "react"; import { RouteComponentProps, withRouter } from "react-router-dom"; -import { useSelector } from "react-redux"; -import { - AppStateTypes, - SHORT_BREAK, - LONG_BREAK, - SPECIAL_BREAK, - SettingTypes, -} from "store"; import { StyledLayout } from "styles"; import Titlebar from "./Titlebar"; import Navigation from "./Navigation"; import { ThemeContext } from "contexts"; +import { TimerStatus } from "store/timer/types"; +import { useAppSelector } from "hooks/storeHooks"; type Props = {} & RouteComponentProps; const Layout: React.FC = ({ history, location, children }) => { - const timer = useSelector((state: AppStateTypes) => state.timer); + const timer = useAppSelector((state) => state.timer); - const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings - ); + const settings = useAppSelector((state) => state.settings); const { toggleThemeAction } = useContext(ThemeContext); @@ -52,9 +44,9 @@ const Layout: React.FC = ({ history, location, children }) => { useEffect(() => { if (settings.enableFullscreenBreak) { if ( - timer.timerType === SHORT_BREAK || - timer.timerType === LONG_BREAK || - timer.timerType === SPECIAL_BREAK + timer.timerType === TimerStatus.SHORT_BREAK || + timer.timerType === TimerStatus.LONG_BREAK || + timer.timerType === TimerStatus.SPECIAL_BREAK ) { if (location.pathname !== "/") { setNoTransition(true); diff --git a/app/renderer/src/components/Navigation.tsx b/app/renderer/src/components/Navigation.tsx index 16da18b4..cca9bdb7 100644 --- a/app/renderer/src/components/Navigation.tsx +++ b/app/renderer/src/components/Navigation.tsx @@ -1,6 +1,5 @@ import React from "react"; -import { useSelector } from "react-redux"; -import { AppStateTypes, TimerTypes } from "store"; +import { useAppSelector } from "hooks/storeHooks"; import { StyledNav, StyledNavList, @@ -11,17 +10,16 @@ import { import { NavNotify } from "components"; import { routes } from "config"; import SVG from "./SVG"; +import { TimerStatus } from "store/timer/types"; type Props = { - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; }; const Navigation: React.FC = ({ timerType }) => { - const settings = useSelector( - (state: AppStateTypes) => state.settings - ); + const settings = useAppSelector((state) => state.settings); - const state = useSelector((state: AppStateTypes) => state); + const state = useAppSelector((state) => state); return ( diff --git a/app/renderer/src/components/Titlebar.tsx b/app/renderer/src/components/Titlebar.tsx index ef4024a3..23e32173 100644 --- a/app/renderer/src/components/Titlebar.tsx +++ b/app/renderer/src/components/Titlebar.tsx @@ -1,5 +1,5 @@ import React, { useContext, useCallback } from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; import { StyledTitlebar, StyledWindowActions, @@ -23,7 +23,7 @@ import appIconLongBreakDark from "assets/logos/tray-dark-lb.png"; type Props = { darkMode: boolean; - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; }; const Titlebar: React.FC = ({ darkMode, timerType }) => { @@ -32,11 +32,11 @@ const Titlebar: React.FC = ({ darkMode, timerType }) => { const getAppIcon = useCallback(() => { switch (timerType) { - case "STAY_FOCUS": + case TimerStatus.STAY_FOCUS: return darkMode ? appIconDark : appIcon; - case "SHORT_BREAK": + case TimerStatus.SHORT_BREAK: return darkMode ? appIconShortBreakDark : appIconShortBreak; - case "LONG_BREAK": + case TimerStatus.LONG_BREAK: return darkMode ? appIconLongBreakDark : appIconLongBreak; default: return darkMode ? appIconLongBreakDark : appIconLongBreak; diff --git a/app/renderer/src/components/TraySVG.tsx b/app/renderer/src/components/TraySVG.tsx index 388377bd..2efdeca7 100644 --- a/app/renderer/src/components/TraySVG.tsx +++ b/app/renderer/src/components/TraySVG.tsx @@ -1,17 +1,17 @@ import React from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; type Props = { dashOffset?: number; - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; }; export const TraySVG: React.FC = ({ timerType, dashOffset }) => { const getProgressColor = (opacity = 1) => { switch (timerType) { - case "STAY_FOCUS": + case TimerStatus.STAY_FOCUS: return `rgba(0, 152, 247, ${opacity})`; - case "SHORT_BREAK": + case TimerStatus.SHORT_BREAK: return `rgba(7, 181, 131, ${opacity})`; default: return `rgba(212, 141, 10, ${opacity})`; @@ -71,7 +71,8 @@ export const TraySVG: React.FC = ({ timerType, dashOffset }) => { ); }; +//TODO: Remove this TraySVG.defaultProps = { dashOffset: 0, - timerType: "STAY_FOCUS", + timerType: TimerStatus.STAY_FOCUS, }; diff --git a/app/renderer/src/contexts/CounterContext.tsx b/app/renderer/src/contexts/CounterContext.tsx index c8b0652b..80d84c9e 100644 --- a/app/renderer/src/contexts/CounterContext.tsx +++ b/app/renderer/src/contexts/CounterContext.tsx @@ -1,18 +1,6 @@ import React, { useState, useEffect, useCallback } from "react"; -import { useSelector, useDispatch } from "react-redux"; import useStayAwake from "use-stay-awake"; -import { - AppStateTypes, - STAY_FOCUS, - SHORT_BREAK, - setRound, - setTimerType, - LONG_BREAK, - TimerTypes, - SPECIAL_BREAK, - SettingTypes, - setPlay, -} from "store"; +import { setRound, setTimerType, SettingTypes, setPlay } from "store"; import { useNotification } from "hooks"; import { padNum, isEqualToOne } from "utils"; @@ -24,11 +12,13 @@ import sessionCompletedWav from "assets/audios/session-completed.wav"; import sixtySecondsLeftWav from "assets/audios/sixty-seconds-left.wav"; import specialBreakStartedWav from "assets/audios/special-break-started.wav"; import thirtySecondsLeftWav from "assets/audios/thirty-seconds-left.wav"; +import { useAppDispatch, useAppSelector } from "hooks/storeHooks"; +import { TimerStatus } from "store/timer/types"; type CounterProps = { count: number; duration: number; - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; resetTimerAction?: () => void; shouldFullscreen?: boolean; }; @@ -39,15 +29,15 @@ const CounterContext = React.createContext({ }); const CounterProvider: React.FC = ({ children }) => { - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); - const { timer, config } = useSelector((state: AppStateTypes) => ({ + const { timer, config } = useAppSelector((state) => ({ timer: state.timer, config: state.config, })); - const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings + const settings: SettingTypes = useAppSelector( + (state) => state.settings ); const { preventSleeping, allowSleeping } = useStayAwake(); @@ -73,16 +63,16 @@ const CounterProvider: React.FC = ({ children }) => { const resetTimerAction = useCallback(() => { switch (timer.timerType) { - case STAY_FOCUS: + case TimerStatus.STAY_FOCUS: setTimerDuration(config.stayFocus); break; - case SHORT_BREAK: + case TimerStatus.SHORT_BREAK: setTimerDuration(config.shortBreak); break; - case LONG_BREAK: + case TimerStatus.LONG_BREAK: setTimerDuration(config.longBreak); break; - case SPECIAL_BREAK: + case TimerStatus.SPECIAL_BREAK: setDuration(duration); setCount(duration); break; @@ -98,7 +88,7 @@ const CounterProvider: React.FC = ({ children }) => { ]); useEffect(() => { - if (timer.playing && timer.timerType !== STAY_FOCUS) { + if (timer.playing && timer.timerType !== TimerStatus.STAY_FOCUS) { preventSleeping(); } else { allowSleeping(); @@ -117,15 +107,15 @@ const CounterProvider: React.FC = ({ children }) => { const currentTime = padNum(date.getHours()) + ":" + padNum(date.getMinutes()); - if (timer.timerType !== SPECIAL_BREAK) { + if (timer.timerType !== TimerStatus.SPECIAL_BREAK) { switch (currentTime) { case firstBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); + dispatch(setTimerType(TimerStatus.SPECIAL_BREAK)); setTimerDuration(firstBreak.duration); notification( "Special break started.", { - body: `Enjoy your ${firstBreak.duration} ${ + body: `Enjoy your ${firstBreak?.duration} ${ isEqualToOne(firstBreak.duration) ? "minute" : "minutes" @@ -135,7 +125,7 @@ const CounterProvider: React.FC = ({ children }) => { ); break; case secondBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); + dispatch(setTimerType(TimerStatus.SPECIAL_BREAK)); setTimerDuration(secondBreak.duration); notification( "Special break started.", @@ -150,7 +140,7 @@ const CounterProvider: React.FC = ({ children }) => { ); break; case thirdBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); + dispatch(setTimerType(TimerStatus.SPECIAL_BREAK)); setTimerDuration(thirdBreak.duration); notification( "Special break started.", @@ -165,7 +155,7 @@ const CounterProvider: React.FC = ({ children }) => { ); break; case fourthBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); + dispatch(setTimerType(TimerStatus.SPECIAL_BREAK)); setTimerDuration(fourthBreak.duration); notification( "Special break started.", @@ -200,13 +190,13 @@ const CounterProvider: React.FC = ({ children }) => { useEffect(() => { switch (timer.timerType) { - case STAY_FOCUS: + case TimerStatus.STAY_FOCUS: setTimerDuration(config.stayFocus); break; - case SHORT_BREAK: + case TimerStatus.SHORT_BREAK: setTimerDuration(config.shortBreak); break; - case LONG_BREAK: + case TimerStatus.LONG_BREAK: setTimerDuration(config.longBreak); break; } @@ -236,26 +226,29 @@ const CounterProvider: React.FC = ({ children }) => { useEffect(() => { if (settings.notificationType === "extra") { if (count === 61) { - if (timer.timerType === SHORT_BREAK) { + if (timer.timerType === TimerStatus.SHORT_BREAK) { notification( "60 seconds left.", { body: "Prepare yourself to stay focused again." }, settings.enableVoiceAssistance && sixtySecondsLeftWav ); - } else if (timer.timerType === LONG_BREAK) { + } else if (timer.timerType === TimerStatus.LONG_BREAK) { notification( "60 seconds left.", { body: "Prepare yourself to stay focused again." }, settings.enableVoiceAssistance && sixtySecondsLeftWav ); - } else if (timer.timerType === SPECIAL_BREAK) { + } else if (timer.timerType === TimerStatus.SPECIAL_BREAK) { notification( "60 seconds left.", { body: "Prepare yourself to stay focused again." }, settings.enableVoiceAssistance && sixtySecondsLeftWav ); } - } else if (count === 31 && timer.timerType === STAY_FOCUS) { + } else if ( + count === 31 && + timer.timerType === TimerStatus.STAY_FOCUS + ) { notification( "30 seconds left.", { body: "Pause all media playing if there's one." }, @@ -266,7 +259,7 @@ const CounterProvider: React.FC = ({ children }) => { if (count === 0) { switch (timer.timerType) { - case STAY_FOCUS: + case TimerStatus.STAY_FOCUS: if (timer.round < config.sessionRounds) { setTimeout(() => { notification( @@ -281,7 +274,7 @@ const CounterProvider: React.FC = ({ children }) => { settings.enableVoiceAssistance && focusFinishedWav ); - dispatch(setTimerType("SHORT_BREAK")); + dispatch(setTimerType(TimerStatus.SHORT_BREAK)); }, 1000); } else { setTimeout(() => { @@ -297,12 +290,12 @@ const CounterProvider: React.FC = ({ children }) => { settings.enableVoiceAssistance && sessionCompletedWav ); - dispatch(setTimerType("LONG_BREAK")); + dispatch(setTimerType(TimerStatus.LONG_BREAK)); }, 1000); } break; - case SHORT_BREAK: + case TimerStatus.SHORT_BREAK: setTimeout(() => { notification( "Break time finished.", @@ -316,7 +309,7 @@ const CounterProvider: React.FC = ({ children }) => { settings.enableVoiceAssistance && breakFinishedWav ); - dispatch(setTimerType("STAY_FOCUS")); + dispatch(setTimerType(TimerStatus.STAY_FOCUS)); dispatch(setRound(timer.round + 1)); if (!settings.autoStartWorkTime) { @@ -325,7 +318,7 @@ const CounterProvider: React.FC = ({ children }) => { }, 1000); break; - case LONG_BREAK: + case TimerStatus.LONG_BREAK: setTimeout(() => { notification( "Break time finished.", @@ -339,7 +332,7 @@ const CounterProvider: React.FC = ({ children }) => { settings.enableVoiceAssistance && breakFinishedWav ); - dispatch(setTimerType("STAY_FOCUS")); + dispatch(setTimerType(TimerStatus.STAY_FOCUS)); dispatch(setRound(1)); if (!settings.autoStartWorkTime) { @@ -348,7 +341,7 @@ const CounterProvider: React.FC = ({ children }) => { }, 1000); break; - case SPECIAL_BREAK: + case TimerStatus.SPECIAL_BREAK: setTimeout(() => { notification( "Break time finished.", @@ -362,7 +355,7 @@ const CounterProvider: React.FC = ({ children }) => { settings.enableVoiceAssistance && breakFinishedWav ); - dispatch(setTimerType("STAY_FOCUS")); + dispatch(setTimerType(TimerStatus.STAY_FOCUS)); if (!settings.autoStartWorkTime) { dispatch(setPlay(false)); @@ -389,7 +382,7 @@ const CounterProvider: React.FC = ({ children }) => { useEffect(() => { if (settings.enableFullscreenBreak) { - if (timer.timerType !== STAY_FOCUS) { + if (timer.timerType !== TimerStatus.STAY_FOCUS) { setShouldFullscreen(true); } else { setShouldFullscreen(false); diff --git a/app/renderer/src/routes/Timer/Control/Control.tsx b/app/renderer/src/routes/Timer/Control/Control.tsx index f95a6cfd..6f1bb82a 100644 --- a/app/renderer/src/routes/Timer/Control/Control.tsx +++ b/app/renderer/src/routes/Timer/Control/Control.tsx @@ -1,19 +1,14 @@ import WarningBell from "assets/audios/warning-bell.wav"; import { SVG } from "components"; import React, { useCallback, useEffect, useState } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useAppDispatch, useAppSelector } from "hooks/storeHooks"; +import { TimerStatus } from "store/timer/types"; import { - AppStateTypes, - LONG_BREAK, setEnableCompactMode, setPlay, setRound, setTimerType, - SettingTypes, - SHORT_BREAK, skipTimer, - SPECIAL_BREAK, - STAY_FOCUS, toggleNotificationSound, } from "store"; import { @@ -35,16 +30,14 @@ type Props = { }; const Control: React.FC = ({ resetTimerAction }) => { - const { timer, config } = useSelector((state: AppStateTypes) => ({ + const { timer, config } = useAppSelector((state) => ({ timer: state.timer, config: state.config, })); - const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings - ); + const settings = useAppSelector((state) => state.settings); - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const [warn, setWarn] = useState(false); @@ -98,29 +91,29 @@ const Control: React.FC = ({ resetTimerAction }) => { } switch (timer.timerType) { - case STAY_FOCUS: + case TimerStatus.STAY_FOCUS: if (timer.round < config.sessionRounds) { - dispatch(skipTimer("SHORT_BREAK")); + dispatch(skipTimer(TimerStatus.SHORT_BREAK)); } else { - dispatch(skipTimer("LONG_BREAK")); + dispatch(skipTimer(TimerStatus.LONG_BREAK)); } if (!timer.playing) dispatch(setPlay(!timer.playing)); break; - case SHORT_BREAK: - dispatch(skipTimer("STAY_FOCUS")); + case TimerStatus.SHORT_BREAK: + dispatch(skipTimer(TimerStatus.STAY_FOCUS)); dispatch(setRound(timer.round + 1)); if (!timer.playing) dispatch(setPlay(!timer.playing)); break; - case LONG_BREAK: - dispatch(skipTimer("STAY_FOCUS")); + case TimerStatus.LONG_BREAK: + dispatch(skipTimer(TimerStatus.STAY_FOCUS)); dispatch(setRound(1)); if (!timer.playing) dispatch(setPlay(!timer.playing)); break; - case SPECIAL_BREAK: - dispatch(skipTimer("STAY_FOCUS")); + case TimerStatus.SPECIAL_BREAK: + dispatch(skipTimer(TimerStatus.STAY_FOCUS)); if (!timer.playing) dispatch(setPlay(!timer.playing)); break; } @@ -135,7 +128,7 @@ const Control: React.FC = ({ resetTimerAction }) => { ]); const onResetSessionCallback = useCallback(() => { - dispatch(setTimerType("STAY_FOCUS")); + dispatch(setTimerType(TimerStatus.STAY_FOCUS)); dispatch(setRound(1)); }, [dispatch]); diff --git a/app/renderer/src/routes/Timer/Control/Sessions.tsx b/app/renderer/src/routes/Timer/Control/Sessions.tsx index e79e5290..eedb1d5b 100644 --- a/app/renderer/src/routes/Timer/Control/Sessions.tsx +++ b/app/renderer/src/routes/Timer/Control/Sessions.tsx @@ -1,10 +1,10 @@ import React from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; import { StyledSessions, StyledSessionReset } from "styles"; import { SVG } from "components"; type Props = { - timerType: TimerTypes["timerType"]; + timerType: TimerStatus; round: number; sessionRounds: number; onClick?: diff --git a/app/renderer/src/routes/Timer/Counter/CounterLabel.tsx b/app/renderer/src/routes/Timer/Counter/CounterLabel.tsx index a66e6ad2..0064c63d 100644 --- a/app/renderer/src/routes/Timer/Counter/CounterLabel.tsx +++ b/app/renderer/src/routes/Timer/Counter/CounterLabel.tsx @@ -1,17 +1,17 @@ import React from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; import { StyledCounterLabel } from "styles"; type Props = { - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; }; const CounterLabel: React.FC = ({ timerType }) => { return ( - {(timerType === "SHORT_BREAK" && "Short Break") || - (timerType === "LONG_BREAK" && "Long Break") || - (timerType === "SPECIAL_BREAK" && "Special Break") || + {(timerType === TimerStatus.SHORT_BREAK && "Short Break") || + (timerType === TimerStatus.LONG_BREAK && "Long Break") || + (timerType === TimerStatus.SHORT_BREAK && "Special Break") || "Stay Focused"} ); diff --git a/app/renderer/src/routes/Timer/Counter/CounterTimer.tsx b/app/renderer/src/routes/Timer/Counter/CounterTimer.tsx index 40a441c9..9cb7bf0e 100644 --- a/app/renderer/src/routes/Timer/Counter/CounterTimer.tsx +++ b/app/renderer/src/routes/Timer/Counter/CounterTimer.tsx @@ -1,9 +1,9 @@ import React from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; import { StyledCounterTimer } from "styles"; type Props = { - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; hours: string; minutes: string; seconds: string; diff --git a/app/renderer/src/routes/Timer/Counter/CounterType.tsx b/app/renderer/src/routes/Timer/Counter/CounterType.tsx index de31e0f9..de1814eb 100644 --- a/app/renderer/src/routes/Timer/Counter/CounterType.tsx +++ b/app/renderer/src/routes/Timer/Counter/CounterType.tsx @@ -1,20 +1,20 @@ import React from "react"; -import { TimerTypes } from "store"; +import { TimerStatus } from "store/timer/types"; import { StyledCounterType } from "styles"; import { SVG } from "components"; type Props = { - timerType?: TimerTypes["timerType"]; + timerType?: TimerStatus; }; const CounterType: React.FC = ({ timerType }) => { return ( - {(timerType === "SHORT_BREAK" && ) || - (timerType === "LONG_BREAK" && ) || - (timerType === "SPECIAL_BREAK" && ) || ( - - )} + {(timerType === TimerStatus.SHORT_BREAK && ) || + (timerType === TimerStatus.LONG_BREAK && ) || + (timerType === TimerStatus.SPECIAL_BREAK && ( + + )) || } ); }; diff --git a/app/renderer/src/store/store.ts b/app/renderer/src/store/store.ts index 021fc68c..5835055b 100644 --- a/app/renderer/src/store/store.ts +++ b/app/renderer/src/store/store.ts @@ -4,7 +4,7 @@ import debounce from "lodash.debounce"; import { saveToStorage, getFromStorage } from "utils"; import configReducer from "./config"; import settingReducer from "./settings"; -import { timerReducer } from "./timer"; +import timerReducer from "./timer"; import { undoableTasksReducer } from "./tasks"; import updateReducer from "./update"; diff --git a/app/renderer/src/store/timer/actions.ts b/app/renderer/src/store/timer/actions.ts deleted file mode 100644 index d4364368..00000000 --- a/app/renderer/src/store/timer/actions.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { - TimerActionTypes, - SET_PLAY, - TimerTypes, - SET_TIMER_TYPE, - SET_ROUND, - SKIP_TIMER, -} from "./types"; - -export const setPlay = ( - playing: TimerTypes["playing"] -): TimerActionTypes => { - return { - type: SET_PLAY, - payload: playing, - }; -}; - -export const setTimerType = ( - timerType: TimerTypes["timerType"] -): TimerActionTypes => { - return { - type: SET_TIMER_TYPE, - payload: timerType, - }; -}; - -export const setRound = ( - round: TimerTypes["round"] -): TimerActionTypes => { - return { - type: SET_ROUND, - payload: round, - }; -}; - -export const skipTimer = ( - timerType: TimerTypes["timerType"] -): TimerActionTypes => { - return { - type: SKIP_TIMER, - payload: timerType, - }; -}; diff --git a/app/renderer/src/store/timer/defaultTimer.ts b/app/renderer/src/store/timer/defaultTimer.ts new file mode 100644 index 00000000..1d740dd3 --- /dev/null +++ b/app/renderer/src/store/timer/defaultTimer.ts @@ -0,0 +1,7 @@ +import { TimerStatus, TimerTypes } from "./types"; + +export const defaultTimer: Readonly = Object.freeze({ + round: 1, + playing: false, + timerType: TimerStatus.STAY_FOCUS, +}); diff --git a/app/renderer/src/store/timer/index.ts b/app/renderer/src/store/timer/index.ts index 6d30c416..d1ba560c 100644 --- a/app/renderer/src/store/timer/index.ts +++ b/app/renderer/src/store/timer/index.ts @@ -1,3 +1,39 @@ -export * from "./actions"; -export * from "./reducer"; -export * from "./types"; +import { createSlice } from "@reduxjs/toolkit"; +import { defaultTimer } from "./defaultTimer"; +import { TimerPayload } from "./types"; + +const timerSlice = createSlice({ + name: "timer", + initialState: defaultTimer, + reducers: { + setPlay(state, action: TimerPayload<"playing">) { + state.playing = action.payload; + }, + + setTimerType(state, action: TimerPayload<"timerType">) { + state.timerType = action.payload; + }, + + setRound(state, action: TimerPayload<"round">) { + state.round = action.payload; + }, + + skipTimer(state, action: TimerPayload<"timerType">) { + state.timerType = action.payload; + }, + + restartTimer() { + return defaultTimer; + }, + }, +}); + +export const { + setPlay, + setTimerType, + setRound, + skipTimer, + restartTimer, +} = timerSlice.actions; + +export default timerSlice.reducer; diff --git a/app/renderer/src/store/timer/reducer.ts b/app/renderer/src/store/timer/reducer.ts deleted file mode 100644 index dbb9d0fb..00000000 --- a/app/renderer/src/store/timer/reducer.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { - TimerTypes, - TimerActionTypes, - SET_PLAY, - SET_TIMER_TYPE, - SET_ROUND, - SKIP_TIMER, -} from "./types"; - -const initialState: TimerTypes = { - round: 1, - playing: false, - timerType: "STAY_FOCUS", -}; - -export const timerReducer = ( - state = initialState, - action: TimerActionTypes -) => { - switch (action.type) { - case SET_PLAY: - return { - ...state, - playing: action.payload, - }; - case SET_TIMER_TYPE: - return { - ...state, - timerType: action.payload, - }; - case SET_ROUND: - return { - ...state, - round: action.payload, - }; - case SKIP_TIMER: - return { - ...state, - timerType: action.payload, - }; - default: - return state; - } -}; diff --git a/app/renderer/src/store/timer/types.ts b/app/renderer/src/store/timer/types.ts index 067f7d4a..11a205bc 100644 --- a/app/renderer/src/store/timer/types.ts +++ b/app/renderer/src/store/timer/types.ts @@ -1,55 +1,18 @@ -const timer = "[timer]"; +import type { PayloadAction } from "@reduxjs/toolkit"; export type TimerTypes = { round: number; playing: boolean; - timerType: - | "STAY_FOCUS" - | "SHORT_BREAK" - | "LONG_BREAK" - | "SPECIAL_BREAK"; + timerType: TimerStatus; }; -export const SET_PLAY = `${timer} SET_PLAY`; -export const SKIP_TIMER = `${timer} SKIP_TIMER`; -export const RESTART_TIMER = `${timer} RESTART_TIMER`; - -export const SET_TIMER_TYPE = `${timer} SET_TIMER_TYPE`; -export const SET_ROUND = `${timer} SET_ROUND`; - -export const STAY_FOCUS = "STAY_FOCUS"; -export const SHORT_BREAK = "SHORT_BREAK"; -export const LONG_BREAK = "LONG_BREAK"; -export const SPECIAL_BREAK = "SPECIAL_BREAK"; - -interface SetPlay { - type: typeof SET_PLAY; - payload?: TimerTypes["playing"]; -} - -interface SkipTimer { - type: typeof SKIP_TIMER; - payload?: any; -} - -interface RestartTimer { - type: typeof RESTART_TIMER; - payload?: any; -} - -interface SetTimerType { - type: typeof SET_TIMER_TYPE; - payload?: TimerTypes["timerType"]; -} - -interface SetRound { - type: typeof SET_ROUND; - payload?: TimerTypes["round"]; +export const enum TimerStatus { + STAY_FOCUS = "STAY_FOCUS", + SHORT_BREAK = "SHORT_BREAK", + LONG_BREAK = "LONG_BREAK", + SPECIAL_BREAK = "SPECIAL_BREAK", } -export type TimerActionTypes = - | SetPlay - | SkipTimer - | RestartTimer - | SetTimerType - | SetRound; +export type TimerPayload = PayloadAction< + TimerTypes[T] +>; diff --git a/app/renderer/src/styles/components/navigation.ts b/app/renderer/src/styles/components/navigation.ts index 242b11dd..9f18e948 100644 --- a/app/renderer/src/styles/components/navigation.ts +++ b/app/renderer/src/styles/components/navigation.ts @@ -1,5 +1,5 @@ import styled from "styled-components/macro"; -import { SHORT_BREAK, LONG_BREAK, SPECIAL_BREAK } from "store"; +import { TimerStatus } from "store/timer/types"; import { NavLink } from "react-router-dom"; import { themes } from "../themes"; @@ -46,7 +46,7 @@ export const StyledNavListItem = styled.li` align-items: center; `; -type NavLinkProps = { type?: string }; +type NavLinkProps = { type?: TimerStatus }; export const StyledNavIconWrapper = styled.div` position: relative; @@ -79,13 +79,13 @@ export const StyledNavLink = styled(NavLink)` &.active { color: ${(p) => - (p.type === SHORT_BREAK && + (p.type === TimerStatus.SHORT_BREAK && p.to === "/" && "var(--color-green)") || - (p.type === LONG_BREAK && + (p.type === TimerStatus.LONG_BREAK && p.to === "/" && "var(--color-yellow)") || - (p.type === SPECIAL_BREAK && + (p.type === TimerStatus.SPECIAL_BREAK && p.to === "/" && "var(--color-yellow)") || "var(--color-primary)"}; diff --git a/app/renderer/src/styles/routes/timer/control.ts b/app/renderer/src/styles/routes/timer/control.ts index 2f3e169a..9265a393 100644 --- a/app/renderer/src/styles/routes/timer/control.ts +++ b/app/renderer/src/styles/routes/timer/control.ts @@ -1,10 +1,5 @@ import styled, { css } from "styled-components/macro"; -import { - SHORT_BREAK, - LONG_BREAK, - SPECIAL_BREAK, - TimerTypes, -} from "store"; +import { TimerStatus } from "store/timer/types"; import { themes } from "../../themes"; const ControlButton = css` @@ -34,7 +29,7 @@ const ControlButton = css` } `; -type ControlProps = { type?: TimerTypes["timerType"] }; +type ControlProps = { type?: TimerStatus }; export const StyledControlSpacer = styled.div` flex: 1 0; @@ -53,16 +48,19 @@ export const StyledControl = styled.div` column-gap: 1rem; color: ${(p) => - (p.type === SHORT_BREAK && "var(--color-green)") || - (p.type === LONG_BREAK && "var(--color-yellow)") || - (p.type === SPECIAL_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SHORT_BREAK && "var(--color-green)") || + (p.type === TimerStatus.LONG_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SPECIAL_BREAK && "var(--color-yellow)") || "var(--color-primary)"}; .ripple-hook { background-color: ${(p) => - (p.type === SHORT_BREAK && "var(--color-bg-ripple-green)") || - (p.type === LONG_BREAK && "var(--color-bg-ripple-yellow)") || - (p.type === SPECIAL_BREAK && "var(--color-bg-ripple-yellow)") || + (p.type === TimerStatus.SHORT_BREAK && + "var(--color-bg-ripple-green)") || + (p.type === TimerStatus.LONG_BREAK && + "var(--color-bg-ripple-yellow)") || + (p.type === TimerStatus.SPECIAL_BREAK && + "var(--color-bg-ripple-yellow)") || "var(--color-bg-ripple-primary)"}; } @@ -72,7 +70,7 @@ export const StyledControl = styled.div` } `; -type SessionProps = { timerType?: TimerTypes["timerType"] }; +type SessionProps = { timerType?: TimerStatus }; export const StyledSessionReset = styled.button` position: absolute; @@ -100,9 +98,12 @@ export const StyledSessionReset = styled.button` &:hover { color: ${(p) => - (p.timerType === SHORT_BREAK && "var(--color-green)") || - (p.timerType === LONG_BREAK && "var(--color-yellow)") || - (p.timerType === SPECIAL_BREAK && "var(--color-yellow)") || + (p.timerType === TimerStatus.SHORT_BREAK && + "var(--color-green)") || + (p.timerType === TimerStatus.LONG_BREAK && + "var(--color-yellow)") || + (p.timerType === TimerStatus.SPECIAL_BREAK && + "var(--color-yellow)") || "var(--color-primary)"}; } diff --git a/app/renderer/src/styles/routes/timer/counter.ts b/app/renderer/src/styles/routes/timer/counter.ts index a47a7411..106c45bb 100644 --- a/app/renderer/src/styles/routes/timer/counter.ts +++ b/app/renderer/src/styles/routes/timer/counter.ts @@ -1,18 +1,19 @@ import styled, { css } from "styled-components/macro"; -import { LONG_BREAK, SHORT_BREAK, SPECIAL_BREAK } from "store"; +import { TimerStatus } from "store/timer/types"; import { ProgressSVG } from "assets/icons"; export type ProgressProps = { offset: number; animate: "true" | "false"; + type?: TimerStatus; }; export const StyledCounterProgress = styled(ProgressSVG)` #progress { stroke: ${(p) => - (p.type === SHORT_BREAK && "var(--color-green)") || - (p.type === LONG_BREAK && "var(--color-yellow)") || - (p.type === SPECIAL_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SHORT_BREAK && "var(--color-green)") || + (p.type === TimerStatus.LONG_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SPECIAL_BREAK && "var(--color-yellow)") || "var(--color-primary)"}; stroke-width: 0.6rem; stroke-linecap: round; @@ -115,7 +116,7 @@ export const StyledCounterType = styled.div` `; type TimerProps = { - type?: string; + type?: TimerStatus; hours: string; } & CounterContainerProps; @@ -123,9 +124,9 @@ export const StyledCounterTimer = styled.h3` font-size: 4rem; font-weight: 400; color: ${(p) => - (p.type === SHORT_BREAK && "var(--color-green)") || - (p.type === LONG_BREAK && "var(--color-yellow)") || - (p.type === SPECIAL_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SHORT_BREAK && "var(--color-green)") || + (p.type === TimerStatus.LONG_BREAK && "var(--color-yellow)") || + (p.type === TimerStatus.SPECIAL_BREAK && "var(--color-yellow)") || "var(--color-primary)"}; line-height: 1.2;