refactor: Convert pure components to functional components

Co-authored-by: David Ralph <me@davidcralph.co.uk>
Co-authored-by: Isaac <contact@eartharoid.me>
This commit is contained in:
alexsparkes
2024-06-14 18:51:36 +01:00
parent 0f9393d3e6
commit 4747dea06b
37 changed files with 1718 additions and 1849 deletions

View File

@@ -15,6 +15,7 @@ import { FileUpload, Text, Switch, Dropdown } from 'components/Form/Settings';
import { ResetModal, Button } from 'components/Elements';
import { Header, Section, Row, Content, Action } from 'components/Layout/Settings';
import { useTab } from 'components/Elements/MainModal/backend/TabContext';
import time_zones from 'features/time/timezones.json';
@@ -22,6 +23,7 @@ function AdvancedOptions() {
const [resetModal, setResetModal] = useState(false);
const [data, setData] = useState(false);
const ADVANCED_SECTION = 'modals.main.settings.sections.advanced';
const { subSection } = useTab();
const Data = () => {
return localStorage.getItem('welcomePreview') !== 'true' ? (
@@ -93,7 +95,7 @@ function AdvancedOptions() {
return (
<>
{header}
{data ? (
{subSection === "data" ? (
<>
<Data />
<Modal
@@ -110,6 +112,7 @@ function AdvancedOptions() {
) : (
<>
<Section
id="data"
title={variables.getMessage(`${ADVANCED_SECTION}.data`)}
subtitle={variables.getMessage(`${ADVANCED_SECTION}.data_subtitle`)}
onClick={() => setData(true)}

View File

@@ -4,6 +4,7 @@ import variables from 'config/variables';
import { Checkbox, Dropdown, Radio, Slider, Text } from 'components/Form/Settings';
import { Header, Section, Row, Content, Action } from 'components/Layout/Settings';
import { useTab } from 'components/Elements/MainModal/backend/TabContext';
import { MdAccessibility } from 'react-icons/md';
@@ -11,6 +12,7 @@ import values from 'utils/data/slider_values.json';
function AppearanceOptions() {
const [accessibility, setAccessibility] = useState(false);
const { subSection } = useTab();
const ThemeSelection = () => {
return (
@@ -262,11 +264,12 @@ function AppearanceOptions() {
return (
<>
{header}
{accessibility ? (
{subSection === "accessibility" ? (
<AccessibilityOptions />
) : (
<>
<Section
id="accessibility"
title={variables.getMessage(
'modals.main.settings.sections.appearance.accessibility.title',
)}

View File

@@ -1,56 +1,27 @@
import variables from 'config/variables';
import { PureComponent, createRef } from 'react';
import { useState, createRef, useEffect } from 'react';
import Markdown from 'markdown-to-jsx';
import { MdOutlineWifiOff } from 'react-icons/md';
class Changelog extends PureComponent {
constructor() {
super();
this.state = {
title: null,
};
this.offlineMode = localStorage.getItem('offlineMode') === 'true';
this.controller = new AbortController();
this.changelog = createRef();
}
function Changelog() {
const [title, setTitle] = useState(null);
const [error, setError] = useState(false);
const [content, setContent] = useState(null);
const [date, setDate] = useState(null);
parseMarkdown = (text) => {
if (typeof text !== 'string') {
throw new Error('Input must be a string');
}
const offlineMode = localStorage.getItem('offlineMode') === 'true';
const controller = new AbortController();
const changelog = createRef();
// Replace markdown syntax
text = text
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/^## (.*$)/gm, '<span class="title">$1</span>')
.replace(
/((http|https):\/\/[^\s]+)/g,
'<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>',
)
// resolve @ to github user link
.replace(
/@([a-zA-Z0-9-_]+)/g,
'<a href="https://github.com/$1" target="_blank" class="changelogAt">@$1</a>',
);
// Replace list items
text = text.replace(/^\* (.*$)/gm, '<li>$1</li>');
// Wrap list items in <ul></ul>
text = text.replace(/((<li>.*<\/li>\s*)+)/g, '<ul>$1</ul>');
return text;
};
async getUpdate() {
const getUpdate = async () => {
const releases = await fetch(
`https://api.github.com/repos/${variables.constants.ORG_NAME}/${variables.constants.REPO_NAME}/releases`,
{
signal: this.controller.signal,
signal: controller.signal,
},
);
if (this.controller.signal.aborted === true) {
if (controller.signal.aborted === true) {
return;
}
@@ -63,92 +34,88 @@ class Changelog extends PureComponent {
}
// request the changelog
const res = await fetch(release.url, { signal: this.controller.signal });
const res = await fetch(release.url, { signal: controller.signal });
if (res.status === 404) {
this.setState({ error: true });
setError(true);
return;
}
if (this.controller.signal.aborted === true) {
if (controller.signal.aborted === true) {
return;
}
const changelog = await res.json();
this.setState({
title: changelog.name,
content: changelog.body,
date: new Date(changelog.published_at).toLocaleDateString(),
});
setTitle(changelog.name);
setContent(changelog.body);
setDate(new Date(changelog.published_at).toLocaleDateString());
}
componentDidMount() {
if (navigator.onLine === false || this.offlineMode) {
useEffect(() => {
if (navigator.onLine === false || offlineMode) {
return;
}
this.getUpdate();
}
getUpdate();
}, []);
componentWillUnmount() {
useEffect(() => {
// stop making requests
this.controller.abort();
}
render() {
const errorMessage = (msg) => {
return (
<div className="emptyItems">
<div className="emptyMessage">{msg}</div>
</div>
);
};
if (navigator.onLine === false || this.offlineMode) {
return errorMessage(
<>
<MdOutlineWifiOff />
<h1>{variables.getMessage('modals.main.marketplace.offline.title')}</h1>
<p className="description">
{variables.getMessage('modals.main.marketplace.offline.description')}
</p>
</>,
);
}
if (this.state.error === true) {
return errorMessage(
<>
<MdOutlineWifiOff />
<span className="title">{variables.getMessage('modals.main.error_boundary.title')}</span>
<span className="subtitle">
{variables.getMessage('modals.main.error_boundary.message')}
</span>
</>,
);
}
if (!this.state.title) {
return errorMessage(
<div className="loaderHolder">
<div id="loader"></div>
<span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
</div>,
);
}
return () => controller.abort();
}, []);
const errorMessage = (msg) => {
return (
<article className="changelogtab prose dark:prose-invert" ref={this.changelog}>
<div className="not-prose">
<span className="mainTitle">{this.state.title}</span>
<span className="subtitle">Released on {this.state.date}</span>
</div>
<Markdown options={{ overrides: { a: { props: { target: '_blank' } } } }}>
{this.state.content}
</Markdown>
</article>
<div className="emptyItems">
<div className="emptyMessage">{msg}</div>
</div>
);
};
if (navigator.onLine === false || offlineMode) {
return errorMessage(
<>
<MdOutlineWifiOff />
<h1>{variables.getMessage('modals.main.marketplace.offline.title')}</h1>
<p className="description">
{variables.getMessage('modals.main.marketplace.offline.description')}
</p>
</>,
);
}
if (error === true) {
return errorMessage(
<>
<MdOutlineWifiOff />
<span className="title">{variables.getMessage('modals.main.error_boundary.title')}</span>
<span className="subtitle">
{variables.getMessage('modals.main.error_boundary.message')}
</span>
</>,
);
}
if (!title) {
return errorMessage(
<div className="loaderHolder">
<div id="loader"></div>
<span className="subtitle">{variables.getMessage('modals.main.loading')}</span>
</div>,
);
}
return (
<article className="changelogtab prose dark:prose-invert" ref={changelog}>
<div className="not-prose">
<span className="mainTitle">{title}</span>
<span className="subtitle">Released on {date}</span>
</div>
<Markdown options={{ overrides: { a: { props: { target: '_blank' } } } }}>
{content}
</Markdown>
</article>
);
}
export { Changelog as default, Changelog };

View File

@@ -29,6 +29,7 @@ const SortableItem = sortableElement(({ value }) => (
</li>
));
const SortableContainer = sortableContainer(({ children }) => (
<ul className="sortableContainer">{children}</ul>
));