update react scripts dependency (#255)

* Move "dependencies" close to "devDependencies"

Makes it easier to have a quick overview

* Upgrade "react-scripts" to latest version

With new versions of node (> v16) the build scripts fails with the following error "error:0308010C:digital envelope routines::unsupported"

* Upgrade "react-scripts" to v5 - Fix import

* Upgrade "eslint" dependencies

The latest version of "react-scripts" uses eslint v8 causing the following error "... ERROR in Plugin "react" was conflicted between ".eslintrc.js" >> eslint-config-airbnb ..."

* Upgrade "eslint" dependencies - Allow nested components as props

* Upgrade "eslint" dependencies - Fix lint issues
This commit is contained in:
schroda
2023-03-11 18:05:58 +01:00
committed by GitHub
parent 91e7bd2b27
commit 23001a4298
24 changed files with 5248 additions and 6320 deletions

View File

@@ -13,11 +13,19 @@ module.exports = {
'react/jsx-no-bind': 'off', 'react/jsx-no-bind': 'off',
'react/jsx-props-no-spreading': 'off', 'react/jsx-props-no-spreading': 'off',
'react/require-default-props': 'off', 'react/require-default-props': 'off',
'react/function-component-definition': 'off',
"no-relative-import-paths/no-relative-import-paths": [ 'react/no-unstable-nested-components': [
"error", 'error',
{ {
rootDir: "src", allowAsProps: true,
},
],
'no-relative-import-paths/no-relative-import-paths': [
'error',
{
rootDir: 'src',
prefix: false, prefix: false,
}, },
], ],

View File

@@ -2,33 +2,6 @@
"name": "project", "name": "project",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@fontsource/roboto": "^4.3.0",
"@mui/icons-material": "^5.0.5",
"@mui/lab": "^5.0.0-alpha.53",
"@mui/material": "^5.0.6",
"@mui/styles": "^5.0.2",
"@mui/system": "^5.0.6",
"axios": "^0.21.1",
"file-selector": "^0.2.4",
"i18next": "^22.4.9",
"i18next-browser-languagedetector": "^7.0.1",
"p-queue": "^7.2.0",
"query-string": "^7.0.1",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^17.0.2",
"react-i18next": "^12.1.5",
"react-lazyload": "^3.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-virtuoso": "^1.8.6",
"swr": "^1.3.0",
"use-query-params": "^1.2.3",
"web-vitals": "^2.1.0"
},
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
"build": "react-scripts build", "build": "react-scripts build",
@@ -50,24 +23,51 @@
"last 1 safari version" "last 1 safari version"
] ]
}, },
"dependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@fontsource/roboto": "^4.3.0",
"@mui/icons-material": "^5.0.5",
"@mui/lab": "^5.0.0-alpha.53",
"@mui/material": "^5.0.6",
"@mui/styles": "^5.0.2",
"@mui/system": "^5.0.6",
"axios": "^0.21.1",
"file-selector": "^0.2.4",
"i18next": "^22.4.9",
"i18next-browser-languagedetector": "^7.0.1",
"p-queue": "^7.2.0",
"query-string": "^7.0.1",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.0.0",
"react-dom": "^17.0.2",
"react-i18next": "^12.1.5",
"react-lazyload": "^3.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "^5.0.1",
"react-virtuoso": "^1.8.6",
"swr": "^1.3.0",
"use-query-params": "^1.2.3",
"web-vitals": "^2.1.0"
},
"devDependencies": { "devDependencies": {
"@types/react": "^17.0.2", "@types/react": "^17.0.2",
"@types/react-beautiful-dnd": "^13.0.0", "@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "^17.0.2", "@types/react-dom": "^17.0.2",
"@types/react-lazyload": "^3.1.0", "@types/react-lazyload": "^3.1.0",
"@types/react-router-dom": "^5.1.7", "@types/react-router-dom": "^5.1.7",
"@typescript-eslint/eslint-plugin": "4.29.3", "@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "4.29.3", "@typescript-eslint/parser": "^5.54.0",
"eslint": "^7.2.0", "eslint": "^8.35.0",
"eslint-config-airbnb": "18.2.1", "eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^14.0.0", "eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-no-relative-import-paths": "^1.5.2", "eslint-plugin-no-relative-import-paths": "^1.5.2",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.21.5", "eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^1.7.0", "eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.8.2", "prettier": "^2.8.2",
"typescript": "^4.8.4" "typescript": "^4.8.4"
} }

View File

@@ -81,9 +81,7 @@ const App: React.FC = () => (
<Route path="/downloads"> <Route path="/downloads">
<DownloadQueue /> <DownloadQueue />
</Route> </Route>
<Route path="/manga/:mangaId/chapter/:chapterNum"> <Route path="/manga/:mangaId/chapter/:chapterNum" />
<></>
</Route>
<Route path="/manga/:id"> <Route path="/manga/:id">
<Manga /> <Manga />
</Route> </Route>

View File

@@ -169,17 +169,10 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
placeItems: 'center', placeItems: 'center',
}} }}
/> />
{gridLayout === GridLayout.Comfortable ? ( {gridLayout !== GridLayout.Comfortable && (
<></>
) : (
<> <>
<BottomGradient /> <BottomGradient />
<BottomGradientDoubledDown /> <BottomGradientDoubledDown />
</>
)}
{gridLayout === GridLayout.Comfortable ? (
<></>
) : (
<MangaTitle <MangaTitle
sx={{ sx={{
color: 'white', color: 'white',
@@ -189,10 +182,11 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
> >
{truncateText(title, 61)} {truncateText(title, 61)}
</MangaTitle> </MangaTitle>
</>
)} )}
</CardActionArea> </CardActionArea>
</Card> </Card>
{gridLayout === GridLayout.Comfortable ? ( {gridLayout === GridLayout.Comfortable && (
<MangaTitle <MangaTitle
sx={{ sx={{
position: 'relative', position: 'relative',
@@ -202,8 +196,6 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
> >
{truncateText(title, 61)} {truncateText(title, 61)}
</MangaTitle> </MangaTitle>
) : (
<></>
)} )}
</Box> </Box>
</Link> </Link>

View File

@@ -15,11 +15,11 @@ interface IProps extends RadioInputProps {
sortDescending?: boolean | null | undefined; sortDescending?: boolean | null | undefined;
} }
const SortRadioInput: React.FC<IProps> = ({ sortDescending, ...rest }) => ( const SortRadioInput = React.memo(({ sortDescending, ...rest }: IProps) => (
<RadioInput <RadioInput
checkedIcon={sortDescending ? <ArrowDownward color="primary" /> : <ArrowUpward color="primary" />} checkedIcon={sortDescending ? <ArrowDownward color="primary" /> : <ArrowUpward color="primary" />}
{...rest} {...rest}
/> />
); ));
export default SortRadioInput; export default SortRadioInput;

View File

@@ -6,7 +6,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import LibraryOptionsContext, { DefaultLibraryOptions } from 'components/context/LibraryOptionsContext'; import LibraryOptionsContext, { DefaultLibraryOptions } from 'components/context/LibraryOptionsContext';
import React from 'react'; import React, { useMemo } from 'react';
import useLocalStorage from 'util/useLocalStorage'; import useLocalStorage from 'util/useLocalStorage';
import { LibraryOptions } from 'typings'; import { LibraryOptions } from 'typings';
@@ -17,7 +17,9 @@ interface IProps {
const LibraryOptionsContextProvider: React.FC<IProps> = ({ children }) => { const LibraryOptionsContextProvider: React.FC<IProps> = ({ children }) => {
const [options, setOptions] = useLocalStorage<LibraryOptions>('libraryOptions', DefaultLibraryOptions); const [options, setOptions] = useLocalStorage<LibraryOptions>('libraryOptions', DefaultLibraryOptions);
return <LibraryOptionsContext.Provider value={{ options, setOptions }}>{children}</LibraryOptionsContext.Provider>; const value = useMemo(() => ({ options, setOptions }), [options, setOptions]);
return <LibraryOptionsContext.Provider value={value}>{children}</LibraryOptionsContext.Provider>;
}; };
export default LibraryOptionsContextProvider; export default LibraryOptionsContextProvider;

View File

@@ -101,7 +101,7 @@ export default function DefaultNavBar() {
// Allow default navbar to be overrided // Allow default navbar to be overrided
if (override.status) return override.value; if (override.status) return override.value;
let navbar = <></>; let navbar: JSX.Element | null = null;
if (isMobileWidth) { if (isMobileWidth) {
if (isMainRoute) { if (isMainRoute) {
navbar = <MobileBottomBar navBarItems={navbarItems.filter((it) => it.show !== 'desktop')} />; navbar = <MobileBottomBar navBarItems={navbarItems.filter((it) => it.show !== 'desktop')} />;

View File

@@ -5,7 +5,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import React, { useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import NavBarContext from 'components/context/NavbarContext'; import NavBarContext from 'components/context/NavbarContext';
import { INavbarOverride } from 'typings'; import { INavbarOverride } from 'typings';
@@ -22,12 +22,17 @@ export default function NavBarProvider({ children }: IProps) {
value: <div />, value: <div />,
}); });
const updateTitle = (newTitle: string) => { const updateTitle = useCallback(
(newTitle: string) => {
console.log('title:', newTitle);
document.title = `${newTitle} - Tachidesk`; document.title = `${newTitle} - Tachidesk`;
setTitle(newTitle); setTitle(newTitle);
}; },
[setTitle],
);
const value = { const value = useMemo(
() => ({
defaultBackTo, defaultBackTo,
setDefaultBackTo, setDefaultBackTo,
title, title,
@@ -36,6 +41,8 @@ export default function NavBarProvider({ children }: IProps) {
setAction, setAction,
override, override,
setOverride, setOverride,
}; }),
[defaultBackTo, setDefaultBackTo, title, updateTitle, action, setAction, override, setOverride],
);
return <NavBarContext.Provider value={value}>{children}</NavBarContext.Provider>; return <NavBarContext.Provider value={value}>{children}</NavBarContext.Provider>;
} }

View File

@@ -25,7 +25,6 @@ export default function ReaderSettingsOptions({
setSettingValue, setSettingValue,
}: IProps) { }: IProps) {
return ( return (
<>
<List> <List>
<ListItem> <ListItem>
<ListItemText primary="Static Navigation" /> <ListItemText primary="Static Navigation" />
@@ -79,6 +78,5 @@ export default function ReaderSettingsOptions({
</Select> </Select>
</ListItem> </ListItem>
</List> </List>
</>
); );
} }

View File

@@ -56,7 +56,7 @@ const TextFilter: React.FC<Props> = (props) => {
</FormControl> </FormControl>
); );
} }
return <></>; return null;
}; };
export default TextFilter; export default TextFilter;

View File

@@ -47,7 +47,7 @@ const TriStateFilter: React.FC<Props> = (props) => {
/> />
); );
} }
return <></>; return null;
}; };
export default TriStateFilter; export default TriStateFilter;

View File

@@ -66,9 +66,8 @@ const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
}; };
}, [handleSearchShortcut]); }, [handleSearchShortcut]);
if (searchOpen) {
return ( return (
<>
{searchOpen ? (
<Input <Input
value={query || ''} value={query || ''}
onChange={handleChange} onChange={handleChange}
@@ -80,12 +79,13 @@ const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
</IconButton> </IconButton>
} }
/> />
) : ( );
}
return (
<IconButton onClick={openSearch}> <IconButton onClick={openSearch}>
<SearchIcon /> <SearchIcon />
</IconButton> </IconButton>
)}
</>
); );
}; };

View File

@@ -30,7 +30,7 @@ export default function LoadingPlaceholder(props: IProps) {
} }
if (children) { if (children) {
return <>{children}</>; return children as JSX.Element;
} }
} }

View File

@@ -51,7 +51,7 @@ export default function Library() {
); );
return () => { return () => {
setTitle(''); setTitle('');
setAction(<></>); setAction(null);
}; };
}, []); }, []);

View File

@@ -11,7 +11,7 @@ import NavbarContext from 'components/context/NavbarContext';
import MangaGrid from 'components/MangaGrid'; import MangaGrid from 'components/MangaGrid';
import LangSelect from 'components/navbar/action/LangSelect'; import LangSelect from 'components/navbar/action/LangSelect';
import AppbarSearch from 'components/util/AppbarSearch'; import AppbarSearch from 'components/util/AppbarSearch';
import PQueue from 'p-queue/dist/index'; import PQueue from 'p-queue';
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { StringParam, useQueryParam } from 'use-query-params'; import { StringParam, useQueryParam } from 'use-query-params';
@@ -54,11 +54,7 @@ const SearchAll: React.FC = () => {
useEffect(() => { useEffect(() => {
setTitle('Global Search'); setTitle('Global Search');
setAction( setAction(<AppbarSearch />);
<>
<AppbarSearch />
</>,
);
}, []); }, []);
useEffect(() => { useEffect(() => {
@@ -222,7 +218,8 @@ const SearchAll: React.FC = () => {
</> </>
); );
} }
return <></>;
return null;
}; };
export default SearchAll; export default SearchAll;

View File

@@ -41,7 +41,7 @@ export default function Settings() {
const { setTitle, setAction } = useContext(NavbarContext); const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { useEffect(() => {
setTitle('Settings'); setTitle('Settings');
setAction(<></>); setAction(null);
}, []); }, []);
const { darkTheme, setDarkTheme } = useContext(DarkTheme); const { darkTheme, setDarkTheme } = useContext(DarkTheme);

View File

@@ -39,7 +39,7 @@ export default function SourceConfigure() {
useEffect(() => { useEffect(() => {
setTitle('Source Configuration'); setTitle('Source Configuration');
setAction(<></>); setAction(null);
}, []); }, []);
const { sourceId } = useParams<{ sourceId: string }>(); const { sourceId } = useParams<{ sourceId: string }>();
@@ -66,7 +66,6 @@ export default function SourceConfigure() {
}; };
return ( return (
<>
<List sx={{ padding: 0 }}> <List sx={{ padding: 0 }}>
{sourcePreferences.map((it, index) => { {sourcePreferences.map((it, index) => {
const props = cloneObject(it.props); const props = cloneObject(it.props);
@@ -78,6 +77,5 @@ export default function SourceConfigure() {
return React.createElement(getPrefComponent(it.type), props); return React.createElement(getPrefComponent(it.type), props);
})} })}
</List> </List>
</>
); );
} }

View File

@@ -25,7 +25,7 @@ interface IPos {
group?: number; group?: number;
} }
export default function SourceMangas(props: { popular: boolean }) { export default function SourceMangas({ popular }: { popular: boolean }) {
const { setTitle, setAction } = useContext(NavbarContext); const { setTitle, setAction } = useContext(NavbarContext);
const history = useHistory(); const history = useHistory();
@@ -153,7 +153,7 @@ export default function SourceMangas(props: { popular: boolean }) {
); );
return () => { return () => {
setAction(<></>); setAction(null);
}; };
}, [isConfigurable]); }, [isConfigurable]);
@@ -183,7 +183,7 @@ export default function SourceMangas(props: { popular: boolean }) {
useEffect(() => { useEffect(() => {
if (lastPageNum !== 0) { if (lastPageNum !== 0) {
const sourceType = props.popular ? 'popular' : 'latest'; const sourceType = popular ? 'popular' : 'latest';
client client
.get( .get(
`/api/v1/source/${sourceId}/${ `/api/v1/source/${sourceId}/${

View File

@@ -99,7 +99,7 @@ const Updates: React.FC = () => {
useEffect(() => { useEffect(() => {
setTitle('Updates'); setTitle('Updates');
setAction(<></>); setAction(null);
}, []); }, []);
useEffect(() => { useEffect(() => {

View File

@@ -13,7 +13,7 @@ export default function About() {
useEffect(() => { useEffect(() => {
setTitle('About'); setTitle('About');
setAction(<></>); setAction(null);
}, []); }, []);
const { data: about } = useQuery<IAbout>('/api/v1/settings/about'); const { data: about } = useQuery<IAbout>('/api/v1/settings/about');

View File

@@ -19,7 +19,7 @@ export default function Backup() {
const { setTitle, setAction } = useContext(NavbarContext); const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { useEffect(() => {
setTitle('Backup'); setTitle('Backup');
setAction(<></>); setAction(null);
}, []); }, []);
const { baseURL } = client.defaults; const { baseURL } = client.defaults;

View File

@@ -52,7 +52,7 @@ export default function Categories() {
const { setTitle, setAction } = useContext(NavbarContext); const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { useEffect(() => {
setTitle('Categories'); setTitle('Categories');
setAction(<></>); setAction(null);
}, []); }, []);
const { data, mutate } = useQuery<ICategory[]>('/api/v1/category/'); const { data, mutate } = useQuery<ICategory[]>('/api/v1/category/');

View File

@@ -26,7 +26,7 @@ export default function DefaultReaderSettings() {
const { setTitle, setAction } = useContext(NavbarContext); const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { useEffect(() => {
setTitle('Default Reader Settings'); setTitle('Default Reader Settings');
setAction(<></>); setAction(null);
}, []); }, []);
const { metadata, settings, loading } = useDefaultReaderSettings(); const { metadata, settings, loading } = useDefaultReaderSettings();

11196
yarn.lock

File diff suppressed because it is too large Load Diff