From 01b89541c0d883e1da5896d9f41a031b71230c18 Mon Sep 17 00:00:00 2001 From: David Ralph Date: Wed, 21 Aug 2024 14:26:46 +0100 Subject: [PATCH] refactor: about functional component, reimplement abort controller --- .../background/options/BackgroundOptions.jsx | 6 + src/features/marketplace/views/Browse.jsx | 5 + src/features/misc/sections/About.jsx | 533 ++++++++---------- src/features/misc/sections/Changelog.jsx | 8 +- 4 files changed, 268 insertions(+), 284 deletions(-) diff --git a/src/features/background/options/BackgroundOptions.jsx b/src/features/background/options/BackgroundOptions.jsx index 32fdb6a4..3ccb9bff 100644 --- a/src/features/background/options/BackgroundOptions.jsx +++ b/src/features/background/options/BackgroundOptions.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import variables from 'config/variables'; import { useState, useEffect } from 'react'; import { MdSource, MdOutlineKeyboardArrowRight, MdOutlineAutoAwesome } from 'react-icons/md'; @@ -33,6 +34,11 @@ function BackgroundOptions() { const [backgroundSettingsSection, setBackgroundSettingsSection] = useState(false); const controller = new AbortController(); + useEffect(() => { + return () => { + controller.abort(); + } + }, []); async function getBackgroundCategories() { const data = await ( diff --git a/src/features/marketplace/views/Browse.jsx b/src/features/marketplace/views/Browse.jsx index 765e8d32..9cd5b946 100644 --- a/src/features/marketplace/views/Browse.jsx +++ b/src/features/marketplace/views/Browse.jsx @@ -24,6 +24,11 @@ function Marketplace() { const { changeTab } = useTab(); const controller = new AbortController(); + useEffect(() => { + return () => { + controller.abort(); + } + }, []); async function toggle(pageType, data) { if (pageType === 'item') { diff --git a/src/features/misc/sections/About.jsx b/src/features/misc/sections/About.jsx index d04f2f0a..cad4a910 100644 --- a/src/features/misc/sections/About.jsx +++ b/src/features/misc/sections/About.jsx @@ -1,5 +1,5 @@ import variables from 'config/variables'; -import { PureComponent } from 'react'; +import { useState, useEffect } from 'react'; import { MdEmail, MdContactPage } from 'react-icons/md'; import { FaDiscord } from 'react-icons/fa'; import { SiGithubsponsors, SiOpencollective, SiX } from 'react-icons/si'; @@ -7,21 +7,25 @@ import { BiDonateHeart } from 'react-icons/bi'; import { Tooltip, Button } from 'components/Elements'; -class About extends PureComponent { - constructor() { - super(); - this.state = { - contributors: [], - sponsors: [], - photographers: [], - curators: [], - update: variables.getMessage('settings:sections.about.version.checking_update'), - loading: variables.getMessage('modals.main.loading'), - }; - this.controller = new AbortController(); - } +function About() { + const [contributors, setContributors] = useState([]); + const [sponsors, setSponsors] = useState([]); + const [photographers, setPhotographers] = useState([]); + const [curators, setCurators] = useState([]); - async getGitHubData() { + const [update, setUpdate] = useState( + variables.getMessage('settings:sections.about.version.checking_update'), + ); + const [loading, setLoading] = useState(variables.getMessage('modals.main.loading')); + + const controller = new AbortController(); + useEffect(() => { + return () => { + controller.abort(); + }; + }, []); + + const getGitHubData = async () => { let contributors, sponsors, photographers, curators, versionData; try { @@ -33,9 +37,10 @@ class About extends PureComponent { '/' + variables.constants.REPO_NAME + '/releases', - { signal: this.controller.signal }, + { signal: controller.signal }, ) ).json(); + contributors = await ( await fetch( variables.constants.GITHUB_URL + @@ -44,52 +49,50 @@ class About extends PureComponent { '/' + variables.constants.REPO_NAME + '/contributors', - { signal: this.controller.signal }, + { signal: controller.signal }, ) ).json(); - sponsors = ( - await ( - await fetch(variables.constants.SPONSORS_URL + '/list', { - signal: this.controller.signal, - }) - ).json() - ).sponsors; + + sponsors = await ( + await fetch(variables.constants.SPONSORS_URL + '/list', { + signal: controller.signal, + }) + ).json().sponsors; + photographers = await ( await fetch(variables.constants.API_URL + '/images/photographers', { - signal: this.controller.signal, + signal: controller.signal, }) ).json(); + curators = ( await ( await fetch(variables.constants.API_URL + '/marketplace/curators', { - signal: this.controller.signal, + signal: controller.signal, }) ).json() ).data; } catch (e) { - if (this.controller.signal.aborted === true) { + if (controller.signal.aborted === true) { return; } - return this.setState({ - update: variables.getMessage('settings:sections.about.version.error.title'), - loading: variables.getMessage( - 'settings:sections.about.version.error.description', - ), - }); + setUpdate(variables.getMessage('settings:sections.about.version.error.title')); + setLoading(variables.getMessage('settings:sections.about.version.error.description')); } if (sponsors.length === 0) { sponsors = [{ handle: 'empty' }]; } - if (this.controller.signal.aborted === true) { + if (controller.signal.aborted === true) { return; } const newVersion = versionData[0].tag_name; let update = variables.getMessage('settings:sections.about.version.no_update'); + if ( Number(variables.constants.VERSION.replaceAll('.', '')) < Number(newVersion.replaceAll('.', '')) @@ -99,280 +102,244 @@ class About extends PureComponent { )}: ${newVersion}`; } - this.setState({ - // exclude bots - contributors: contributors.filter((contributor) => !contributor.login.includes('bot')), - sponsors, - update, - photographers, - curators, - loading: null, - }); - } + setContributors(contributors.filter((contributor) => !contributor.login.includes('bot'))); + setSponsors(sponsors); + setUpdate(update); + setPhotographers(photographers); + setCurators(curators); + setLoading(null); + }; - componentDidMount() { + useEffect(() => { if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') { - this.setState({ - update: variables.getMessage('marketplace:offline.description'), - loading: variables.getMessage('marketplace:offline.description'), - }); + setUpdate(variables.getMessage('marketplace:offline.description')); + setLoading(variables.getMessage('marketplace:offline.description')); return; } - this.getGitHubData(); - } + getGitHubData(); + }, []); - componentWillUnmount() { - // stop making requests - this.controller.abort(); - } - - render() { - return ( -
-
-
- Logo -
- Mue, by Kaiso - - {variables.getMessage('settings:sections.about.version.title')}{' '} - {variables.constants.VERSION} - - ({this.state.update}) -
-
- - Copyright 2018- - {new Date().getFullYear()}{' '} - - The Mue Authors - - -

- - Copyright 2023-2024{' '} - - {' '} - Kaiso One Ltd - - -
- Licensed under the BSD-3-Clause License + return ( +
+
+
+ Logo +
+ Mue, by Kaiso + {variables.getMessage('settings:sections.about.version.title')}{' '} + {variables.constants.VERSION} + + ({update}) +
+
+ + Copyright 2018- + {new Date().getFullYear()}{' '} - {variables.getMessage('welcome:sections.privacy.links.privacy_policy')} + The Mue Authors + + +

+ + Copyright 2023-2024{' '} + + {' '} + Kaiso One Ltd
-
- -
- - {variables.getMessage('settings:sections.about.contact_us')} - -
-
-
- -
- - {variables.getMessage('settings:sections.about.support_mue')} - -

{variables.getMessage('settings:sections.about.support_subtitle')}

-
-
-
- -
- - {variables.getMessage('settings:sections.about.resources_used.title')} - + Licensed under the BSD-3-Clause License - Pexels + {variables.getMessage('welcome:sections.privacy.links.privacy_policy')} - ,{' '} - - Unsplash - {' '} - ({variables.getMessage('settings:sections.about.resources_used.bg_images')})
- -
- - {variables.getMessage('settings:sections.about.contributors')} - -

{this.state.loading}

-
- {this.state.contributors.map(({ login, id }) => ( - - - {login} - - - ))} -
-
- -
- - {variables.getMessage('settings:sections.about.supporters')} - -

{this.state.loading}

-
- {this.state.sponsors.map(({ handle, avatar }) => { - if (handle === 'empty') { - return ( -

{variables.getMessage('settings:sections.about.no_supporters')}

- ); - } - - return ( - - - {handle} - - - ); - })} -
-
-
- - {variables.getMessage('settings:sections.about.photographers')} - - {!!this.state.loading ?

{this.state.loading}

: <>} -
    - {this.state.photographers.map(({ name, count }) => ( -
  • - {name} - ({count} images) -
  • - ))} -
-
-
- - {variables.getMessage('settings:sections.about.curators')} - - {!!this.state.loading ?

{this.state.loading}

: <>} -
    - {this.state.curators.map((name) => ( -
  • - {name} -
  • - ))} -
-
- ); - } + +
+ {variables.getMessage('settings:sections.about.contact_us')} +
+
+
+ +
+ {variables.getMessage('settings:sections.about.support_mue')} +

{variables.getMessage('settings:sections.about.support_subtitle')}

+
+
+
+ +
+ + {variables.getMessage('settings:sections.about.resources_used.title')} + + + + Pexels + + ,{' '} + + Unsplash + {' '} + ({variables.getMessage('settings:sections.about.resources_used.bg_images')}) + +
+ +
+ + {variables.getMessage('settings:sections.about.contributors')} + +

{loading}

+
+ {contributors.map(({ login, id }) => ( + + + {login} + + + ))} +
+
+ +
+ {variables.getMessage('settings:sections.about.supporters')} +

{loading}

+
+ {sponsors.map(({ handle, avatar }) => { + if (handle === 'empty') { + return

{variables.getMessage('settings:sections.about.no_supporters')}

; + } + + return ( + + + {handle} + + + ); + })} +
+
+
+ + {variables.getMessage('settings:sections.about.photographers')} + + {!!loading ?

{loading}

: <>} +
    + {photographers.map(({ name, count }) => ( +
  • + {name} + ({count} images) +
  • + ))} +
+
+
+ {variables.getMessage('settings:sections.about.curators')} + {!!loading ?

{loading}

: <>} +
    + {curators.map((name) => ( +
  • + {name} +
  • + ))} +
+
+
+ ); } export { About as default, About }; diff --git a/src/features/misc/sections/Changelog.jsx b/src/features/misc/sections/Changelog.jsx index d261f7b4..9feb3bf9 100644 --- a/src/features/misc/sections/Changelog.jsx +++ b/src/features/misc/sections/Changelog.jsx @@ -10,9 +10,15 @@ function Changelog() { const [date, setDate] = useState(null); const offlineMode = localStorage.getItem('offlineMode') === 'true'; - const controller = new AbortController(); const changelog = createRef(); + const controller = new AbortController(); + useEffect(() => { + return () => { + controller.abort(); + } + }, []); + const getUpdate = async () => { const releases = await fetch( `https://api.github.com/repos/${variables.constants.ORG_NAME}/${variables.constants.REPO_NAME}/releases`,