Home
diff --git a/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx b/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx
index aff8ee6..a84e0a5 100644
--- a/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx
+++ b/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx
@@ -1,10 +1,10 @@
import { FolderOpenFilled } from "@ant-design/icons";
import { Button, Card, Input, Space } from "antd";
-import { useEffect, useState } from "react";
+import { useEffect, useState, FC } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
-const SettingsEmsOutFilePath: React.FC = () => {
+const SettingsEmsOutFilePath: FC = () => {
const { t } = useTranslation();
const [emsFilePath, setEmsFilePath] = useState
(null);
diff --git a/src/renderer/src/components/Settings/Settings.PpcFilePath.tsx b/src/renderer/src/components/Settings/Settings.PpcFilePath.tsx
index 43318a7..82ff80c 100644
--- a/src/renderer/src/components/Settings/Settings.PpcFilePath.tsx
+++ b/src/renderer/src/components/Settings/Settings.PpcFilePath.tsx
@@ -1,10 +1,10 @@
import { FolderOpenFilled } from "@ant-design/icons";
import { Button, Card, Input, Space } from "antd";
-import { useEffect, useState } from "react";
+import { useEffect, useState, FC } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
-const SettingsPpcFilepath: React.FC = () => {
+const SettingsPpcFilepath: FC = () => {
const { t } = useTranslation();
const [ppcFilePath, setPpcFilePath] = useState(null);
diff --git a/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx b/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx
index dfe0999..81026f4 100644
--- a/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx
+++ b/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx
@@ -1,10 +1,10 @@
import { DeleteFilled, FileAddFilled } from "@ant-design/icons";
import { Button, Card, Space, Timeline } from "antd";
-import { useEffect, useState } from "react";
+import { useEffect, useState, FC } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
-const SettingsWatchedPaths: React.FC = () => {
+const SettingsWatchedPaths: FC = () => {
const [watchedPaths, setWatchedPaths] = useState([]);
const { t } = useTranslation();
diff --git a/src/renderer/src/components/Settings/Settings.Watcher.tsx b/src/renderer/src/components/Settings/Settings.Watcher.tsx
index 136b561..6215ec6 100644
--- a/src/renderer/src/components/Settings/Settings.Watcher.tsx
+++ b/src/renderer/src/components/Settings/Settings.Watcher.tsx
@@ -1,14 +1,14 @@
+import { useAppSelector } from "@renderer/redux/reduxHooks";
import {
CheckCircleFilled,
ExclamationCircleFilled,
- PlayCircleOutlined,
PauseCircleOutlined,
+ PlayCircleOutlined,
} from "@ant-design/icons";
import {
selectWatcherError,
selectWatcherStatus,
} from "@renderer/redux/app.slice";
-import { useAppSelector } from "@renderer/redux/reduxHooks";
import {
Alert,
Badge,
@@ -20,7 +20,7 @@ import {
Space,
Switch,
} from "antd";
-import { useEffect, useState } from "react";
+import { FC, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
@@ -29,7 +29,7 @@ const colSpans = {
sm: 24,
};
-const SettingsWatcher: React.FC = () => {
+const SettingsWatcher: FC = () => {
const { t } = useTranslation();
const isWatcherStarted = useAppSelector(selectWatcherStatus);
const watcherError = useAppSelector(selectWatcherError);
diff --git a/src/renderer/src/components/Settings/Settings.tsx b/src/renderer/src/components/Settings/Settings.tsx
index b0eb60a..0e71702 100644
--- a/src/renderer/src/components/Settings/Settings.tsx
+++ b/src/renderer/src/components/Settings/Settings.tsx
@@ -1,4 +1,5 @@
import { Col, Row } from "antd";
+import { FC } from "react";
import SettingsWatchedPaths from "./Settings.WatchedPaths";
import SettingsWatcher from "./Settings.Watcher";
import Welcome from "../Welcome/Welcome";
@@ -9,7 +10,7 @@ const colSpans = {
md: 12,
sm: 24,
};
-const Settings: React.FC = () => {
+const Settings: FC = () => {
return (
diff --git a/src/renderer/src/components/SignInForm/SignInForm.tsx b/src/renderer/src/components/SignInForm/SignInForm.tsx
index 83dff59..360cc23 100644
--- a/src/renderer/src/components/SignInForm/SignInForm.tsx
+++ b/src/renderer/src/components/SignInForm/SignInForm.tsx
@@ -1,6 +1,6 @@
import { auth } from "@renderer/util/firebase";
import type { FormProps } from "antd";
-import { Alert, Button, Form, Input, Space, Card, Typography } from "antd";
+import { Alert, Button, Card, Form, Input, Typography } from "antd";
import log from "electron-log/renderer";
import { signInWithEmailAndPassword } from "firebase/auth";
import { useState } from "react";
diff --git a/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
index b808854..a43c61b 100644
--- a/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
+++ b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx
@@ -8,9 +8,9 @@ import { useAppSelector } from "@renderer/redux/reduxHooks";
import { Affix, Button, Card, Progress, Space, Statistic } from "antd";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
-import { useState } from "react";
+import { useState, FC } from "react";
-const UpdateAvailable: React.FC = () => {
+const UpdateAvailable: FC = () => {
const { t } = useTranslation();
const isUpdateAvailable = useAppSelector(selectUpdateAvailable);
diff --git a/src/renderer/src/components/Versions.tsx b/src/renderer/src/components/Versions.tsx
index dc71bbf..ddd7349 100644
--- a/src/renderer/src/components/Versions.tsx
+++ b/src/renderer/src/components/Versions.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { JSX, useState } from "react";
function Versions(): JSX.Element {
const [versions] = useState(window.electron.process.versions);
diff --git a/src/renderer/src/components/Welcome/Welcome.tsx b/src/renderer/src/components/Welcome/Welcome.tsx
index a36ed9d..d3d3c87 100644
--- a/src/renderer/src/components/Welcome/Welcome.tsx
+++ b/src/renderer/src/components/Welcome/Welcome.tsx
@@ -1,10 +1,11 @@
import { LogoutOutlined } from "@ant-design/icons";
import { auth } from "@renderer/util/firebase";
import { Button, Space, Typography } from "antd";
-import _ from "lodash";
+import { isEmpty } from "lodash";
import { JSX, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
+
const Welcome = (): JSX.Element => {
const { t } = useTranslation();
const [shopName, setShopName] = useState(null);
@@ -21,7 +22,7 @@ const Welcome = (): JSX.Element => {
<>
{t("auth.labels.welcome", {
- name: _.isEmpty(auth.currentUser?.displayName)
+ name: isEmpty(auth.currentUser?.displayName)
? auth.currentUser?.email
: `${auth.currentUser?.displayName} (${auth.currentUser?.email})`.trim(),
})}
@@ -33,7 +34,9 @@ const Welcome = (): JSX.Element => {
danger
icon={}
onClick={(): void => {
- auth.signOut();
+ auth.signOut().catch((error) => {
+ console.error("Sign out error:", error);
+ });
}}
>
{t("navigation.signout")}
diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx
index a9c033b..ef1b4a0 100644
--- a/src/renderer/src/main.tsx
+++ b/src/renderer/src/main.tsx
@@ -5,6 +5,16 @@ import "./util/i18n";
import "./util/ipcRendererHandler";
import * as Sentry from "@sentry/electron/renderer";
+// Extend the Window interface to include the api property
+declare global {
+ interface Window {
+ api: {
+ isTest: () => boolean;
+ };
+ }
+}
+
+
Sentry.init({
dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296",
});
diff --git a/src/renderer/src/redux/app.slice.ts b/src/renderer/src/redux/app.slice.ts
index 09dc261..806c8e8 100644
--- a/src/renderer/src/redux/app.slice.ts
+++ b/src/renderer/src/redux/app.slice.ts
@@ -1,6 +1,7 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import log from "electron-log/renderer";
import type { RootState } from "./redux-store";
+
interface AppState {
value: number;
watcher: {
diff --git a/src/renderer/src/redux/redux-store.ts b/src/renderer/src/redux/redux-store.ts
index 84a9707..a798de3 100644
--- a/src/renderer/src/redux/redux-store.ts
+++ b/src/renderer/src/redux/redux-store.ts
@@ -9,6 +9,7 @@ const store = configureStore({
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType;
+
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;
export type AppStore = typeof store;
diff --git a/src/renderer/src/util/countdownHook.ts b/src/renderer/src/util/countdownHook.ts
index 5b2acd9..61b2d28 100644
--- a/src/renderer/src/util/countdownHook.ts
+++ b/src/renderer/src/util/countdownHook.ts
@@ -1,4 +1,12 @@
-import React from "react";
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+
+type Timer = {
+ started: number | null;
+ lastInterval: number | null;
+ timeLeft: number;
+ timeToCount: number;
+ requestId: number;
+};
const useCountDown = (
timeToCount = 60 * 1000,
@@ -12,10 +20,16 @@ const useCountDown = (
reset: () => void;
},
] => {
- const [timeLeft, setTimeLeft] = React.useState(0);
- const timer = React.useRef({});
+ const [timeLeft, setTimeLeft] = useState(0);
+ const timer = useRef({
+ started: null,
+ lastInterval: null,
+ timeLeft: 0,
+ timeToCount: 0,
+ requestId: 0,
+ });
- const run = (ts) => {
+ const run = (ts: number) => {
if (!timer.current.started) {
timer.current.started = ts;
timer.current.lastInterval = ts;
@@ -25,7 +39,7 @@ const useCountDown = (
interval,
timer.current.timeLeft || Infinity,
);
- if (ts - timer.current.lastInterval >= localInterval) {
+ if (timer.current.lastInterval && ts - timer.current.lastInterval >= localInterval) {
timer.current.lastInterval += localInterval;
setTimeLeft((timeLeft) => {
timer.current.timeLeft = timeLeft - localInterval;
@@ -36,12 +50,18 @@ const useCountDown = (
if (ts - timer.current.started < timer.current.timeToCount) {
timer.current.requestId = window.requestAnimationFrame(run);
} else {
- timer.current = {};
+ timer.current = {
+ started: null,
+ lastInterval: null,
+ timeLeft: 0,
+ timeToCount: 0,
+ requestId: 0,
+ };
setTimeLeft(0);
}
};
- const start = React.useCallback(
+ const start = useCallback(
(ttc) => {
window.cancelAnimationFrame(timer.current.requestId);
@@ -57,14 +77,14 @@ const useCountDown = (
[],
);
- const pause = React.useCallback(() => {
+ const pause = useCallback(() => {
window.cancelAnimationFrame(timer.current.requestId);
timer.current.started = null;
timer.current.lastInterval = null;
timer.current.timeToCount = timer.current.timeLeft;
}, []);
- const resume = React.useCallback(
+ const resume = useCallback(
() => {
if (!timer.current.started && timer.current.timeLeft > 0) {
window.cancelAnimationFrame(timer.current.requestId);
@@ -75,20 +95,26 @@ const useCountDown = (
[],
);
- const reset = React.useCallback(() => {
+ const reset = useCallback(() => {
if (timer.current.timeLeft) {
window.cancelAnimationFrame(timer.current.requestId);
- timer.current = {};
+ timer.current = {
+ started: null,
+ lastInterval: null,
+ timeLeft: 0,
+ timeToCount: 0,
+ requestId: 0,
+ };
setTimeLeft(0);
}
}, []);
- const actions = React.useMemo(
+ const actions = useMemo(
() => ({ start, pause, resume, reset }), // eslint-disable-next-line react-hooks/exhaustive-deps
[],
);
- React.useEffect(() => {
+ useEffect(() => {
return () => window.cancelAnimationFrame(timer.current.requestId);
}, []);
diff --git a/src/renderer/src/util/graphql.client.ts b/src/renderer/src/util/graphql.client.ts
index 5183a9f..5ddac51 100644
--- a/src/renderer/src/util/graphql.client.ts
+++ b/src/renderer/src/util/graphql.client.ts
@@ -10,6 +10,7 @@ const httpLink: HttpLink = new HttpLink({
});
const middlewares = [];
+
const client: ApolloClient = new ApolloClient({
link: ApolloLink.from(middlewares),
cache: new InMemoryCache(),
diff --git a/src/renderer/src/util/i18n.ts b/src/renderer/src/util/i18n.ts
index 414aa6c..0df882e 100644
--- a/src/renderer/src/util/i18n.ts
+++ b/src/renderer/src/util/i18n.ts
@@ -6,13 +6,19 @@ const resources = {
en: enTranslations,
};
-i18n.use(initReactI18next).init({
- resources,
- debug: import.meta.env.DEV,
- lng: "en",
- interpolation: {
- escapeValue: false,
- },
-});
+i18n
+ .use(initReactI18next)
+ .init({
+ resources,
+ debug: import.meta.env.DEV,
+ lng: "en",
+ interpolation: {
+ escapeValue: false,
+ },
+ })
+ .catch((err) => {
+ console.error("i18n initialization error:", err);
+ throw err;
+ });
export default i18n;
diff --git a/src/renderer/src/util/ipcRendererHandler.ts b/src/renderer/src/util/ipcRendererHandler.ts
index c0bc704..8182169 100644
--- a/src/renderer/src/util/ipcRendererHandler.ts
+++ b/src/renderer/src/util/ipcRendererHandler.ts
@@ -1,4 +1,4 @@
-//Set up all of the IPC handlers.
+//Set up all the IPC handlers.
import {
setWatcherPolling,
updateAvailable,
@@ -40,6 +40,7 @@ ipcRenderer.on(ipcTypes.toRenderer.watcher.stopped, () => {
console.log("Watcher has stopped");
dispatch(watcherStopped());
});
+
ipcRenderer.on(
ipcTypes.toRenderer.watcher.error,
(_event: Electron.IpcRendererEvent, error: string) => {
@@ -58,6 +59,7 @@ ipcRenderer.on(ipcTypes.toRenderer.updates.checking, () => {
ipcRenderer.on(ipcTypes.toRenderer.updates.available, () => {
dispatch(updateAvailable());
});
+
ipcRenderer.on(
ipcTypes.toRenderer.updates.downloading,
(_event: Electron.IpcRendererEvent, arg) => {
@@ -70,6 +72,7 @@ ipcRenderer.on(
);
},
);
+
ipcRenderer.on(ipcTypes.toRenderer.updates.downloaded, () => {
dispatch(updateDownloaded());
});
diff --git a/src/renderer/src/util/notificationContext.tsx b/src/renderer/src/util/notificationContext.tsx
index 8f4450f..efec48a 100644
--- a/src/renderer/src/util/notificationContext.tsx
+++ b/src/renderer/src/util/notificationContext.tsx
@@ -1,5 +1,4 @@
-// eslint-disable-all
-import { createContext, useContext } from "react";
+import {createContext, FC, ReactNode, useContext} from "react";
import { notification } from "antd";
/**
@@ -23,10 +22,10 @@ export const useNotification = () => {
* - Provide `api` via the NotificationContext.
*/
interface NotificationProviderProps {
- children?: React.ReactNode | React.ReactNode[];
+ children?: ReactNode | ReactNode[];
}
-export const NotificationProvider: React.FC = ({
+export const NotificationProvider: FC = ({
// eslint-disable-next-line react/prop-types
children, //TODO: Unable to resolve this. Adding an eslint disable.
}) => {
@@ -37,6 +36,7 @@ export const NotificationProvider: React.FC = ({
});
return (
+ // @ts-ignore
{/* contextHolder must be rendered in the DOM so notifications can appear */}
{contextHolder}
diff --git a/src/util/deepLowercaseKeys.ts b/src/util/deepLowercaseKeys.ts
index 9bf9d47..052ee8c 100644
--- a/src/util/deepLowercaseKeys.ts
+++ b/src/util/deepLowercaseKeys.ts
@@ -33,4 +33,5 @@ function deepLowerCaseKeys(obj: any): T {
{} as Record,
) as T;
}
+
export default deepLowerCaseKeys;
diff --git a/src/util/errorTypeCheck.ts b/src/util/errorTypeCheck.ts
index 8ed8853..149b348 100644
--- a/src/util/errorTypeCheck.ts
+++ b/src/util/errorTypeCheck.ts
@@ -12,6 +12,7 @@ function errorTypeCheck(passedError: Error | unknown): ParsedError {
stack: errorStack,
};
}
+
export default errorTypeCheck;
export interface ParsedError {