From c107c273ff30388adf0b94a121c8c1aa3c76d20d Mon Sep 17 00:00:00 2001 From: Sekwah Date: Mon, 19 Dec 2022 01:24:54 +0000 Subject: [PATCH] chore: clean up the files for pre-commit that are required --- app/main/nodemon.json | 4 +- app/main/src/helpers/globalShortcuts.ts | 4 +- .../__tests__/fullScreenBreak.test.ts | 10 +- .../lifecycleEventHandlers/fullScreenBreak.ts | 6 +- app/main/src/main.ts | 671 ++++++++------- app/renderer/src/contexts/CounterContext.tsx | 768 +++++++++--------- .../Timer/Control/CompactModeButton.tsx | 4 +- .../src/routes/Timer/Control/Control.tsx | 2 +- .../src/routes/Timer/Counter/Counter.tsx | 2 +- website/src/components/PageHead.tsx | 2 +- 10 files changed, 725 insertions(+), 748 deletions(-) diff --git a/app/main/nodemon.json b/app/main/nodemon.json index ecfaa928..e4d2220f 100644 --- a/app/main/nodemon.json +++ b/app/main/nodemon.json @@ -1,4 +1,4 @@ { - "watch": ["src"], - "ext": "ts, css, png" + "watch": ["src"], + "ext": "ts, css, png" } diff --git a/app/main/src/helpers/globalShortcuts.ts b/app/main/src/helpers/globalShortcuts.ts index ce41e659..3d097ea0 100644 --- a/app/main/src/helpers/globalShortcuts.ts +++ b/app/main/src/helpers/globalShortcuts.ts @@ -14,11 +14,11 @@ export function activateGlobalShortcuts(shortcuts: ShortCut[]) { } export function activateFullScreenShortcuts( - exitFullScreenCallback: () => void + exitFullScreenCallback: () => void, ) { globalShortcut.registerAll( [EXIT_SHORTCUTS.ESCAPE, EXIT_SHORTCUTS.QUIT], - exitFullScreenCallback + exitFullScreenCallback, ); } diff --git a/app/main/src/lifecycleEventHandlers/__tests__/fullScreenBreak.test.ts b/app/main/src/lifecycleEventHandlers/__tests__/fullScreenBreak.test.ts index 07687104..6223ec0a 100644 --- a/app/main/src/lifecycleEventHandlers/__tests__/fullScreenBreak.test.ts +++ b/app/main/src/lifecycleEventHandlers/__tests__/fullScreenBreak.test.ts @@ -13,7 +13,7 @@ describe("Fullscreen break", () => { setResizable: jest.spyOn(window, "setResizable"), setVisibleOnAllWorkspaces: jest.spyOn( window, - "setVisibleOnAllWorkspaces" + "setVisibleOnAllWorkspaces", ), }; }; @@ -41,7 +41,7 @@ describe("Fullscreen break", () => { isFullscreen: fullscreenState.isFullscreen, trayTooltip, tray, - } + }, ); // Verify that window has been setup to fullscreen @@ -49,7 +49,7 @@ describe("Fullscreen break", () => { expect(windowSpies.focus).toHaveBeenCalledTimes(1); expect(windowSpies.setAlwaysOnTop).toHaveBeenCalledWith( true, - "screen-saver" + "screen-saver", ); expect(windowSpies.setSkipTaskbar).toHaveBeenCalledWith(true); expect(windowSpies.setFullScreen).toHaveBeenCalledWith(true); @@ -90,7 +90,7 @@ describe("Fullscreen break", () => { isFullscreen: fullscreenState.isFullscreen, trayTooltip, tray, - } + }, ); // Verify that window has been setup to fullscreen @@ -98,7 +98,7 @@ describe("Fullscreen break", () => { expect(windowSpies.focus).toHaveBeenCalledTimes(1); expect(windowSpies.setAlwaysOnTop).toHaveBeenCalledWith( true, - "screen-saver" + "screen-saver", ); expect(windowSpies.setSkipTaskbar).toHaveBeenCalledWith(false); expect(windowSpies.setFullScreen).toHaveBeenCalledWith(false); diff --git a/app/main/src/lifecycleEventHandlers/fullScreenBreak.ts b/app/main/src/lifecycleEventHandlers/fullScreenBreak.ts index ad8708a8..438baaa2 100644 --- a/app/main/src/lifecycleEventHandlers/fullScreenBreak.ts +++ b/app/main/src/lifecycleEventHandlers/fullScreenBreak.ts @@ -25,7 +25,7 @@ const setFullScreen = ( flag: boolean, alwaysOnTop: boolean, win: BrowserWindow | null, - isFullscreen: FullscreenState["isFullscreen"] + isFullscreen: FullscreenState["isFullscreen"], ) => { if (flag) { win?.setResizable(true); @@ -48,7 +48,7 @@ const setFullScreen = ( */ export const setFullscreenBreakHandler = ( fullscreenArgs: FullscreenArgs, - appArgs: AppArgs + appArgs: AppArgs, ) => { const { shouldFullscreen, alwaysOnTop } = fullscreenArgs; const { tray, trayTooltip, win, contextMenu, isFullscreen } = appArgs; @@ -64,7 +64,7 @@ export const setFullscreenBreakHandler = ( { label: "Please wait for your break to end.", }, - ]) + ]), ); } else { setFullScreen(false, alwaysOnTop, win, isFullscreen); diff --git a/app/main/src/main.ts b/app/main/src/main.ts index 47b70af3..14011d37 100644 --- a/app/main/src/main.ts +++ b/app/main/src/main.ts @@ -1,36 +1,36 @@ import { - BrowserWindow, - app, - ipcMain, - globalShortcut, - Menu, - Tray, - shell, - nativeImage, + BrowserWindow, + app, + ipcMain, + globalShortcut, + Menu, + Tray, + shell, + nativeImage, } from "electron"; import debounce from "lodash.debounce"; import notifier from "node-notifier"; import path from "path"; import { - SET_ALWAYS_ON_TOP, - SET_FULLSCREEN_BREAK, - SET_MINIMIZE, - SET_CLOSE, - SET_UI_THEME, - SET_NATIVE_TITLEBAR, - SET_SHOW, - RELEASED_NOTES_LINK, - TRAY_ICON_UPDATE, - SET_COMPACT_MODE, + SET_ALWAYS_ON_TOP, + SET_FULLSCREEN_BREAK, + SET_MINIMIZE, + SET_CLOSE, + SET_UI_THEME, + SET_NATIVE_TITLEBAR, + SET_SHOW, + RELEASED_NOTES_LINK, + TRAY_ICON_UPDATE, + SET_COMPACT_MODE, } from "@pomatez/shareables"; import { - activateGlobalShortcuts, - activateAutoUpdate, - blockShortcutKeys, - getIcon, - isWindow, - getFromStorage, - createContextMenu, + activateGlobalShortcuts, + activateAutoUpdate, + blockShortcutKeys, + getIcon, + isWindow, + getFromStorage, + createContextMenu, } from "./helpers"; import { activateUser } from "./helpers/analytics"; import store from "./store"; @@ -39,16 +39,13 @@ const isWin = process.platform === "win32"; import "v8-compile-cache"; import { - FullscreenState, - setFullscreenBreakHandler, + FullscreenState, + setFullscreenBreakHandler, } from "./lifecycleEventHandlers/fullScreenBreak"; const onProduction = app.isPackaged; -const notificationIcon = path.join( - __dirname, - "./assets/notification-dark.png" -); +const notificationIcon = path.join(__dirname, "./assets/notification-dark.png"); const trayIcon = path.join(__dirname, "./assets/tray-dark.png"); @@ -57,14 +54,14 @@ const onlySingleInstance = app.requestSingleInstanceLock(); Menu.setApplicationMenu(null); const getFrameHeight = () => { - if (isWindow()) { - return 502; - } else { - if (store.get("useNativeTitlebar")) { - return 480; - } - return 502; - } + if (isWindow()) { + return 502; + } else { + if (store.get("useNativeTitlebar")) { + return 480; + } + return 502; + } }; let tray: Tray | null = null; @@ -72,358 +69,358 @@ let tray: Tray | null = null; let win: BrowserWindow | null; type WindowStateProps = { - isOnCompactMode: boolean; + isOnCompactMode: boolean; } & FullscreenState; const windowState: WindowStateProps = { - isFullscreen: false, - isOnCompactMode: false, + isFullscreen: false, + isOnCompactMode: false, }; function createMainWindow() { - win = new BrowserWindow({ - width: 340, - height: getFrameHeight(), - resizable: true, - maximizable: false, - show: false, - frame: store.get("useNativeTitlebar"), - icon: getIcon(), - backgroundColor: store.get("isDarkMode") ? "#141e25" : "#fff", - webPreferences: { - contextIsolation: true, - backgroundThrottling: false, - preload: path.join(__dirname, "preload.js"), - }, - }); - - // Open the DevTools. - if (isDev) win.webContents.openDevTools({ mode: "detach" }); - - win.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url); - return { action: "deny" }; - }); - - win.loadURL( - !onProduction - ? "http://localhost:3000" - : `file://${path.join(__dirname, "index.html")}` - ); - - win.once("ready-to-show", () => { - win?.show(); - }); - - win.on( - "minimize", - debounce( - async () => { - try { - if (win) { - const data = await getFromStorage(win, "state"); - if (data.settings.minimizeToTray) { - if (!windowState.isFullscreen) { - win?.hide(); - if (tray === null && data.settings.minimizeToTray) { - createSystemTray(); - } - } - } - } - } catch (error) { - console.log(error); - } - }, - 1000, - { leading: true } - ) - ); - /** - * This only exists to counteract an issue with linux where leave-full-screen triggers every time this is called on linux (when exiting fullscreen) - * - * It may be fixed in a future version of linux. - * - * If you try to set the size smaller than the minimum allowed it will also cause issues here. - * - * @param width - * @param height - */ - function setSizeIfDiff(width: number, height: number) { - // Just to stop an infinite loop in the case of a bug - const minSize = win?.getMinimumSize(); - width = Math.max(width, minSize?.[0] || 0); - height = Math.max(height, minSize?.[1] || 0); - const size = win?.getSize(); - if (!size || size[0] !== width || size[1] !== height) { - win?.setSize(width, height); - } - } - - win.on("leave-full-screen", () => { - if (windowState.isOnCompactMode) { - setSizeIfDiff(340, 100); - // Windows doesn't like trying to set it as not resizeable it along with everything else that's going on - setTimeout(() => { - win?.setResizable(false); - }); - } else { - setSizeIfDiff(340, getFrameHeight()); - } - }); - - win.on( - "close", - debounce( - async (e) => { - e.preventDefault(); - try { - if (win) { - const data = await getFromStorage(win, "state"); - if (!data.settings.closeToTray) { - app.exit(); - } else { - if (!windowState.isFullscreen) { - win?.hide(); - if (tray === null && data.settings.closeToTray) { - createSystemTray(); - } - } - } - } - } catch (error) { - console.log(error); - } - }, - 1000, - { leading: true } - ) - ); - - win.on("closed", () => { - win = null; - }); - - createContextMenu(win); + win = new BrowserWindow({ + width: 340, + height: getFrameHeight(), + resizable: true, + maximizable: false, + show: false, + frame: store.get("useNativeTitlebar"), + icon: getIcon(), + backgroundColor: store.get("isDarkMode") ? "#141e25" : "#fff", + webPreferences: { + contextIsolation: true, + backgroundThrottling: false, + preload: path.join(__dirname, "preload.js"), + }, + }); + + // Open the DevTools. + if (isDev) win.webContents.openDevTools({ mode: "detach" }); + + win.webContents.setWindowOpenHandler((details) => { + shell.openExternal(details.url); + return { action: "deny" }; + }); + + win.loadURL( + !onProduction + ? "http://localhost:3000" + : `file://${path.join(__dirname, "index.html")}`, + ); + + win.once("ready-to-show", () => { + win?.show(); + }); + + win.on( + "minimize", + debounce( + async () => { + try { + if (win) { + const data = await getFromStorage(win, "state"); + if (data.settings.minimizeToTray) { + if (!windowState.isFullscreen) { + win?.hide(); + if (tray === null && data.settings.minimizeToTray) { + createSystemTray(); + } + } + } + } + } catch (error) { + console.log(error); + } + }, + 1000, + { leading: true }, + ), + ); + /** + * This only exists to counteract an issue with linux where leave-full-screen triggers every time this is called on linux (when exiting fullscreen) + * + * It may be fixed in a future version of linux. + * + * If you try to set the size smaller than the minimum allowed it will also cause issues here. + * + * @param width + * @param height + */ + function setSizeIfDiff(width: number, height: number) { + // Just to stop an infinite loop in the case of a bug + const minSize = win?.getMinimumSize(); + width = Math.max(width, minSize?.[0] || 0); + height = Math.max(height, minSize?.[1] || 0); + const size = win?.getSize(); + if (!size || size[0] !== width || size[1] !== height) { + win?.setSize(width, height); + } + } + + win.on("leave-full-screen", () => { + if (windowState.isOnCompactMode) { + setSizeIfDiff(340, 100); + // Windows doesn't like trying to set it as not resizeable it along with everything else that's going on + setTimeout(() => { + win?.setResizable(false); + }); + } else { + setSizeIfDiff(340, getFrameHeight()); + } + }); + + win.on( + "close", + debounce( + async (e) => { + e.preventDefault(); + try { + if (win) { + const data = await getFromStorage(win, "state"); + if (!data.settings.closeToTray) { + app.exit(); + } else { + if (!windowState.isFullscreen) { + win?.hide(); + if (tray === null && data.settings.closeToTray) { + createSystemTray(); + } + } + } + } + } catch (error) { + console.log(error); + } + }, + 1000, + { leading: true }, + ), + ); + + win.on("closed", () => { + win = null; + }); + + createContextMenu(win); } const trayTooltip = "Just click to restore."; const contextMenu = Menu.buildFromTemplate([ - { - label: "Restore the app", - click: () => { - win?.show(); - }, - }, - { - label: "Exit", - click: () => { - app.exit(); - }, - }, + { + label: "Restore the app", + click: () => { + win?.show(); + }, + }, + { + label: "Exit", + click: () => { + app.exit(); + }, + }, ]); function createSystemTray() { - tray = new Tray(trayIcon); - - tray.setToolTip(trayTooltip); - tray.setContextMenu(contextMenu); - - tray?.on("click", () => { - if (!win?.isVisible()) { - win?.show(); - } else { - if (!win?.isFullScreen()) { - win?.hide(); - } - } - }); + tray = new Tray(trayIcon); + + tray.setToolTip(trayTooltip); + tray.setContextMenu(contextMenu); + + tray?.on("click", () => { + if (!win?.isVisible()) { + win?.show(); + } else { + if (!win?.isFullScreen()) { + win?.hide(); + } + } + }); } if (!onlySingleInstance) { - app.quit(); + app.quit(); } else { - app.on("second-instance", () => { - if (win) { - if (win.isMinimized()) { - win.restore(); - } else if (!win.isVisible()) { - win.show(); - } else { - win.focus(); - } - } - }); - - app.whenReady().then(async () => { - if (isDev) { - console.log("Installing devtools"); - const extensions = ["REACT_DEVELOPER_TOOLS", "REDUX_DEVTOOLS"]; - const installer = await import("electron-devtools-installer"); - console.log(installer); - for (const tool of extensions) { - try { - await installer.default(installer[tool], true); - } catch (e) { - console.log(e); - } - } - } - createMainWindow(); - - if (onProduction) { - if (win) { - const blockKeys = [ - "CommandOrControl+R", - "CommandOrControl+Shift+R", - "CommandOrControl+Alt+Q", - "F11", - ]; - blockShortcutKeys(win, blockKeys); - } - } - - activateGlobalShortcuts([ - { - key: "Alt+Shift+H", - callback: () => { - win?.hide(); - }, - }, - { - key: "Alt+Shift+S", - callback: () => { - win?.show(); - }, - }, - ]); - - const autoUpdater = activateAutoUpdate({ - onUpdateAvailable: (info) => { - notifier.notify( - { - icon: notificationIcon, - title: "NEW UPDATE IS AVAILABLE", - message: `App version ${info.version} ready to be downloaded.`, - actions: ["View Released Notes"], - sound: true, - wait: true, - }, - (err, response) => { - if (!err) { - shell.openExternal(RELEASED_NOTES_LINK); - } - } - ); - }, - onUpdateDownloaded: (info) => { - notifier.notify( - { - icon: notificationIcon, - title: "READY TO BE INSTALLED", - message: "Update has been successfully downloaded.", - actions: ["Quit and Install", "Install it Later"], - sound: true, - wait: true, - }, - (err, response) => { - if (!err) { - if (response === "quit and install") { - autoUpdater.quitAndInstall(); - } - } - } - ); - }, - }); - }); - activateUser(); + app.on("second-instance", () => { + if (win) { + if (win.isMinimized()) { + win.restore(); + } else if (!win.isVisible()) { + win.show(); + } else { + win.focus(); + } + } + }); + + app.whenReady().then(async () => { + if (isDev) { + console.log("Installing devtools"); + const extensions = ["REACT_DEVELOPER_TOOLS", "REDUX_DEVTOOLS"]; + const installer = await import("electron-devtools-installer"); + console.log(installer); + for (const tool of extensions) { + try { + await installer.default(installer[tool], true); + } catch (e) { + console.log(e); + } + } + } + createMainWindow(); + + if (onProduction) { + if (win) { + const blockKeys = [ + "CommandOrControl+R", + "CommandOrControl+Shift+R", + "CommandOrControl+Alt+Q", + "F11", + ]; + blockShortcutKeys(win, blockKeys); + } + } + + activateGlobalShortcuts([ + { + key: "Alt+Shift+H", + callback: () => { + win?.hide(); + }, + }, + { + key: "Alt+Shift+S", + callback: () => { + win?.show(); + }, + }, + ]); + + const autoUpdater = activateAutoUpdate({ + onUpdateAvailable: (info) => { + notifier.notify( + { + icon: notificationIcon, + title: "NEW UPDATE IS AVAILABLE", + message: `App version ${info.version} ready to be downloaded.`, + actions: ["View Released Notes"], + sound: true, + wait: true, + }, + (err, response) => { + if (!err) { + shell.openExternal(RELEASED_NOTES_LINK); + } + }, + ); + }, + onUpdateDownloaded: (info) => { + notifier.notify( + { + icon: notificationIcon, + title: "READY TO BE INSTALLED", + message: "Update has been successfully downloaded.", + actions: ["Quit and Install", "Install it Later"], + sound: true, + wait: true, + }, + (err, response) => { + if (!err) { + if (response === "quit and install") { + autoUpdater.quitAndInstall(); + } + } + }, + ); + }, + }); + }); + activateUser(); } ipcMain.on(SET_ALWAYS_ON_TOP, (e, { alwaysOnTop }) => { - win?.setAlwaysOnTop(alwaysOnTop); + win?.setAlwaysOnTop(alwaysOnTop); }); ipcMain.on(SET_FULLSCREEN_BREAK, (e, args) => { - setFullscreenBreakHandler(args, { - win, - tray, - trayTooltip, - contextMenu, - isFullscreen: windowState.isFullscreen, - }); + setFullscreenBreakHandler(args, { + win, + tray, + trayTooltip, + contextMenu, + isFullscreen: windowState.isFullscreen, + }); }); ipcMain.on(SET_COMPACT_MODE, (e, args) => { - if (args.compactMode) { - win?.setMinimumSize(340, 100); - win?.setSize(340, 100); - win?.setResizable(false); - windowState.isOnCompactMode = true; - } else { - win?.setResizable(true); - windowState.isOnCompactMode = false; - win?.setMinimumSize(340, getFrameHeight()); - win?.setSize(340, getFrameHeight()); - } + if (args.compactMode) { + win?.setMinimumSize(340, 100); + win?.setSize(340, 100); + win?.setResizable(false); + windowState.isOnCompactMode = true; + } else { + win?.setResizable(true); + windowState.isOnCompactMode = false; + win?.setMinimumSize(340, getFrameHeight()); + win?.setSize(340, getFrameHeight()); + } }); ipcMain.on(SET_UI_THEME, (e, { isDarkMode }) => { - store.set("isDarkMode", isDarkMode); + store.set("isDarkMode", isDarkMode); }); ipcMain.on(SET_SHOW, () => { - if (!win?.isVisible()) { - win?.show(); - } else { - win?.focus(); - } + if (!win?.isVisible()) { + win?.show(); + } else { + win?.focus(); + } }); ipcMain.on(SET_MINIMIZE, (e, { minimizeToTray }) => { - win?.minimize(); - if (tray === null && minimizeToTray) { - createSystemTray(); - } + win?.minimize(); + if (tray === null && minimizeToTray) { + createSystemTray(); + } }); ipcMain.on(SET_CLOSE, (e, { closeToTray }) => { - app.quit(); - if (tray === null && closeToTray) { - createSystemTray(); - } + app.quit(); + if (tray === null && closeToTray) { + createSystemTray(); + } }); ipcMain.on(SET_NATIVE_TITLEBAR, (e, { useNativeTitlebar }) => { - if (store.get("useNativeTitlebar") !== useNativeTitlebar) { - store.set("useNativeTitlebar", useNativeTitlebar); - setTimeout(() => { - app.relaunch(); - app.exit(); - }, 1000); - } + if (store.get("useNativeTitlebar") !== useNativeTitlebar) { + store.set("useNativeTitlebar", useNativeTitlebar); + setTimeout(() => { + app.relaunch(); + app.exit(); + }, 1000); + } }); ipcMain.on(TRAY_ICON_UPDATE, (e, dataUrl) => { - const image = nativeImage.createFromDataURL(dataUrl); - tray?.setImage(image); + const image = nativeImage.createFromDataURL(dataUrl); + tray?.setImage(image); }); app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } + if (process.platform !== "darwin") { + app.quit(); + } }); app.on("activate", () => { - if (BrowserWindow.getAllWindows().length === 0) { - createMainWindow(); - } + if (BrowserWindow.getAllWindows().length === 0) { + createMainWindow(); + } }); app.on("will-quit", () => { - globalShortcut.unregisterAll(); + globalShortcut.unregisterAll(); }); app.setLoginItemSettings({ openAtLogin: true }); diff --git a/app/renderer/src/contexts/CounterContext.tsx b/app/renderer/src/contexts/CounterContext.tsx index 2eaf2b16..deeb6489 100644 --- a/app/renderer/src/contexts/CounterContext.tsx +++ b/app/renderer/src/contexts/CounterContext.tsx @@ -2,16 +2,16 @@ 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, + AppStateTypes, + STAY_FOCUS, + SHORT_BREAK, + setRound, + setTimerType, + LONG_BREAK, + TimerTypes, + SPECIAL_BREAK, + SettingTypes, + setPlay, } from "store"; import { useNotification } from "hooks"; import { padNum, isEqualToOne } from "utils"; @@ -26,396 +26,376 @@ import specialBreakStartedWav from "assets/audios/special-break-started.wav"; import thirtySecondsLeftWav from "assets/audios/thirty-seconds-left.wav"; type CounterProps = { - count: number; - duration: number; - timerType?: TimerTypes["timerType"]; - resetTimerAction?: () => void; - shouldFullscreen?: boolean; + count: number; + duration: number; + timerType?: TimerTypes["timerType"]; + resetTimerAction?: () => void; + shouldFullscreen?: boolean; }; const CounterContext = React.createContext({ - count: 0, - duration: 0, + count: 0, + duration: 0, }); const CounterProvider: React.FC = ({ children }) => { - const dispatch = useDispatch(); - - const { timer, config } = useSelector((state: AppStateTypes) => ({ - timer: state.timer, - config: state.config, - })); - - const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings - ); - - const { preventSleeping, allowSleeping } = useStayAwake(); - - const notification = useNotification( - { - icon: notificationIcon, - mute: !settings.notificationSoundOn, - }, - settings.notificationProperty !== "none" - ); - - const [shouldFullscreen, setShouldFullscreen] = useState(false); - - const [count, setCount] = useState(config.stayFocus * 60); - - const [duration, setDuration] = useState(config.stayFocus * 60); - - const setTimerDuration = useCallback((time: number) => { - setDuration(time * 60); - setCount(time * 60); - }, []); - - const resetTimerAction = useCallback(() => { - switch (timer.timerType) { - case STAY_FOCUS: - setTimerDuration(config.stayFocus); - break; - case SHORT_BREAK: - setTimerDuration(config.shortBreak); - break; - case LONG_BREAK: - setTimerDuration(config.longBreak); - break; - case SPECIAL_BREAK: - setDuration(duration); - setCount(duration); - break; - } - }, [ - config.longBreak, - config.stayFocus, - config.shortBreak, - timer.timerType, - duration, - setDuration, - setTimerDuration, - ]); - - useEffect(() => { - if (timer.playing && timer.timerType !== STAY_FOCUS) { - preventSleeping(); - } else { - allowSleeping(); - } - }, [timer.playing, timer.timerType, preventSleeping, allowSleeping]); - - useEffect(() => { - let interval: NodeJS.Timeout; - - const { firstBreak, secondBreak, thirdBreak, fourthBreak } = - config.specialBreaks; - - if (timer.playing) { - interval = setInterval(() => { - const date = new Date(); - const currentTime = - padNum(date.getHours()) + ":" + padNum(date.getMinutes()); - - if (timer.timerType !== SPECIAL_BREAK) { - switch (currentTime) { - case firstBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); - setTimerDuration(firstBreak.duration); - notification( - "Special break started.", - { - body: `You can now start taking your ${ - firstBreak.duration - } ${ - isEqualToOne(firstBreak.duration) - ? "minute" - : "minutes" - } special break.`, - }, - specialBreakStartedWav - ); - break; - case secondBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); - setTimerDuration(secondBreak.duration); - notification( - "Special break started.", - { - body: `You can now start taking your ${ - secondBreak.duration - } ${ - isEqualToOne(secondBreak.duration) - ? "minute" - : "minutes" - } special break.`, - }, - specialBreakStartedWav - ); - break; - case thirdBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); - setTimerDuration(thirdBreak.duration); - notification( - "Special break started.", - { - body: `You can now start taking your ${ - thirdBreak.duration - } ${ - isEqualToOne(thirdBreak.duration) - ? "minute" - : "minutes" - } special break.`, - }, - specialBreakStartedWav - ); - break; - case fourthBreak.fromTime: - dispatch(setTimerType("SPECIAL_BREAK")); - setTimerDuration(fourthBreak.duration); - notification( - "Special break started.", - { - body: `You can now start taking your ${ - fourthBreak.duration - } ${ - isEqualToOne(fourthBreak.duration) - ? "minute" - : "minutes" - } special break.`, - }, - specialBreakStartedWav - ); - break; - default: - return; - } - } else { - return clearInterval(interval); - } - }, 500); - } - - return () => clearInterval(interval); - }, [ - config.specialBreaks, - timer.timerType, - timer.playing, - dispatch, - notification, - setTimerDuration, - ]); - - useEffect(() => { - switch (timer.timerType) { - case STAY_FOCUS: - setTimerDuration(config.stayFocus); - break; - case SHORT_BREAK: - setTimerDuration(config.shortBreak); - break; - case LONG_BREAK: - setTimerDuration(config.longBreak); - break; - } - }, [ - setTimerDuration, - timer.timerType, - config.stayFocus, - config.shortBreak, - config.longBreak, - ]); - - useEffect(() => { - let timerInterval: NodeJS.Timeout; - - if (timer.playing) { - timerInterval = setInterval(() => { - setCount((prevState) => { - let remaining = prevState - 1; - return remaining; - }); - }, 1000); - } - - return () => clearInterval(timerInterval); - }, [timer.playing]); - - useEffect(() => { - if (settings.notificationProperty === "extra") { - if (count === 61) { - if (timer.timerType === SHORT_BREAK) { - notification( - "60 seconds left.", - { body: "Please prepare yourself to stay focused again." }, - settings.enableVoiceAssistance && sixtySecondsLeftWav - ); - } else if (timer.timerType === LONG_BREAK) { - notification( - "60 seconds left.", - { body: "Please prepare yourself to stay focused again." }, - settings.enableVoiceAssistance && sixtySecondsLeftWav - ); - } else if (timer.timerType === SPECIAL_BREAK) { - notification( - "60 seconds left.", - { body: "Please prepare yourself to stay focused again." }, - settings.enableVoiceAssistance && sixtySecondsLeftWav - ); - } - } else if (count === 31 && timer.timerType === STAY_FOCUS) { - notification( - "30 seconds left.", - { body: "Please pause all media playing if there's one." }, - settings.enableVoiceAssistance && thirtySecondsLeftWav - ); - } - } - - if (count === 0) { - switch (timer.timerType) { - case STAY_FOCUS: - if (timer.round < config.sessionRounds) { - setTimeout(() => { - notification( - "Focus time finished.", - { - body: `You can now start taking your ${ - config.shortBreak - } ${ - isEqualToOne(config.shortBreak) - ? "minute" - : "minutes" - } short break.`, - }, - settings.enableVoiceAssistance && focusFinishedWav - ); - - dispatch(setTimerType("SHORT_BREAK")); - }, 1000); - } else { - setTimeout(() => { - notification( - "Session rounds completed.", - { - body: `You can now start taking your ${ - config.longBreak - } ${ - isEqualToOne(config.longBreak) - ? "minute" - : "minutes" - } long break.`, - }, - settings.enableVoiceAssistance && sessionCompletedWav - ); - - dispatch(setTimerType("LONG_BREAK")); - }, 1000); - } - break; - - case SHORT_BREAK: - setTimeout(() => { - notification( - "Break time finished.", - { - body: `Stay focused for about ${config.stayFocus} ${ - isEqualToOne(config.stayFocus) ? "minute" : "minutes" - }.`, - }, - settings.enableVoiceAssistance && breakFinishedWav - ); - - dispatch(setTimerType("STAY_FOCUS")); - dispatch(setRound(timer.round + 1)); - - if (!settings.autoStartWorkTime) { - dispatch(setPlay(false)); - } - }, 1000); - break; - - case LONG_BREAK: - setTimeout(() => { - notification( - "Break time finished.", - { - body: `Stay focused for about ${config.stayFocus} ${ - isEqualToOne(config.stayFocus) ? "minute" : "minutes" - }.`, - }, - settings.enableVoiceAssistance && breakFinishedWav - ); - - dispatch(setTimerType("STAY_FOCUS")); - dispatch(setRound(1)); - - if (!settings.autoStartWorkTime) { - dispatch(setPlay(false)); - } - }, 1000); - break; - - case SPECIAL_BREAK: - setTimeout(() => { - notification( - "Break time finished.", - { - body: `Stay focused for about ${config.stayFocus} ${ - isEqualToOne(config.stayFocus) ? "minute" : "minutes" - }.`, - }, - settings.enableVoiceAssistance && breakFinishedWav - ); - - dispatch(setTimerType("STAY_FOCUS")); - - if (!settings.autoStartWorkTime) { - dispatch(setPlay(false)); - } - }, 1000); - break; - } - } - }, [ - count, - timer.round, - timer.playing, - timer.timerType, - dispatch, - notification, - config.stayFocus, - config.shortBreak, - config.longBreak, - config.sessionRounds, - settings.notificationProperty, - settings.autoStartWorkTime, - settings.enableVoiceAssistance, - ]); - - useEffect(() => { - if (settings.enableFullscreenBreak) { - if (timer.timerType !== STAY_FOCUS) { - setShouldFullscreen(true); - } else { - setShouldFullscreen(false); - } - } - }, [settings.enableFullscreenBreak, timer.timerType]); - - return ( - - {children} - - ); + const dispatch = useDispatch(); + + const { timer, config } = useSelector((state: AppStateTypes) => ({ + timer: state.timer, + config: state.config, + })); + + const settings: SettingTypes = useSelector( + (state: AppStateTypes) => state.settings, + ); + + const { preventSleeping, allowSleeping } = useStayAwake(); + + const notification = useNotification( + { + icon: notificationIcon, + mute: !settings.notificationSoundOn, + }, + settings.notificationProperty !== "none", + ); + + const [shouldFullscreen, setShouldFullscreen] = useState(false); + + const [count, setCount] = useState(config.stayFocus * 60); + + const [duration, setDuration] = useState(config.stayFocus * 60); + + const setTimerDuration = useCallback((time: number) => { + setDuration(time * 60); + setCount(time * 60); + }, []); + + const resetTimerAction = useCallback(() => { + switch (timer.timerType) { + case STAY_FOCUS: + setTimerDuration(config.stayFocus); + break; + case SHORT_BREAK: + setTimerDuration(config.shortBreak); + break; + case LONG_BREAK: + setTimerDuration(config.longBreak); + break; + case SPECIAL_BREAK: + setDuration(duration); + setCount(duration); + break; + } + }, [ + config.longBreak, + config.stayFocus, + config.shortBreak, + timer.timerType, + duration, + setDuration, + setTimerDuration, + ]); + + useEffect(() => { + if (timer.playing && timer.timerType !== STAY_FOCUS) { + preventSleeping(); + } else { + allowSleeping(); + } + }, [timer.playing, timer.timerType, preventSleeping, allowSleeping]); + + useEffect(() => { + let interval: NodeJS.Timeout; + + const { firstBreak, secondBreak, thirdBreak, fourthBreak } = + config.specialBreaks; + + if (timer.playing) { + interval = setInterval(() => { + const date = new Date(); + const currentTime = + padNum(date.getHours()) + ":" + padNum(date.getMinutes()); + + if (timer.timerType !== SPECIAL_BREAK) { + switch (currentTime) { + case firstBreak.fromTime: + dispatch(setTimerType("SPECIAL_BREAK")); + setTimerDuration(firstBreak.duration); + notification( + "Special break started.", + { + body: `You can now start taking your ${firstBreak.duration} ${ + isEqualToOne(firstBreak.duration) ? "minute" : "minutes" + } special break.`, + }, + specialBreakStartedWav, + ); + break; + case secondBreak.fromTime: + dispatch(setTimerType("SPECIAL_BREAK")); + setTimerDuration(secondBreak.duration); + notification( + "Special break started.", + { + body: `You can now start taking your ${ + secondBreak.duration + } ${ + isEqualToOne(secondBreak.duration) ? "minute" : "minutes" + } special break.`, + }, + specialBreakStartedWav, + ); + break; + case thirdBreak.fromTime: + dispatch(setTimerType("SPECIAL_BREAK")); + setTimerDuration(thirdBreak.duration); + notification( + "Special break started.", + { + body: `You can now start taking your ${thirdBreak.duration} ${ + isEqualToOne(thirdBreak.duration) ? "minute" : "minutes" + } special break.`, + }, + specialBreakStartedWav, + ); + break; + case fourthBreak.fromTime: + dispatch(setTimerType("SPECIAL_BREAK")); + setTimerDuration(fourthBreak.duration); + notification( + "Special break started.", + { + body: `You can now start taking your ${ + fourthBreak.duration + } ${ + isEqualToOne(fourthBreak.duration) ? "minute" : "minutes" + } special break.`, + }, + specialBreakStartedWav, + ); + break; + default: + return; + } + } else { + return clearInterval(interval); + } + }, 500); + } + + return () => clearInterval(interval); + }, [ + config.specialBreaks, + timer.timerType, + timer.playing, + dispatch, + notification, + setTimerDuration, + ]); + + useEffect(() => { + switch (timer.timerType) { + case STAY_FOCUS: + setTimerDuration(config.stayFocus); + break; + case SHORT_BREAK: + setTimerDuration(config.shortBreak); + break; + case LONG_BREAK: + setTimerDuration(config.longBreak); + break; + } + }, [ + setTimerDuration, + timer.timerType, + config.stayFocus, + config.shortBreak, + config.longBreak, + ]); + + useEffect(() => { + let timerInterval: NodeJS.Timeout; + + if (timer.playing) { + timerInterval = setInterval(() => { + setCount((prevState) => { + let remaining = prevState - 1; + return remaining; + }); + }, 1000); + } + + return () => clearInterval(timerInterval); + }, [timer.playing]); + + useEffect(() => { + if (settings.notificationProperty === "extra") { + if (count === 61) { + if (timer.timerType === SHORT_BREAK) { + notification( + "60 seconds left.", + { body: "Please prepare yourself to stay focused again." }, + settings.enableVoiceAssistance && sixtySecondsLeftWav, + ); + } else if (timer.timerType === LONG_BREAK) { + notification( + "60 seconds left.", + { body: "Please prepare yourself to stay focused again." }, + settings.enableVoiceAssistance && sixtySecondsLeftWav, + ); + } else if (timer.timerType === SPECIAL_BREAK) { + notification( + "60 seconds left.", + { body: "Please prepare yourself to stay focused again." }, + settings.enableVoiceAssistance && sixtySecondsLeftWav, + ); + } + } else if (count === 31 && timer.timerType === STAY_FOCUS) { + notification( + "30 seconds left.", + { body: "Please pause all media playing if there's one." }, + settings.enableVoiceAssistance && thirtySecondsLeftWav, + ); + } + } + + if (count === 0) { + switch (timer.timerType) { + case STAY_FOCUS: + if (timer.round < config.sessionRounds) { + setTimeout(() => { + notification( + "Focus time finished.", + { + body: `You can now start taking your ${config.shortBreak} ${ + isEqualToOne(config.shortBreak) ? "minute" : "minutes" + } short break.`, + }, + settings.enableVoiceAssistance && focusFinishedWav, + ); + + dispatch(setTimerType("SHORT_BREAK")); + }, 1000); + } else { + setTimeout(() => { + notification( + "Session rounds completed.", + { + body: `You can now start taking your ${config.longBreak} ${ + isEqualToOne(config.longBreak) ? "minute" : "minutes" + } long break.`, + }, + settings.enableVoiceAssistance && sessionCompletedWav, + ); + + dispatch(setTimerType("LONG_BREAK")); + }, 1000); + } + break; + + case SHORT_BREAK: + setTimeout(() => { + notification( + "Break time finished.", + { + body: `Stay focused for about ${config.stayFocus} ${ + isEqualToOne(config.stayFocus) ? "minute" : "minutes" + }.`, + }, + settings.enableVoiceAssistance && breakFinishedWav, + ); + + dispatch(setTimerType("STAY_FOCUS")); + dispatch(setRound(timer.round + 1)); + + if (!settings.autoStartWorkTime) { + dispatch(setPlay(false)); + } + }, 1000); + break; + + case LONG_BREAK: + setTimeout(() => { + notification( + "Break time finished.", + { + body: `Stay focused for about ${config.stayFocus} ${ + isEqualToOne(config.stayFocus) ? "minute" : "minutes" + }.`, + }, + settings.enableVoiceAssistance && breakFinishedWav, + ); + + dispatch(setTimerType("STAY_FOCUS")); + dispatch(setRound(1)); + + if (!settings.autoStartWorkTime) { + dispatch(setPlay(false)); + } + }, 1000); + break; + + case SPECIAL_BREAK: + setTimeout(() => { + notification( + "Break time finished.", + { + body: `Stay focused for about ${config.stayFocus} ${ + isEqualToOne(config.stayFocus) ? "minute" : "minutes" + }.`, + }, + settings.enableVoiceAssistance && breakFinishedWav, + ); + + dispatch(setTimerType("STAY_FOCUS")); + + if (!settings.autoStartWorkTime) { + dispatch(setPlay(false)); + } + }, 1000); + break; + } + } + }, [ + count, + timer.round, + timer.playing, + timer.timerType, + dispatch, + notification, + config.stayFocus, + config.shortBreak, + config.longBreak, + config.sessionRounds, + settings.notificationProperty, + settings.autoStartWorkTime, + settings.enableVoiceAssistance, + ]); + + useEffect(() => { + if (settings.enableFullscreenBreak) { + if (timer.timerType !== STAY_FOCUS) { + setShouldFullscreen(true); + } else { + setShouldFullscreen(false); + } + } + }, [settings.enableFullscreenBreak, timer.timerType]); + + return ( + + {children} + + ); }; export { CounterContext, CounterProvider }; diff --git a/app/renderer/src/routes/Timer/Control/CompactModeButton.tsx b/app/renderer/src/routes/Timer/Control/CompactModeButton.tsx index c783fdc8..0fb0e3c8 100644 --- a/app/renderer/src/routes/Timer/Control/CompactModeButton.tsx +++ b/app/renderer/src/routes/Timer/Control/CompactModeButton.tsx @@ -10,7 +10,7 @@ type Props = { flipped?: boolean } & React.HTMLProps; const CompactModeButton: React.FC = ({ onClick, flipped }) => { const { compactMode }: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings + (state: AppStateTypes) => state.settings, ); const buttonRef = useRef(null); @@ -24,7 +24,7 @@ const CompactModeButton: React.FC = ({ onClick, flipped }) => { onClick(e); } }), - [buttonClickAction, onClick] + [buttonClickAction, onClick], ); return ( diff --git a/app/renderer/src/routes/Timer/Control/Control.tsx b/app/renderer/src/routes/Timer/Control/Control.tsx index 615f1b69..171cf8af 100644 --- a/app/renderer/src/routes/Timer/Control/Control.tsx +++ b/app/renderer/src/routes/Timer/Control/Control.tsx @@ -41,7 +41,7 @@ const Control: React.FC = ({ resetTimerAction }) => { })); const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings + (state: AppStateTypes) => state.settings, ); const dispatch = useDispatch(); diff --git a/app/renderer/src/routes/Timer/Counter/Counter.tsx b/app/renderer/src/routes/Timer/Counter/Counter.tsx index f41a968c..3cf717cf 100644 --- a/app/renderer/src/routes/Timer/Counter/Counter.tsx +++ b/app/renderer/src/routes/Timer/Counter/Counter.tsx @@ -14,7 +14,7 @@ import CounterType from "./CounterType"; const Counter: React.FC = () => { const settings: SettingTypes = useSelector( - (state: AppStateTypes) => state.settings + (state: AppStateTypes) => state.settings, ); const { count, duration, timerType, shouldFullscreen } = diff --git a/website/src/components/PageHead.tsx b/website/src/components/PageHead.tsx index 0b0051e2..a04bbec8 100644 --- a/website/src/components/PageHead.tsx +++ b/website/src/components/PageHead.tsx @@ -145,7 +145,7 @@ export const PageHead: React.FC = ({ name: "twitter:card", content: "summary", }, - ] + ], ); if (meta) {