feature/IO-3066-1-scaffolding: Minor cleanup
This commit is contained in:
6
.idea/prettier.xml
generated
Normal file
6
.idea/prettier.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PrettierConfiguration">
|
||||
<option name="myConfigurationMode" value="AUTOMATIC" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -16,7 +16,6 @@ import { NotificationProvider } from "./util/notificationContext";
|
||||
|
||||
const App: FC = () => {
|
||||
const [user, setUser] = useState<User | boolean | null>(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Only set up the listener once when component mounts
|
||||
if (auth.currentUser) {
|
||||
@@ -66,7 +65,7 @@ const App: FC = () => {
|
||||
) : (
|
||||
<Badge.Ribbon
|
||||
text={isTest && "Connected to Test"}
|
||||
color={isTest && "red"}
|
||||
color={isTest ? "red" : undefined}
|
||||
>
|
||||
<Layout.Content style={{ padding: "0 24px" }}>
|
||||
<UpdateAvailable />
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
//TODO: remove eslint-disable
|
||||
import { FC } from "react";
|
||||
import { Button, Result } from "antd";
|
||||
import { FallbackProps } from "react-error-boundary";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const ErrorBoundaryFallback: React.FC<FallbackProps> = ({
|
||||
const ErrorBoundaryFallback: FC<FallbackProps> = ({
|
||||
error,
|
||||
resetErrorBoundary,
|
||||
}) => {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const Home: React.FC = () => {
|
||||
import { FC } from "react";
|
||||
|
||||
const Home: FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>Home</h1>
|
||||
|
||||
@@ -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<string | null>(null);
|
||||
|
||||
@@ -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<string | null>(null);
|
||||
|
||||
@@ -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<string[]>([]);
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { JSX, useState } from "react";
|
||||
|
||||
function Versions(): JSX.Element {
|
||||
const [versions] = useState(window.electron.process.versions);
|
||||
|
||||
@@ -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<string | null>(null);
|
||||
@@ -21,7 +22,7 @@ const Welcome = (): JSX.Element => {
|
||||
<>
|
||||
<Typography.Title level={4}>
|
||||
{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={<LogoutOutlined />}
|
||||
onClick={(): void => {
|
||||
auth.signOut();
|
||||
auth.signOut().catch((error) => {
|
||||
console.error("Sign out error:", error);
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("navigation.signout")}
|
||||
|
||||
@@ -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",
|
||||
});
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -9,6 +9,7 @@ const store = configureStore({
|
||||
|
||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
|
||||
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
export type AppStore = typeof store;
|
||||
|
||||
@@ -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<Timer>({
|
||||
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);
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ const httpLink: HttpLink = new HttpLink({
|
||||
});
|
||||
|
||||
const middlewares = [];
|
||||
|
||||
const client: ApolloClient<any> = new ApolloClient({
|
||||
link: ApolloLink.from(middlewares),
|
||||
cache: new InMemoryCache(),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
|
||||
@@ -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<NotificationProviderProps> = ({
|
||||
export const NotificationProvider: FC<NotificationProviderProps> = ({
|
||||
// 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<NotificationProviderProps> = ({
|
||||
});
|
||||
|
||||
return (
|
||||
// @ts-ignore
|
||||
<NotificationContext.Provider value={api}>
|
||||
{/* contextHolder must be rendered in the DOM so notifications can appear */}
|
||||
{contextHolder}
|
||||
|
||||
@@ -33,4 +33,5 @@ function deepLowerCaseKeys<T = any>(obj: any): T {
|
||||
{} as Record<string, any>,
|
||||
) as T;
|
||||
}
|
||||
|
||||
export default deepLowerCaseKeys;
|
||||
|
||||
@@ -12,6 +12,7 @@ function errorTypeCheck(passedError: Error | unknown): ParsedError {
|
||||
stack: errorStack,
|
||||
};
|
||||
}
|
||||
|
||||
export default errorTypeCheck;
|
||||
|
||||
export interface ParsedError {
|
||||
|
||||
Reference in New Issue
Block a user