diff --git a/frontend/src/AppWrapper.tsx b/frontend/src/AppWrapper.tsx
new file mode 100644
index 0000000..597bb12
--- /dev/null
+++ b/frontend/src/AppWrapper.tsx
@@ -0,0 +1,23 @@
+import { IsFatalError } from '@wailsapp/go/main/App';
+import { EventsOn, EventsOff } from '@wailsapp/runtime/runtime';
+import { useState, useEffect } from 'react';
+import App from './ui/App';
+import ErrorWindow from './ui/ErrorWindow';
+
+export default function AppWrapper() {
+ const [fatalErrorEncountered, setFatalErrorStatus] = useState(false);
+ useEffect(() => {
+ void IsFatalError().then(setFatalErrorStatus);
+ EventsOn('fatalError', () => {
+ setFatalErrorStatus(true);
+ });
+ return () => {
+ EventsOff('fatalError');
+ };
+ }, []);
+
+ if (fatalErrorEncountered) {
+ return ;
+ }
+ return ;
+}
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 75becb8..6d4586c 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -1,9 +1,7 @@
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { HashRouter } from 'react-router-dom';
-import { StrictMode, useEffect, useState } from 'react';
-import { EventsOff, EventsOn } from '@wailsapp/runtime';
-import { IsFatalError } from '@wailsapp/go/main/App';
+import { StrictMode } from 'react';
import 'inter-ui/inter.css';
import '@fontsource/space-mono/index.css';
@@ -11,30 +9,11 @@ import 'normalize.css/normalize.css';
import './locale/setup';
import store from './store';
-import App from './ui/App';
-import ErrorWindow from './ui/ErrorWindow';
import { globalStyles } from './ui/theme';
+import AppWrapper from './AppWrapper';
globalStyles();
-function AppWrapper() {
- const [fatalErrorEncountered, setFatalErrorStatus] = useState(false);
- useEffect(() => {
- void IsFatalError().then(setFatalErrorStatus);
- EventsOn('fatalError', () => {
- setFatalErrorStatus(true);
- });
- return () => {
- EventsOff('fatalError');
- };
- }, []);
-
- if (fatalErrorEncountered) {
- return ;
- }
- return ;
-}
-
const main = document.getElementById('main');
const root = createRoot(main);
root.render(
diff --git a/frontend/src/ui/components/AlertContent.tsx b/frontend/src/ui/components/AlertContent.tsx
index 79b4d01..2f6f6af 100644
--- a/frontend/src/ui/components/AlertContent.tsx
+++ b/frontend/src/ui/components/AlertContent.tsx
@@ -71,4 +71,5 @@ function AlertContent({
);
}
-export default React.memo(AlertContent);
+const PureAlertContent = React.memo(AlertContent);
+export default PureAlertContent;
diff --git a/frontend/src/ui/components/BrowserLink.tsx b/frontend/src/ui/components/BrowserLink.tsx
index 31b5e33..49f6fa9 100644
--- a/frontend/src/ui/components/BrowserLink.tsx
+++ b/frontend/src/ui/components/BrowserLink.tsx
@@ -19,4 +19,5 @@ function BrowserLink(props: React.AnchorHTMLAttributes) {
);
}
-export default React.memo(BrowserLink);
+const PureBrowserLink = React.memo(BrowserLink);
+export default PureBrowserLink;
diff --git a/frontend/src/ui/components/DefinitionTable.tsx b/frontend/src/ui/components/DefinitionTable.tsx
index 14df73e..d28c8bd 100644
--- a/frontend/src/ui/components/DefinitionTable.tsx
+++ b/frontend/src/ui/components/DefinitionTable.tsx
@@ -37,4 +37,5 @@ function DefinitionTable({ entries }: DefinitionTableProps) {
);
}
-export default React.memo(DefinitionTable);
+const PureDefinitionTable = React.memo(DefinitionTable);
+export default PureDefinitionTable;
diff --git a/frontend/src/ui/components/DialogContent.tsx b/frontend/src/ui/components/DialogContent.tsx
index cb640a6..9d23e76 100644
--- a/frontend/src/ui/components/DialogContent.tsx
+++ b/frontend/src/ui/components/DialogContent.tsx
@@ -45,4 +45,5 @@ function DialogContent({
);
}
-export default React.memo(DialogContent);
+const PureDialogContent = React.memo(DialogContent);
+export default PureDialogContent;
diff --git a/frontend/src/ui/components/LogViewer.tsx b/frontend/src/ui/components/LogViewer.tsx
index 045a5fa..461d61d 100644
--- a/frontend/src/ui/components/LogViewer.tsx
+++ b/frontend/src/ui/components/LogViewer.tsx
@@ -429,4 +429,5 @@ function LogViewer() {
);
}
-export default React.memo(LogViewer);
+const PureLogViewer = React.memo(LogViewer);
+export default PureLogViewer;
diff --git a/frontend/src/ui/components/PageList.tsx b/frontend/src/ui/components/PageList.tsx
index 5d37972..9e0cdec 100644
--- a/frontend/src/ui/components/PageList.tsx
+++ b/frontend/src/ui/components/PageList.tsx
@@ -156,4 +156,5 @@ function PageList({
);
}
-export default React.memo(PageList);
+const PurePageList = React.memo(PageList);
+export default PurePageList;
diff --git a/frontend/src/ui/components/forms/Interval.tsx b/frontend/src/ui/components/forms/Interval.tsx
index 2aaa4cf..3a41b34 100644
--- a/frontend/src/ui/components/forms/Interval.tsx
+++ b/frontend/src/ui/components/forms/Interval.tsx
@@ -1,17 +1,13 @@
-import React from 'react';
import { useTranslation } from 'react-i18next';
import { getInterval } from '~/lib/time';
import { ComboBox, FlexRow, InputBox } from '../../theme';
+import { seconds, minutes, hours } from './units';
export interface TimeUnit {
multiplier: number;
unit: string;
}
-export const seconds = { multiplier: 1, unit: 'time.seconds' };
-export const minutes = { multiplier: 60, unit: 'time.minutes' };
-export const hours = { multiplier: 3600, unit: 'time.hours' };
-
export interface IntervalProps {
active: boolean;
value: number;
@@ -22,7 +18,7 @@ export interface IntervalProps {
onChange?: (value: number) => void;
}
-function Interval({
+export default function Interval({
id,
active,
value,
@@ -87,5 +83,3 @@ function Interval({
>
);
}
-
-export default React.memo(Interval);
diff --git a/frontend/src/ui/components/forms/MultiInput.tsx b/frontend/src/ui/components/forms/MultiInput.tsx
index 0727cec..a641315 100644
--- a/frontend/src/ui/components/forms/MultiInput.tsx
+++ b/frontend/src/ui/components/forms/MultiInput.tsx
@@ -91,4 +91,5 @@ function MultiInput({
);
}
-export default React.memo(MultiInput);
+const PureMultiInput = React.memo(MultiInput);
+export default PureMultiInput;
diff --git a/frontend/src/ui/components/forms/PasswordField.tsx b/frontend/src/ui/components/forms/PasswordField.tsx
index e94cc46..6af22c9 100644
--- a/frontend/src/ui/components/forms/PasswordField.tsx
+++ b/frontend/src/ui/components/forms/PasswordField.tsx
@@ -22,4 +22,5 @@ function PasswordField(
);
}
-export default React.memo(PasswordField);
+const PurePasswordField = React.memo(PasswordField);
+export default PurePasswordField;
diff --git a/frontend/src/ui/components/forms/RadioGroup.tsx b/frontend/src/ui/components/forms/RadioGroup.tsx
index b46a0bd..e28ce0b 100644
--- a/frontend/src/ui/components/forms/RadioGroup.tsx
+++ b/frontend/src/ui/components/forms/RadioGroup.tsx
@@ -60,7 +60,7 @@ const RadioIndicator = styled(Indicator, {
},
});
-export default function RadioGroup(props: RadioGroupProps & RootProps) {
+function RadioGroup(props: RadioGroupProps & RootProps) {
return (
{props.values.map(({ id, label }) => (
@@ -74,3 +74,6 @@ export default function RadioGroup(props: RadioGroupProps & RootProps) {
);
}
+
+const PureRadioGroup = React.memo(RadioGroup);
+export default PureRadioGroup;
diff --git a/frontend/src/ui/components/forms/SaveButton.tsx b/frontend/src/ui/components/forms/SaveButton.tsx
index 65c5ab9..f8641e0 100644
--- a/frontend/src/ui/components/forms/SaveButton.tsx
+++ b/frontend/src/ui/components/forms/SaveButton.tsx
@@ -31,4 +31,5 @@ function SaveButton(
}
}
-export default React.memo(SaveButton);
+const PureSaveButton = React.memo(SaveButton);
+export default PureSaveButton;
diff --git a/frontend/src/ui/components/forms/units.tsx b/frontend/src/ui/components/forms/units.tsx
new file mode 100644
index 0000000..ef663be
--- /dev/null
+++ b/frontend/src/ui/components/forms/units.tsx
@@ -0,0 +1,3 @@
+export const seconds = { multiplier: 1, unit: 'time.seconds' };
+export const minutes = { multiplier: 60, unit: 'time.minutes' };
+export const hours = { multiplier: 3600, unit: 'time.hours' };
diff --git a/frontend/src/ui/components/utils/RevealLink.tsx b/frontend/src/ui/components/utils/RevealLink.tsx
index 61064e4..793d6c0 100644
--- a/frontend/src/ui/components/utils/RevealLink.tsx
+++ b/frontend/src/ui/components/utils/RevealLink.tsx
@@ -28,4 +28,5 @@ function RevealLink({ value, setter }: RevealLinkProps) {
);
}
-export default React.memo(RevealLink);
+const PureRevealLink = React.memo(RevealLink);
+export default PureRevealLink;
diff --git a/frontend/src/ui/components/utils/Scrollbar.tsx b/frontend/src/ui/components/utils/Scrollbar.tsx
index 4635643..ffd8fd1 100644
--- a/frontend/src/ui/components/utils/Scrollbar.tsx
+++ b/frontend/src/ui/components/utils/Scrollbar.tsx
@@ -61,4 +61,5 @@ function Scrollbar({
);
}
-export default React.memo(Scrollbar);
+const PureScrollbar = React.memo(Scrollbar);
+export default PureScrollbar;
diff --git a/frontend/src/ui/components/utils/WIPNotice.tsx b/frontend/src/ui/components/utils/WIPNotice.tsx
index 0270baf..29c4505 100644
--- a/frontend/src/ui/components/utils/WIPNotice.tsx
+++ b/frontend/src/ui/components/utils/WIPNotice.tsx
@@ -33,4 +33,5 @@ function WIP(): React.ReactElement {
);
}
-export default React.memo(WIP);
+const PureWIP = React.memo(WIP);
+export default PureWIP;
diff --git a/frontend/src/ui/pages/BotTimers.tsx b/frontend/src/ui/pages/BotTimers.tsx
index 86321ca..a872c4b 100644
--- a/frontend/src/ui/pages/BotTimers.tsx
+++ b/frontend/src/ui/pages/BotTimers.tsx
@@ -8,7 +8,8 @@ import { modules } from '~/store/api/reducer';
import { TwitchBotTimer } from '~/store/api/types';
import AlertContent from '../components/AlertContent';
import DialogContent from '../components/DialogContent';
-import Interval, { hours, minutes } from '../components/forms/Interval';
+import Interval from '../components/forms/Interval';
+import { hours, minutes } from '../components/forms/units';
import MultiInput from '../components/forms/MultiInput';
import {
Button,