[ESLint] Prefer named exports (#427)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extends: ['airbnb', 'airbnb-typescript', 'prettier'],
|
extends: ['airbnb', 'airbnb-typescript', 'prettier'],
|
||||||
plugins: ['unused-imports', '@typescript-eslint', 'no-relative-import-paths', 'prettier', 'header'],
|
plugins: ['unused-imports', 'eslint-plugin-import', '@typescript-eslint', 'no-relative-import-paths', 'prettier', 'header'],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
project: ['./tsconfig.json', './tsconfig.node.json', './tools/scripts/tsconfig.json'],
|
project: ['./tsconfig.json', './tsconfig.node.json', './tools/scripts/tsconfig.json'],
|
||||||
},
|
},
|
||||||
@@ -10,6 +10,9 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
'unused-imports/no-unused-imports': 'error',
|
'unused-imports/no-unused-imports': 'error',
|
||||||
|
|
||||||
|
'import/prefer-default-export': 'off',
|
||||||
|
'import/no-default-export': 'error',
|
||||||
|
|
||||||
'header/header': [
|
'header/header': [
|
||||||
'error',
|
'error',
|
||||||
'block', // comment type
|
'block', // comment type
|
||||||
|
|||||||
42
src/App.tsx
42
src/App.tsx
@@ -12,33 +12,33 @@ import React from 'react';
|
|||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
import { loadErrorMessages, loadDevMessages } from '@apollo/client/dev';
|
import { loadErrorMessages, loadDevMessages } from '@apollo/client/dev';
|
||||||
import { __DEV__ } from '@apollo/client/utilities/globals';
|
import { __DEV__ } from '@apollo/client/utilities/globals';
|
||||||
import AppContext from '@/components/context/AppContext';
|
import { AppContext } from '@/components/context/AppContext';
|
||||||
import Browse from '@/screens/Browse';
|
import { Browse } from '@/screens/Browse';
|
||||||
import DownloadQueue from '@/screens/DownloadQueue';
|
import { DownloadQueue } from '@/screens/DownloadQueue';
|
||||||
import Extensions from '@/screens/Extensions';
|
import { Extensions } from '@/screens/Extensions';
|
||||||
import Library from '@/screens/Library';
|
import { Library } from '@/screens/Library';
|
||||||
import Manga from '@/screens/Manga';
|
import { Manga } from '@/screens/Manga';
|
||||||
import Reader from '@/screens/Reader';
|
import { Reader } from '@/screens/Reader';
|
||||||
import SearchAll from '@/screens/SearchAll';
|
import { SearchAll } from '@/screens/SearchAll';
|
||||||
import Settings from '@/screens/Settings';
|
import { Settings } from '@/screens/Settings';
|
||||||
import About from '@/screens/settings/About';
|
import { About } from '@/screens/settings/About';
|
||||||
import Backup from '@/screens/settings/Backup';
|
import { Backup } from '@/screens/settings/Backup';
|
||||||
import Categories from '@/screens/settings/Categories';
|
import { Categories } from '@/screens/settings/Categories';
|
||||||
import DefaultReaderSettings from '@/screens/settings/DefaultReaderSettings';
|
import { DefaultReaderSettings } from '@/screens/settings/DefaultReaderSettings';
|
||||||
import SourceConfigure from '@/screens/SourceConfigure';
|
import { SourceConfigure } from '@/screens/SourceConfigure';
|
||||||
import SourceMangas from '@/screens/SourceMangas';
|
import { SourceMangas } from '@/screens/SourceMangas';
|
||||||
import Sources from '@/screens/Sources';
|
import { Sources } from '@/screens/Sources';
|
||||||
import Updates from '@/screens/Updates';
|
import { Updates } from '@/screens/Updates';
|
||||||
import '@/i18n';
|
import '@/i18n';
|
||||||
import LibrarySettings from '@/screens/settings/LibrarySettings';
|
import { LibrarySettings } from '@/screens/settings/LibrarySettings';
|
||||||
import DefaultNavBar from '@/components/navbar/DefaultNavBar';
|
import { DefaultNavBar } from '@/components/navbar/DefaultNavBar';
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
// Adds messages only in a dev environment
|
// Adds messages only in a dev environment
|
||||||
loadDevMessages();
|
loadDevMessages();
|
||||||
loadErrorMessages();
|
loadErrorMessages();
|
||||||
}
|
}
|
||||||
const App: React.FC = () => (
|
export const App: React.FC = () => (
|
||||||
<AppContext>
|
<AppContext>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<DefaultNavBar />
|
<DefaultNavBar />
|
||||||
@@ -91,5 +91,3 @@ const App: React.FC = () => (
|
|||||||
</Routes>
|
</Routes>
|
||||||
</AppContext>
|
</AppContext>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PartialExtension, TranslationKey } from '@/typings';
|
import { PartialExtension, TranslationKey } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
extension: PartialExtension;
|
extension: PartialExtension;
|
||||||
@@ -60,7 +60,7 @@ const INSTALLED_STATE_TO_TRANSLATION_KEY_MAP: { [installedState in InstalledStat
|
|||||||
[InstalledState.INSTALLING]: 'extension.state.label.installing',
|
[InstalledState.INSTALLING]: 'extension.state.label.installing',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default function ExtensionCard(props: IProps) {
|
export function ExtensionCard(props: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Avatar, Box, CardContent, styled } from '@mui/material';
|
import { Avatar, Box, CardContent, styled } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
import SpinnerImage from '@/components/util/SpinnerImage';
|
import { SpinnerImage } from '@/components/util/SpinnerImage';
|
||||||
import { TPartialManga } from '@/typings.ts';
|
import { TPartialManga } from '@/typings.ts';
|
||||||
|
|
||||||
const BottomGradient = styled('div')({
|
const BottomGradient = styled('div')({
|
||||||
@@ -71,7 +71,7 @@ interface IProps {
|
|||||||
inLibraryIndicator?: boolean;
|
inLibraryIndicator?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MangaCard = (props: IProps) => {
|
export const MangaCard = (props: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -259,5 +259,3 @@ const MangaCard = (props: IProps) => {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MangaCard;
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import Grid, { GridTypeMap } from '@mui/material/Grid';
|
|||||||
import { Box, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import { GridItemProps, VirtuosoGrid, VirtuosoGridHandle } from 'react-virtuoso';
|
import { GridItemProps, VirtuosoGrid, VirtuosoGridHandle } from 'react-virtuoso';
|
||||||
import { useNavigate, useLocation } from 'react-router-dom';
|
import { useNavigate, useLocation } from 'react-router-dom';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import { EmptyView } from '@/components/util/EmptyView';
|
||||||
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
||||||
import MangaCard from '@/components/MangaCard';
|
import { MangaCard } from '@/components/MangaCard';
|
||||||
import { GridLayout } from '@/components/context/LibraryOptionsContext';
|
import { GridLayout } from '@/components/context/LibraryOptionsContext';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import { TPartialManga } from '@/typings.ts';
|
import { TPartialManga } from '@/typings.ts';
|
||||||
|
|
||||||
const GridContainer = React.forwardRef<HTMLDivElement, GridTypeMap['props']>(({ children, ...props }, ref) => (
|
const GridContainer = React.forwardRef<HTMLDivElement, GridTypeMap['props']>(({ children, ...props }, ref) => (
|
||||||
@@ -162,7 +162,7 @@ export interface IMangaGridProps {
|
|||||||
inLibraryIndicator?: boolean;
|
inLibraryIndicator?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MangaGrid: React.FC<IMangaGridProps> = (props) => {
|
export const MangaGrid: React.FC<IMangaGridProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
mangas,
|
mangas,
|
||||||
isLoading,
|
isLoading,
|
||||||
@@ -256,5 +256,3 @@ MangaGrid.defaultProps = {
|
|||||||
message: '',
|
message: '',
|
||||||
messageExtra: undefined,
|
messageExtra: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MangaGrid;
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { ISource } from '@/typings';
|
import { ISource } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
||||||
import { SourceContentType } from '@/screens/SourceMangas';
|
import { SourceContentType } from '@/screens/SourceMangas';
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ interface IProps {
|
|||||||
source: ISource;
|
source: ISource;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SourceCard: React.FC<IProps> = (props: IProps) => {
|
export const SourceCard: React.FC<IProps> = (props: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -137,5 +137,3 @@ const SourceCard: React.FC<IProps> = (props: IProps) => {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SourceCard;
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ interface IProps extends CheckboxProps {
|
|||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
|
export const CheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
|
||||||
<FormControlLabel control={<Checkbox {...rest} />} label={label} sx={sx} />
|
<FormControlLabel control={<Checkbox {...rest} />} label={label} sx={sx} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default CheckboxInput;
|
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* 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/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { CircularProgress, IconButton, IconButtonProps } from '@mui/material';
|
|
||||||
import React, { useState } from 'react';
|
|
||||||
|
|
||||||
interface IProps extends Omit<IconButtonProps, 'onClick'> {
|
|
||||||
loading?: boolean;
|
|
||||||
onClick: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => Promise<any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadingIconButton = ({ onClick, children, loading: iLoading, ...rest }: IProps) => {
|
|
||||||
const [sLoading, setLoading] = useState(false);
|
|
||||||
const loading = sLoading || iLoading;
|
|
||||||
|
|
||||||
const handleClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
||||||
setLoading(true);
|
|
||||||
onClick(e).finally(() => setLoading(false));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IconButton disabled={loading} {...rest} onClick={handleClick}>
|
|
||||||
{loading ? <CircularProgress size={24} /> : children}
|
|
||||||
</IconButton>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
LoadingIconButton.defaultProps = {
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LoadingIconButton;
|
|
||||||
@@ -13,8 +13,6 @@ export interface RadioInputProps extends RadioProps {
|
|||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RadioInput: React.FC<RadioInputProps> = ({ label, sx, ...rest }) => (
|
export const RadioInput: React.FC<RadioInputProps> = ({ label, sx, ...rest }) => (
|
||||||
<FormControlLabel control={<Radio {...rest} />} label={label} sx={sx} />
|
<FormControlLabel control={<Radio {...rest} />} label={label} sx={sx} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default RadioInput;
|
|
||||||
|
|||||||
@@ -9,17 +9,15 @@
|
|||||||
import ArrowDownward from '@mui/icons-material/ArrowDownward';
|
import ArrowDownward from '@mui/icons-material/ArrowDownward';
|
||||||
import ArrowUpward from '@mui/icons-material/ArrowUpward';
|
import ArrowUpward from '@mui/icons-material/ArrowUpward';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import RadioInput, { RadioInputProps } from '@/components/atoms/RadioInput';
|
import { RadioInput, RadioInputProps } from '@/components/atoms/RadioInput';
|
||||||
|
|
||||||
interface IProps extends RadioInputProps {
|
interface IProps extends RadioInputProps {
|
||||||
sortDescending?: boolean | null | undefined;
|
sortDescending?: boolean | null | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortRadioInput = memo(({ sortDescending, ...rest }: IProps) => (
|
export const SortRadioInput = 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;
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export interface ThreeStateCheckboxProps extends Omit<CheckboxProps, 'checked' |
|
|||||||
* When checked is false, checkbox contains cross
|
* When checked is false, checkbox contains cross
|
||||||
* When checked is null or undefined, checkbox is empty
|
* When checked is null or undefined, checkbox is empty
|
||||||
*/
|
*/
|
||||||
const ThreeStateCheckbox: React.FC<ThreeStateCheckboxProps> = ({ checked, onChange, ...rest }) => {
|
export const ThreeStateCheckbox: React.FC<ThreeStateCheckboxProps> = ({ checked, onChange, ...rest }) => {
|
||||||
const handleChange = useCallback(() => {
|
const handleChange = useCallback(() => {
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
const newState = nextState(checked);
|
const newState = nextState(checked);
|
||||||
@@ -46,4 +46,3 @@ const ThreeStateCheckbox: React.FC<ThreeStateCheckboxProps> = ({ checked, onChan
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default ThreeStateCheckbox;
|
|
||||||
|
|||||||
@@ -8,14 +8,12 @@
|
|||||||
|
|
||||||
import { FormControlLabel } from '@mui/material';
|
import { FormControlLabel } from '@mui/material';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ThreeStateCheckbox, { ThreeStateCheckboxProps } from '@/components/atoms/ThreeStateCheckbox';
|
import { ThreeStateCheckbox, ThreeStateCheckboxProps } from '@/components/atoms/ThreeStateCheckbox';
|
||||||
|
|
||||||
interface IProps extends ThreeStateCheckboxProps {
|
interface IProps extends ThreeStateCheckboxProps {
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ThreeStateCheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
|
export const ThreeStateCheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
|
||||||
<FormControlLabel control={<ThreeStateCheckbox {...rest} />} label={label} sx={sx} />
|
<FormControlLabel control={<ThreeStateCheckbox {...rest} />} label={label} sx={sx} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default ThreeStateCheckboxInput;
|
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ import React, { useMemo } from 'react';
|
|||||||
import { BrowserRouter as Router } from 'react-router-dom';
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
import { QueryParamProvider } from 'use-query-params';
|
import { QueryParamProvider } from 'use-query-params';
|
||||||
import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6';
|
import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6';
|
||||||
import createTheme from '@/theme';
|
import { createTheme } from '@/theme';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import DarkTheme from '@/components/context/DarkTheme';
|
import { DarkTheme } from '@/components/context/DarkTheme';
|
||||||
import NavBarContextProvider from '@/components/navbar/NavBarContextProvider';
|
import { NavBarContextProvider } from '@/components/navbar/NavBarContextProvider';
|
||||||
import LibraryOptionsContextProvider from '@/components/library/LibraryOptionsProvider';
|
import { LibraryOptionsContextProvider } from '@/components/library/LibraryOptionsProvider';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppContext: React.FC<Props> = ({ children }) => {
|
export const AppContext: React.FC<Props> = ({ children }) => {
|
||||||
const [darkTheme, setDarkTheme] = useLocalStorage<boolean>('darkTheme', true);
|
const [darkTheme, setDarkTheme] = useLocalStorage<boolean>('darkTheme', true);
|
||||||
|
|
||||||
const darkThemeContext = useMemo(
|
const darkThemeContext = useMemo(
|
||||||
@@ -50,5 +50,3 @@ const AppContext: React.FC<Props> = ({ children }) => {
|
|||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppContext;
|
|
||||||
|
|||||||
@@ -13,9 +13,7 @@ type ContextType = {
|
|||||||
setDarkTheme: React.Dispatch<React.SetStateAction<boolean>>;
|
setDarkTheme: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DarkTheme = React.createContext<ContextType>({
|
export const DarkTheme = React.createContext<ContextType>({
|
||||||
darkTheme: true,
|
darkTheme: true,
|
||||||
setDarkTheme: (): void => {},
|
setDarkTheme: (): void => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default DarkTheme;
|
|
||||||
|
|||||||
@@ -34,13 +34,11 @@ export const DefaultLibraryOptions: LibraryOptions = {
|
|||||||
showTabSize: false,
|
showTabSize: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const LibraryOptionsContext = React.createContext<ContextType>({
|
export const LibraryOptionsContext = React.createContext<ContextType>({
|
||||||
options: DefaultLibraryOptions,
|
options: DefaultLibraryOptions,
|
||||||
setOptions: () => {},
|
setOptions: () => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LibraryOptionsContext;
|
|
||||||
|
|
||||||
export function useLibraryOptionsContext() {
|
export function useLibraryOptionsContext() {
|
||||||
return useContext(LibraryOptionsContext);
|
return useContext(LibraryOptionsContext);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ type ContextType = {
|
|||||||
setOverride: React.Dispatch<React.SetStateAction<INavbarOverride>>;
|
setOverride: React.Dispatch<React.SetStateAction<INavbarOverride>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NavBarContext = React.createContext<ContextType>({
|
export const NavBarContext = React.createContext<ContextType>({
|
||||||
defaultBackTo: undefined,
|
defaultBackTo: undefined,
|
||||||
setDefaultBackTo: (): void => {},
|
setDefaultBackTo: (): void => {},
|
||||||
title: 'Tachidesk',
|
title: 'Tachidesk',
|
||||||
@@ -38,8 +38,6 @@ const NavBarContext = React.createContext<ContextType>({
|
|||||||
setOverride: (): void => {},
|
setOverride: (): void => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default NavBarContext;
|
|
||||||
|
|
||||||
export const useNavBarContext = () => useContext(NavBarContext);
|
export const useNavBarContext = () => useContext(NavBarContext);
|
||||||
|
|
||||||
export const useSetDefaultBackTo = (value: string) => {
|
export const useSetDefaultBackTo = (value: string) => {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const CheckboxContainer = styled('div')({
|
export const CheckboxContainer = styled('div')({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { GlobalUpdateSettingsCategories } from '@/components/globalUpdate/GlobalUpdateSettingsCategories.tsx';
|
import { GlobalUpdateSettingsCategories } from '@/components/globalUpdate/GlobalUpdateSettingsCategories.tsx';
|
||||||
import { GlobalUpdateSettingsEntries } from '@/components/globalUpdate/GlobalUpdateSettingsEntries.tsx';
|
import { GlobalUpdateSettingsEntries } from '@/components/globalUpdate/GlobalUpdateSettingsEntries.tsx';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GlobalUpdateSettings = () => {
|
export const GlobalUpdateSettings = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ import DialogContentText from '@mui/material/DialogContentText';
|
|||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import { t as translate } from 'i18next';
|
import { t as translate } from 'i18next';
|
||||||
import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput.tsx';
|
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput.tsx';
|
||||||
import makeToast from '@/components/util/Toast.tsx';
|
import { makeToast } from '@/components/util/Toast.tsx';
|
||||||
import { IncludeInUpdate } from '@/lib/graphql/generated/graphql.ts';
|
import { IncludeInUpdate } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { TCategory } from '@/typings.ts';
|
import { TCategory } from '@/typings.ts';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { CheckboxContainer } from '@/components/globalUpdate/CheckboxContainer.ts';
|
import { CheckboxContainer } from '@/components/globalUpdate/CheckboxContainer.ts';
|
||||||
|
|
||||||
const booleanToIncludeInStatus = (status: boolean | null | undefined): IncludeInUpdate => {
|
const booleanToIncludeInStatus = (status: boolean | null | undefined): IncludeInUpdate => {
|
||||||
@@ -78,7 +78,6 @@ const getCategoryUpdateInfo = (
|
|||||||
return categories.map((category) => category.name).join(', ');
|
return categories.map((category) => category.name).join(', ');
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GlobalUpdateSettingsCategories = () => {
|
export const GlobalUpdateSettingsCategories = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import ListItemText from '@mui/material/ListItemText';
|
|||||||
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
||||||
import { GetServerSettingsQuery } from '@/lib/graphql/generated/graphql.ts';
|
import { GetServerSettingsQuery } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { TranslationKey } from '@/typings.ts';
|
import { TranslationKey } from '@/typings.ts';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import makeToast from '@/components/util/Toast.tsx';
|
import { makeToast } from '@/components/util/Toast.tsx';
|
||||||
import { CheckboxContainer } from '@/components/globalUpdate/CheckboxContainer';
|
import { CheckboxContainer } from '@/components/globalUpdate/CheckboxContainer';
|
||||||
import CheckboxInput from '@/components/atoms/CheckboxInput';
|
import { CheckboxInput } from '@/components/atoms/CheckboxInput';
|
||||||
|
|
||||||
type GlobalUpdateSkipEntriesSettings = Pick<
|
type GlobalUpdateSkipEntriesSettings = Pick<
|
||||||
GetServerSettingsQuery['settings'],
|
GetServerSettingsQuery['settings'],
|
||||||
@@ -69,7 +69,6 @@ const extractSkipEntriesSettings = (
|
|||||||
excludeUnreadChapters: serverSettings.excludeUnreadChapters,
|
excludeUnreadChapters: serverSettings.excludeUnreadChapters,
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GlobalUpdateSettingsEntries = () => {
|
export const GlobalUpdateSettingsEntries = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { data, loading, error: requestError } = requestManager.useGetServerSettings();
|
const { data, loading, error: requestError } = requestManager.useGetServerSettings();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { LibrarySortMode, NullAndUndefined, TManga } from '@/typings';
|
import { LibrarySortMode, NullAndUndefined, TManga } from '@/typings';
|
||||||
import { useSearchSettings } from '@/util/searchSettings';
|
import { useSearchSettings } from '@/util/searchSettings';
|
||||||
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
import MangaGrid from '@/components/MangaGrid';
|
import { MangaGrid } from '@/components/MangaGrid';
|
||||||
|
|
||||||
const unreadFilter = (unread: NullAndUndefined<boolean>, { unreadCount }: TManga): boolean => {
|
const unreadFilter = (unread: NullAndUndefined<boolean>, { unreadCount }: TManga): boolean => {
|
||||||
switch (unread) {
|
switch (unread) {
|
||||||
@@ -109,7 +109,7 @@ interface LibraryMangaGridProps {
|
|||||||
message?: string;
|
message?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LibraryMangaGrid: React.FC<LibraryMangaGridProps> = ({ mangas, isLoading, message }) => {
|
export const LibraryMangaGrid: React.FC<LibraryMangaGridProps> = ({ mangas, isLoading, message }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [query] = useQueryParam('query', StringParam);
|
const [query] = useQueryParam('query', StringParam);
|
||||||
@@ -144,5 +144,3 @@ const LibraryMangaGrid: React.FC<LibraryMangaGridProps> = ({ mangas, isLoading,
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LibraryMangaGrid;
|
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import { FormLabel, RadioGroup } from '@mui/material';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { LibraryOptions, LibrarySortMode, TranslationKey } from '@/typings';
|
import { LibraryOptions, LibrarySortMode, TranslationKey } from '@/typings';
|
||||||
import CheckboxInput from '@/components/atoms/CheckboxInput';
|
import { CheckboxInput } from '@/components/atoms/CheckboxInput';
|
||||||
import RadioInput from '@/components/atoms/RadioInput';
|
import { RadioInput } from '@/components/atoms/RadioInput';
|
||||||
import SortRadioInput from '@/components/atoms/SortRadioInput';
|
import { SortRadioInput } from '@/components/atoms/SortRadioInput';
|
||||||
import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput';
|
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput';
|
||||||
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
import OptionsTabs from '@/components/molecules/OptionsTabs';
|
import { OptionsTabs } from '@/components/molecules/OptionsTabs';
|
||||||
|
|
||||||
const TITLES: { [key in 'filter' | 'sort' | 'display']: TranslationKey } = {
|
const TITLES: { [key in 'filter' | 'sort' | 'display']: TranslationKey } = {
|
||||||
filter: 'global.label.filter',
|
filter: 'global.label.filter',
|
||||||
@@ -35,7 +35,7 @@ interface IProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { options, setOptions } = useLibraryOptionsContext();
|
const { options, setOptions } = useLibraryOptionsContext();
|
||||||
|
|
||||||
@@ -133,5 +133,3 @@ const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LibraryOptionsPanel;
|
|
||||||
|
|||||||
@@ -8,19 +8,17 @@
|
|||||||
|
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { LibraryOptions } from '@/typings';
|
import { LibraryOptions } from '@/typings';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import LibraryOptionsContext, { DefaultLibraryOptions } from '@/components/context/LibraryOptionsContext';
|
import { LibraryOptionsContext, DefaultLibraryOptions } from '@/components/context/LibraryOptionsContext';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LibraryOptionsContextProvider: React.FC<IProps> = ({ children }) => {
|
export const LibraryOptionsContextProvider: React.FC<IProps> = ({ children }) => {
|
||||||
const [options, setOptions] = useLocalStorage<LibraryOptions>('libraryOptions', DefaultLibraryOptions);
|
const [options, setOptions] = useLocalStorage<LibraryOptions>('libraryOptions', DefaultLibraryOptions);
|
||||||
|
|
||||||
const value = useMemo(() => ({ options, setOptions }), [options, setOptions]);
|
const value = useMemo(() => ({ options, setOptions }), [options, setOptions]);
|
||||||
|
|
||||||
return <LibraryOptionsContext.Provider value={value}>{children}</LibraryOptionsContext.Provider>;
|
return <LibraryOptionsContext.Provider value={value}>{children}</LibraryOptionsContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LibraryOptionsContextProvider;
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import FilterList from '@mui/icons-material/FilterList';
|
|||||||
import { IconButton } from '@mui/material';
|
import { IconButton } from '@mui/material';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
import LibraryOptionsPanel from '@/components/library/LibraryOptionsPanel';
|
import { LibraryOptionsPanel } from '@/components/library/LibraryOptionsPanel';
|
||||||
|
|
||||||
const LibraryToolbarMenu: React.FC = () => {
|
export const LibraryToolbarMenu: React.FC = () => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { options } = useLibraryOptionsContext();
|
const { options } = useLibraryOptionsContext();
|
||||||
const active = options.downloaded != null || options.unread != null;
|
const active = options.downloaded != null || options.unread != null;
|
||||||
@@ -26,5 +26,3 @@ const LibraryToolbarMenu: React.FC = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LibraryToolbarMenu;
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import CircularProgress from '@mui/material/CircularProgress';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import makeToast from '@/components/util/Toast';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
import { UpdaterSubscription } from '@/lib/graphql/generated/graphql.ts';
|
import { UpdaterSubscription } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
interface IProgressProps {
|
interface IProgressProps {
|
||||||
@@ -45,7 +45,7 @@ const calcProgress = (status: UpdaterSubscription['updateStatusChanged'] | undef
|
|||||||
return Number.isNaN(progress) ? 0 : progress;
|
return Number.isNaN(progress) ? 0 : progress;
|
||||||
};
|
};
|
||||||
|
|
||||||
function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: () => void }) {
|
export function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: () => void }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { data: updaterData } = requestManager.useUpdaterSubscription();
|
const { data: updaterData } = requestManager.useUpdaterSubscription();
|
||||||
@@ -81,5 +81,3 @@ function UpdateChecker({ handleFinishedUpdate }: { handleFinishedUpdate: () => v
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UpdateChecker;
|
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { getUploadDateString } from '@/util/date';
|
import { getUploadDateString } from '@/util/date';
|
||||||
import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator';
|
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
||||||
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { TChapter } from '@/typings.ts';
|
import { TChapter } from '@/typings.ts';
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ interface IProps {
|
|||||||
selected: boolean | null;
|
selected: boolean | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
export const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@@ -212,5 +212,3 @@ const ChapterCard: React.FC<IProps> = (props: IProps) => {
|
|||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChapterCard;
|
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ import React, { ComponentProps, useEffect, useMemo, useRef, useState } from 'rea
|
|||||||
import { Virtuoso } from 'react-virtuoso';
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { TChapter, TManga, TranslationKey } from '@/typings';
|
import { TChapter, TManga, TranslationKey } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import ChapterCard from '@/components/manga/ChapterCard';
|
import { ChapterCard } from '@/components/manga/ChapterCard';
|
||||||
import ResumeFab from '@/components/manga/ResumeFAB';
|
import { ResumeFab } from '@/components/manga/ResumeFAB';
|
||||||
import { filterAndSortChapters, useChapterOptions } from '@/components/manga/util';
|
import { filterAndSortChapters, useChapterOptions } from '@/components/manga/util';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import { EmptyView } from '@/components/util/EmptyView';
|
||||||
import makeToast from '@/components/util/Toast';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
import ChaptersToolbarMenu from '@/components/manga/ChaptersToolbarMenu';
|
import { ChaptersToolbarMenu } from '@/components/manga/ChaptersToolbarMenu';
|
||||||
import SelectionFAB from '@/components/manga/SelectionFAB';
|
import { SelectionFAB } from '@/components/manga/SelectionFAB';
|
||||||
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
|
import { DEFAULT_FULL_FAB_HEIGHT } from '@/components/util/StyledFab';
|
||||||
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
import { DownloadType, UpdateChapterPatchInput } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ interface IProps {
|
|||||||
isRefreshing: boolean;
|
isRefreshing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
export const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [selection, setSelection] = useState<number[] | null>(null);
|
const [selection, setSelection] = useState<number[] | null>(null);
|
||||||
@@ -299,5 +299,3 @@ const ChapterList: React.FC<IProps> = ({ manga, isRefreshing }) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChapterList;
|
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import { RadioGroup } from '@mui/material';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ChapterListOptions, ChapterOptionsReducerAction, TranslationKey } from '@/typings';
|
import { ChapterListOptions, ChapterOptionsReducerAction, TranslationKey } from '@/typings';
|
||||||
import RadioInput from '@/components/atoms/RadioInput';
|
import { RadioInput } from '@/components/atoms/RadioInput';
|
||||||
import SortRadioInput from '@/components/atoms/SortRadioInput';
|
import { SortRadioInput } from '@/components/atoms/SortRadioInput';
|
||||||
import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput';
|
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput';
|
||||||
import OptionsTabs from '@/components/molecules/OptionsTabs';
|
import { OptionsTabs } from '@/components/molecules/OptionsTabs';
|
||||||
import { SORT_OPTIONS } from '@/components/manga/util';
|
import { SORT_OPTIONS } from '@/components/manga/util';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@@ -29,7 +29,7 @@ const TITLES: { [key in 'filter' | 'sort' | 'display']: TranslationKey } = {
|
|||||||
display: 'global.label.display',
|
display: 'global.label.display',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ChapterOptions: React.FC<IProps> = ({ open, onClose, options, optionsDispatch }) => {
|
export const ChapterOptions: React.FC<IProps> = ({ open, onClose, options, optionsDispatch }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -110,5 +110,3 @@ const ChapterOptions: React.FC<IProps> = ({ open, onClose, options, optionsDispa
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChapterOptions;
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import FilterList from '@mui/icons-material/FilterList';
|
|||||||
import { IconButton } from '@mui/material';
|
import { IconButton } from '@mui/material';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ChapterListOptions, ChapterOptionsReducerAction } from '@/typings';
|
import { ChapterListOptions, ChapterOptionsReducerAction } from '@/typings';
|
||||||
import ChapterOptions from '@/components/manga/ChapterOptions';
|
import { ChapterOptions } from '@/components/manga/ChapterOptions';
|
||||||
import { isFilterActive } from '@/components/manga/util';
|
import { isFilterActive } from '@/components/manga/util';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@@ -18,7 +18,7 @@ interface IProps {
|
|||||||
optionsDispatch: React.Dispatch<ChapterOptionsReducerAction>;
|
optionsDispatch: React.Dispatch<ChapterOptionsReducerAction>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChaptersToolbarMenu = ({ options, optionsDispatch }: IProps) => {
|
export const ChaptersToolbarMenu = ({ options, optionsDispatch }: IProps) => {
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const isFiltered = isFilterActive(options);
|
const isFiltered = isFilterActive(options);
|
||||||
|
|
||||||
@@ -36,5 +36,3 @@ const ChaptersToolbarMenu = ({ options, optionsDispatch }: IProps) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ChaptersToolbarMenu;
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { t as translate } from 'i18next';
|
import { t as translate } from 'i18next';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import { ISource, TManga } from '@/typings';
|
import { ISource, TManga } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import makeToast from '@/components/util/Toast';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
|
|
||||||
const DetailsWrapper = styled('div')(({ theme }) => ({
|
const DetailsWrapper = styled('div')(({ theme }) => ({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@@ -165,7 +165,7 @@ function getValueOrUnknown(val?: string | null) {
|
|||||||
return val || 'UNKNOWN';
|
return val || 'UNKNOWN';
|
||||||
}
|
}
|
||||||
|
|
||||||
const MangaDetails: React.FC<IProps> = ({ manga }) => {
|
export const MangaDetails: React.FC<IProps> = ({ manga }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { data: categoriesData, loading: areCategoriesLoading } = requestManager.useGetCategories();
|
const { data: categoriesData, loading: areCategoriesLoading } = requestManager.useGetCategories();
|
||||||
const categories = categoriesData?.categories.nodes ?? [];
|
const categories = categoriesData?.categories.nodes ?? [];
|
||||||
@@ -250,5 +250,3 @@ const MangaDetails: React.FC<IProps> = ({ manga }) => {
|
|||||||
</DetailsWrapper>
|
</DetailsWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MangaDetails;
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import CategorySelect from '@/components/navbar/action/CategorySelect';
|
import { CategorySelect } from '@/components/navbar/action/CategorySelect';
|
||||||
import { TManga } from '@/typings.ts';
|
import { TManga } from '@/typings.ts';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@@ -30,7 +30,7 @@ interface IProps {
|
|||||||
refreshing: boolean;
|
refreshing: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MangaToolbarMenu = ({ manga, onRefresh, refreshing }: IProps) => {
|
export const MangaToolbarMenu = ({ manga, onRefresh, refreshing }: IProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isLargeScreen = useMediaQuery(theme.breakpoints.up('sm'));
|
const isLargeScreen = useMediaQuery(theme.breakpoints.up('sm'));
|
||||||
@@ -123,5 +123,3 @@ const MangaToolbarMenu = ({ manga, onRefresh, refreshing }: IProps) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MangaToolbarMenu;
|
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { PlayArrow } from '@mui/icons-material';
|
import { PlayArrow } from '@mui/icons-material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import StyledFab from '@/components/util/StyledFab';
|
import { StyledFab } from '@/components/util/StyledFab';
|
||||||
|
|
||||||
interface ResumeFABProps {
|
interface ResumeFABProps {
|
||||||
chapterIndex: number;
|
chapterIndex: number;
|
||||||
mangaId: number;
|
mangaId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ResumeFab(props: ResumeFABProps) {
|
export function ResumeFab(props: ResumeFABProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { chapterIndex, mangaId } = props;
|
const { chapterIndex, mangaId } = props;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Fab, Menu, Box } from '@mui/material';
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { IChapterWithMeta } from '@/components/manga/ChapterList';
|
import type { IChapterWithMeta } from '@/components/manga/ChapterList';
|
||||||
import SelectionFABActionItem from '@/components/manga/SelectionFABActionItem';
|
import { SelectionFABActionItem } from '@/components/manga/SelectionFABActionItem';
|
||||||
import { DEFAULT_FAB_STYLE } from '@/components/util/StyledFab';
|
import { DEFAULT_FAB_STYLE } from '@/components/util/StyledFab';
|
||||||
|
|
||||||
export type SelectionAction = 'download' | 'delete' | 'bookmark' | 'unbookmark' | 'mark_as_read' | 'mark_as_unread';
|
export type SelectionAction = 'download' | 'delete' | 'bookmark' | 'unbookmark' | 'mark_as_read' | 'mark_as_unread';
|
||||||
@@ -21,7 +21,7 @@ interface SelectionFABProps {
|
|||||||
onAction: (action: SelectionAction, chapters: IChapterWithMeta[]) => void;
|
onAction: (action: SelectionAction, chapters: IChapterWithMeta[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectionFAB: React.FC<SelectionFABProps> = (props) => {
|
export const SelectionFAB: React.FC<SelectionFABProps> = (props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { selectedChapters, onAction } = props;
|
const { selectedChapters, onAction } = props;
|
||||||
@@ -102,5 +102,3 @@ const SelectionFAB: React.FC<SelectionFABProps> = (props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SelectionFAB;
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const ICONS = {
|
|||||||
mark_as_unread: RemoveDone,
|
mark_as_unread: RemoveDone,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SelectionFABActionItem: React.FC<IProps> = ({ action, matchingChapters, onClick, title }) => {
|
export const SelectionFABActionItem: React.FC<IProps> = ({ action, matchingChapters, onClick, title }) => {
|
||||||
const count = matchingChapters.length;
|
const count = matchingChapters.length;
|
||||||
const Icon = ICONS[action];
|
const Icon = ICONS[action];
|
||||||
return (
|
return (
|
||||||
@@ -48,5 +48,3 @@ const SelectionFABActionItem: React.FC<IProps> = ({ action, matchingChapters, on
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SelectionFABActionItem;
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
|
|
||||||
export const useRefreshManga = (mangaId: string) => {
|
export const useRefreshManga = (mangaId: string) => {
|
||||||
const [fetchingOnline, setFetchingOnline] = useState(false);
|
const [fetchingOnline, setFetchingOnline] = useState(false);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const DOWNLOAD_STATE_TO_TRANSLATION_KEY_MAP: { [state in DownloadState]: Transla
|
|||||||
QUEUED: 'download.state.label.queued',
|
QUEUED: 'download.state.label.queued',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const DownloadStateIndicator: React.FC<DownloadStateIndicatorProps> = ({ download }) => {
|
export const DownloadStateIndicator: React.FC<DownloadStateIndicatorProps> = ({ download }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -59,5 +59,3 @@ const DownloadStateIndicator: React.FC<DownloadStateIndicatorProps> = ({ downloa
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DownloadStateIndicator;
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface IProps {
|
|||||||
minHeight?: number;
|
minHeight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OptionsPanel: React.FC<IProps> = ({ open, onClose, children, minHeight }) => (
|
export const OptionsPanel: React.FC<IProps> = ({ open, onClose, children, minHeight }) => (
|
||||||
<Drawer
|
<Drawer
|
||||||
anchor="bottom"
|
anchor="bottom"
|
||||||
open={open}
|
open={open}
|
||||||
@@ -37,5 +37,3 @@ const OptionsPanel: React.FC<IProps> = ({ open, onClose, children, minHeight })
|
|||||||
OptionsPanel.defaultProps = {
|
OptionsPanel.defaultProps = {
|
||||||
minHeight: undefined,
|
minHeight: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OptionsPanel;
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
import { Stack, Tab, Tabs } from '@mui/material';
|
import { Stack, Tab, Tabs } from '@mui/material';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import TabPanel from '@/components/util/TabPanel';
|
import { TabPanel } from '@/components/util/TabPanel';
|
||||||
import OptionsPanel from '@/components/molecules/OptionsPanel';
|
import { OptionsPanel } from '@/components/molecules/OptionsPanel';
|
||||||
|
|
||||||
interface IProps<T = string> {
|
interface IProps<T = string> {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -20,7 +20,7 @@ interface IProps<T = string> {
|
|||||||
minHeight?: number;
|
minHeight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OptionsTabs = <T extends string = string>({
|
export const OptionsTabs = <T extends string = string>({
|
||||||
open,
|
open,
|
||||||
onClose,
|
onClose,
|
||||||
tabs,
|
tabs,
|
||||||
@@ -55,5 +55,3 @@ const OptionsTabs = <T extends string = string>({
|
|||||||
OptionsTabs.defaultProps = {
|
OptionsTabs.defaultProps = {
|
||||||
minHeight: undefined,
|
minHeight: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OptionsTabs;
|
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ import ArrowBack from '@mui/icons-material/ArrowBack';
|
|||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { NavbarItem } from '@/typings';
|
import { NavbarItem } from '@/typings';
|
||||||
import NavBarContext from '@/components/context/NavbarContext';
|
import { NavBarContext } from '@/components/context/NavbarContext';
|
||||||
import ExtensionOutlinedIcon from '@/components/util/CustomExtensionOutlinedIcon';
|
import { ExtensionOutlinedIcon } from '@/components/util/CustomExtensionOutlinedIcon';
|
||||||
import DesktopSideBar from '@/components/navbar/navigation/DesktopSideBar';
|
import { DesktopSideBar } from '@/components/navbar/navigation/DesktopSideBar';
|
||||||
import MobileBottomBar from '@/components/navbar/navigation/MobileBottomBar';
|
import { MobileBottomBar } from '@/components/navbar/navigation/MobileBottomBar';
|
||||||
import { useHistory } from '@/util/useHistory';
|
import { useHistory } from '@/util/useHistory';
|
||||||
|
|
||||||
const navbarItems: Array<NavbarItem> = [
|
const navbarItems: Array<NavbarItem> = [
|
||||||
@@ -85,7 +85,7 @@ const navbarItems: Array<NavbarItem> = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function DefaultNavBar() {
|
export function DefaultNavBar() {
|
||||||
const { title, action, override, defaultBackTo: backToUrl } = useContext(NavBarContext);
|
const { title, action, override, defaultBackTo: backToUrl } = useContext(NavBarContext);
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
|
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { INavbarOverride } from '@/typings';
|
import { INavbarOverride } from '@/typings';
|
||||||
import NavBarContext from '@/components/context/NavbarContext';
|
import { NavBarContext } from '@/components/context/NavbarContext';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NavBarProvider({ children }: IProps) {
|
export function NavBarContextProvider({ children }: IProps) {
|
||||||
const [defaultBackTo, setDefaultBackTo] = useState<string | undefined>();
|
const [defaultBackTo, setDefaultBackTo] = useState<string | undefined>();
|
||||||
const [title, setTitle] = useState<string | React.ReactNode>('Tachidesk');
|
const [title, setTitle] = useState<string | React.ReactNode>('Tachidesk');
|
||||||
const [action, setAction] = useState<any>(<div />);
|
const [action, setAction] = useState<any>(<div />);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
|||||||
import Collapse from '@mui/material/Collapse';
|
import Collapse from '@mui/material/Collapse';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings';
|
import { ChapterOffset, IReaderSettings, TChapter, TManga } from '@/typings';
|
||||||
import ReaderSettingsOptions from '@/components/reader/ReaderSettingsOptions';
|
import { ReaderSettingsOptions } from '@/components/reader/ReaderSettingsOptions';
|
||||||
|
|
||||||
const Root = styled('div')(({ theme }) => ({
|
const Root = styled('div')(({ theme }) => ({
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -122,7 +122,7 @@ interface IProps {
|
|||||||
retrievingNextChapter: boolean;
|
retrievingNextChapter: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ReaderNavBar(props: IProps) {
|
export function ReaderNavBar(props: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation<{
|
const location = useLocation<{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import Checkbox from '@mui/material/Checkbox';
|
|||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
import FormGroup from '@mui/material/FormGroup';
|
import FormGroup from '@mui/material/FormGroup';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -24,7 +24,7 @@ interface IProps {
|
|||||||
mangaId: number;
|
mangaId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CategorySelect(props: IProps) {
|
export function CategorySelect(props: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { open, setOpen, mangaId } = props;
|
const { open, setOpen, mangaId } = props;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import FilterListIcon from '@mui/icons-material/FilterList';
|
|||||||
import { List, ListItemSecondaryAction, ListItemText } from '@mui/material';
|
import { List, ListItemSecondaryAction, ListItemText } from '@mui/material';
|
||||||
import ListItem from '@mui/material/ListItem';
|
import ListItem from '@mui/material/ListItem';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import cloneObject from '@/util/cloneObject';
|
import { cloneObject } from '@/util/cloneObject';
|
||||||
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
||||||
|
|
||||||
function removeAll(firstList: any[], secondList: any[]) {
|
function removeAll(firstList: any[], secondList: any[]) {
|
||||||
@@ -39,7 +39,7 @@ interface IProps {
|
|||||||
forcedLangs?: string[];
|
forcedLangs?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LangSelect(props: IProps) {
|
export function LangSelect(props: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { shownLangs, setShownLangs, allLangs, forcedLangs } = props;
|
const { shownLangs, setShownLangs, allLangs, forcedLangs } = props;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ interface IProps {
|
|||||||
navBarItems: Array<NavbarItem>;
|
navBarItems: Array<NavbarItem>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DesktopSideBar({ navBarItems }: IProps) {
|
export function DesktopSideBar({ navBarItems }: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ interface IProps {
|
|||||||
navBarItems: Array<NavbarItem>;
|
navBarItems: Array<NavbarItem>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MobileBottomBar({ navBarItems }: IProps) {
|
export function MobileBottomBar({ navBarItems }: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface IProps {
|
|||||||
settings: IReaderSettings;
|
settings: IReaderSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DoublePage = forwardRef((props: IProps, ref: any) => {
|
export const DoublePage = forwardRef((props: IProps, ref: any) => {
|
||||||
const { image1src, image2src, index, settings } = props;
|
const { image1src, image2src, index, settings } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -47,5 +47,3 @@ const DoublePage = forwardRef((props: IProps, ref: any) => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default DoublePage;
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { useState, useEffect, forwardRef, useRef } from 'react';
|
import { useState, useEffect, forwardRef, useRef } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { IReaderSettings } from '@/typings';
|
import { IReaderSettings } from '@/typings';
|
||||||
import SpinnerImage from '@/components/util/SpinnerImage';
|
import { SpinnerImage } from '@/components/util/SpinnerImage';
|
||||||
|
|
||||||
function imageStyle(settings: IReaderSettings): any {
|
function imageStyle(settings: IReaderSettings): any {
|
||||||
const [dimensions, setDimensions] = useState({
|
const [dimensions, setDimensions] = useState({
|
||||||
@@ -65,7 +65,7 @@ interface IProps {
|
|||||||
settings: IReaderSettings;
|
settings: IReaderSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Page = forwardRef((props: IProps, ref: any) => {
|
export const Page = forwardRef((props: IProps, ref: any) => {
|
||||||
const { src, index, onImageLoad, settings } = props;
|
const { src, index, onImageLoad, settings } = props;
|
||||||
|
|
||||||
const imgRef = useRef<HTMLImageElement>(null);
|
const imgRef = useRef<HTMLImageElement>(null);
|
||||||
@@ -92,5 +92,3 @@ const Page = forwardRef((props: IProps, ref: any) => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export default Page;
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface IProps {
|
|||||||
pageCount: number;
|
pageCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PageNumber(props: IProps) {
|
export function PageNumber(props: IProps) {
|
||||||
const { settings, curPage, pageCount } = props;
|
const { settings, curPage, pageCount } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ interface IProps extends IReaderSettings {
|
|||||||
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ReaderSettingsOptions({
|
export function ReaderSettingsOptions({
|
||||||
staticNav,
|
staticNav,
|
||||||
loadNextOnEnding,
|
loadNextOnEnding,
|
||||||
readerType,
|
readerType,
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { useEffect, useRef } from 'react';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import Page from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
import DoublePage from '@/components/reader/DoublePage';
|
import { DoublePage } from '@/components/reader/DoublePage';
|
||||||
|
|
||||||
const isSpreadPage = (image: HTMLImageElement): boolean => {
|
const isSpreadPage = (image: HTMLImageElement): boolean => {
|
||||||
const aspectRatio = image.height / image.width;
|
const aspectRatio = image.height / image.width;
|
||||||
@@ -29,7 +29,7 @@ const isSinglePage = (index: number, spreadPages: boolean[], offsetFirstPage: bo
|
|||||||
return offsetFirstPage ? numberOfNonSpreads % 2 === 0 : numberOfNonSpreads % 2 === 1;
|
return offsetFirstPage ? numberOfNonSpreads % 2 === 0 : numberOfNonSpreads % 2 === 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DoublePagedPager(props: IReaderProps) {
|
export function DoublePagedPager(props: IReaderProps) {
|
||||||
const { pages, settings, setCurPage, initialPage, curPage, nextChapter, prevChapter } = props;
|
const { pages, settings, setCurPage, initialPage, curPage, nextChapter, prevChapter } = props;
|
||||||
|
|
||||||
const selfRef = useRef<HTMLDivElement>(null);
|
const selfRef = useRef<HTMLDivElement>(null);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import Page from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
|
|
||||||
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
||||||
for (let i = 0; i < wrapper.children.length; i++) {
|
for (let i = 0; i < wrapper.children.length; i++) {
|
||||||
@@ -31,7 +31,7 @@ const isAtEnd = () => {
|
|||||||
};
|
};
|
||||||
const isAtStart = () => window.scrollX <= 0;
|
const isAtStart = () => window.scrollX <= 0;
|
||||||
|
|
||||||
export default function HorizontalPager(props: IReaderProps) {
|
export function HorizontalPager(props: IReaderProps) {
|
||||||
const { pages, curPage, initialPage, settings, setCurPage, prevChapter, nextChapter } = props;
|
const { pages, curPage, initialPage, settings, setCurPage, prevChapter, nextChapter } = props;
|
||||||
|
|
||||||
const currentPageRef = useRef(initialPage);
|
const currentPageRef = useRef(initialPage);
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import Page from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
|
|
||||||
export default function PagedReader(props: IReaderProps) {
|
export function PagedPager(props: IReaderProps) {
|
||||||
const { pages, settings, setCurPage, initialPage, curPage, nextChapter, prevChapter } = props;
|
const { pages, settings, setCurPage, initialPage, curPage, nextChapter, prevChapter } = props;
|
||||||
|
|
||||||
const selfRef = useRef<HTMLDivElement>(null);
|
const selfRef = useRef<HTMLDivElement>(null);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { useCallback, useEffect, useRef } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { IReaderProps } from '@/typings';
|
import { IReaderProps } from '@/typings';
|
||||||
import Page from '@/components/reader/Page';
|
import { Page } from '@/components/reader/Page';
|
||||||
|
|
||||||
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
const findCurrentPageIndex = (wrapper: HTMLDivElement): number => {
|
||||||
for (let i = 0; i < wrapper.children.length; i++) {
|
for (let i = 0; i < wrapper.children.length; i++) {
|
||||||
@@ -35,7 +35,7 @@ const isAtBottom = () => {
|
|||||||
};
|
};
|
||||||
const isAtTop = () => window.scrollY <= 0;
|
const isAtTop = () => window.scrollY <= 0;
|
||||||
|
|
||||||
export default function VerticalPager(props: IReaderProps) {
|
export function VerticalPager(props: IReaderProps) {
|
||||||
const { pages, settings, setCurPage, initialPage, nextChapter, prevChapter } = props;
|
const { pages, settings, setCurPage, initialPage, nextChapter, prevChapter } = props;
|
||||||
|
|
||||||
const currentPageRef = useRef(initialPage);
|
const currentPageRef = useRef(initialPage);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
|
|
||||||
// TODO: clean up this to use a FormControl, and remove dependency on name o radio button
|
// TODO: clean up this to use a FormControl, and remove dependency on name o radio button
|
||||||
export default function SourceGridLayout() {
|
export function SourceGridLayout() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import MangaGrid, { IMangaGridProps } from '@/components/MangaGrid';
|
import { MangaGrid, IMangaGridProps } from '@/components/MangaGrid';
|
||||||
import { TPartialManga } from '@/typings.ts';
|
import { TPartialManga } from '@/typings.ts';
|
||||||
|
|
||||||
function filterManga(mangas: TPartialManga[]): TPartialManga[] {
|
function filterManga(mangas: TPartialManga[]): TPartialManga[] {
|
||||||
return mangas;
|
return mangas;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SourceMangaGrid(props: IMangaGridProps) {
|
export function SourceMangaGrid(props: IMangaGridProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { mangas, isLoading, hasNextPage, loadMore, message, messageExtra, gridLayout } = props;
|
const { mangas, isLoading, hasNextPage, loadMore, message, messageExtra, gridLayout } = props;
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,18 @@ import { Button, Stack, Box } from '@mui/material';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { SourceFilters } from '@/typings';
|
import { SourceFilters } from '@/typings';
|
||||||
import OptionsPanel from '@/components/molecules/OptionsPanel';
|
import { OptionsPanel } from '@/components/molecules/OptionsPanel';
|
||||||
import CheckBoxFilter from '@/components/source/filters/CheckBoxFilter';
|
import { CheckBoxFilter } from '@/components/source/filters/CheckBoxFilter';
|
||||||
import HeaderFilter from '@/components/source/filters/HeaderFilter';
|
import { HeaderFilter } from '@/components/source/filters/HeaderFilter';
|
||||||
import SelectFilter from '@/components/source/filters/SelectFilter';
|
import { SelectFilter } from '@/components/source/filters/SelectFilter';
|
||||||
import SortFilter from '@/components/source/filters/SortFilter';
|
import { SortFilter } from '@/components/source/filters/SortFilter';
|
||||||
import TextFilter from '@/components/source/filters/TextFilter';
|
import { TextFilter } from '@/components/source/filters/TextFilter';
|
||||||
import TriStateFilter from '@/components/source/filters/TriStateFilter';
|
import { TriStateFilter } from '@/components/source/filters/TriStateFilter';
|
||||||
// this can only cycle once, so should be fine
|
// this can only cycle once, so should be fine
|
||||||
// eslint-disable-next-line import/no-cycle
|
// eslint-disable-next-line import/no-cycle
|
||||||
import GroupFilter from '@/components/source/filters/GroupFilter';
|
import { GroupFilter } from '@/components/source/filters/GroupFilter';
|
||||||
import SeperatorFilter from '@/components/source/filters/SeparatorFilter';
|
import { SeparatorFilter } from '@/components/source/filters/SeparatorFilter';
|
||||||
import StyledFab from '@/components/util/StyledFab';
|
import { StyledFab } from '@/components/util/StyledFab';
|
||||||
|
|
||||||
interface IFilters {
|
interface IFilters {
|
||||||
sourceFilter: SourceFilters[];
|
sourceFilter: SourceFilters[];
|
||||||
@@ -88,7 +88,7 @@ export function Options({ sourceFilter, group, updateFilterValue, update }: IFil
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case 'SeparatorFilter':
|
case 'SeparatorFilter':
|
||||||
return <SeperatorFilter key={`filters ${e.name}`} name={e.name} />;
|
return <SeparatorFilter key={`filters ${e.name}`} name={e.name} />;
|
||||||
case 'SortFilter':
|
case 'SortFilter':
|
||||||
return (
|
return (
|
||||||
<SortFilter
|
<SortFilter
|
||||||
@@ -139,7 +139,7 @@ export function Options({ sourceFilter, group, updateFilterValue, update }: IFil
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SourceOptions({
|
export function SourceOptions({
|
||||||
sourceFilter,
|
sourceFilter,
|
||||||
updateFilterValue,
|
updateFilterValue,
|
||||||
resetFilterValue,
|
resetFilterValue,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import CheckboxInput from '@/components/atoms/CheckboxInput';
|
import { CheckboxInput } from '@/components/atoms/CheckboxInput';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
state: boolean;
|
state: boolean;
|
||||||
@@ -18,7 +18,7 @@ interface Props {
|
|||||||
update: any;
|
update: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CheckBoxFilter: React.FC<Props> = (props: Props) => {
|
export const CheckBoxFilter: React.FC<Props> = (props: Props) => {
|
||||||
const { state, name, position, group, updateFilterValue, update } = props;
|
const { state, name, position, group, updateFilterValue, update } = props;
|
||||||
const [val, setval] = React.useState(state);
|
const [val, setval] = React.useState(state);
|
||||||
|
|
||||||
@@ -35,5 +35,3 @@ const CheckBoxFilter: React.FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CheckBoxFilter;
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ interface Props {
|
|||||||
update: any;
|
update: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GroupFilter: React.FC<Props> = (props: Props) => {
|
export const GroupFilter: React.FC<Props> = (props: Props) => {
|
||||||
const { state, name, position, updateFilterValue, update } = props;
|
const { state, name, position, updateFilterValue, update } = props;
|
||||||
|
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
@@ -46,5 +46,3 @@ const GroupFilter: React.FC<Props> = (props: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GroupFilter;
|
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ interface Props {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderFilter: React.FC<Props> = ({ name }) => (
|
export const HeaderFilter: React.FC<Props> = ({ name }) => (
|
||||||
<Typography key={name} sx={{ mt: 2 }} variant="subtitle2">
|
<Typography key={name} sx={{ mt: 2 }} variant="subtitle2">
|
||||||
{name}
|
{name}
|
||||||
</Typography>
|
</Typography>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default HeaderFilter;
|
|
||||||
|
|||||||
@@ -60,7 +60,5 @@ function noSelect(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SelectFilter: React.FC<Props> = ({ values, name, state, position, updateFilterValue, update, group }) =>
|
export const SelectFilter: React.FC<Props> = ({ values, name, state, position, updateFilterValue, update, group }) =>
|
||||||
noSelect(values, name, state, position, updateFilterValue, update, group);
|
noSelect(values, name, state, position, updateFilterValue, update, group);
|
||||||
|
|
||||||
export default SelectFilter;
|
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ interface Props {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SeparatorFilter: React.FC<Props> = ({ name }) => (
|
export const SeparatorFilter: React.FC<Props> = ({ name }) => (
|
||||||
<Divider key={name} sx={{ my: 1 }} textAlign="center">
|
<Divider key={name} sx={{ my: 1 }} textAlign="center">
|
||||||
{name}
|
{name}
|
||||||
</Divider>
|
</Divider>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default SeparatorFilter;
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { ExpandLess, ExpandMore } from '@mui/icons-material';
|
import { ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||||
import { Collapse, ListItemButton, ListItemText, Stack, Box } from '@mui/material';
|
import { Collapse, ListItemButton, ListItemText, Stack, Box } from '@mui/material';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SortRadioInput from '@/components/atoms/SortRadioInput';
|
import { SortRadioInput } from '@/components/atoms/SortRadioInput';
|
||||||
import { SortSelectionInput } from '@/lib/graphql/generated/graphql.ts';
|
import { SortSelectionInput } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -22,7 +22,7 @@ interface Props {
|
|||||||
update: any;
|
update: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortFilter: React.FC<Props> = (props: Props) => {
|
export const SortFilter: React.FC<Props> = (props: Props) => {
|
||||||
const { values, name, state, position, group, updateFilterValue, update } = props;
|
const { values, name, state, position, group, updateFilterValue, update } = props;
|
||||||
const [val, setval] = React.useState(state);
|
const [val, setval] = React.useState(state);
|
||||||
|
|
||||||
@@ -72,5 +72,3 @@ const SortFilter: React.FC<Props> = (props: Props) => {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SortFilter;
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ interface Props {
|
|||||||
update: any;
|
update: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextFilter: React.FC<Props> = (props) => {
|
export const TextFilter: React.FC<Props> = (props) => {
|
||||||
const { state, name, position, group, updateFilterValue, update } = props;
|
const { state, name, position, group, updateFilterValue, update } = props;
|
||||||
const [Search, setsearch] = React.useState(state || '');
|
const [Search, setsearch] = React.useState(state || '');
|
||||||
const inputText = useDebounce(Search, 500);
|
const inputText = useDebounce(Search, 500);
|
||||||
@@ -51,5 +51,3 @@ const TextFilter: React.FC<Props> = (props) => {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TextFilter;
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ThreeStateCheckboxInput from '@/components/atoms/ThreeStateCheckboxInput';
|
import { ThreeStateCheckboxInput } from '@/components/atoms/ThreeStateCheckboxInput';
|
||||||
import { TriState } from '@/lib/graphql/generated/graphql.ts';
|
import { TriState } from '@/lib/graphql/generated/graphql.ts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -45,7 +45,7 @@ const convertNumberToTriState = (state: number): TriState => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const TriStateFilter: React.FC<Props> = (props) => {
|
export const TriStateFilter: React.FC<Props> = (props) => {
|
||||||
const { state, name, position, group, updateFilterValue, update } = props;
|
const { state, name, position, group, updateFilterValue, update } = props;
|
||||||
const [val, setval] = React.useState(convertTriStateToNumber(state));
|
const [val, setval] = React.useState(convertTriStateToNumber(state));
|
||||||
|
|
||||||
@@ -78,5 +78,3 @@ const TriStateFilter: React.FC<Props> = (props) => {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TriStateFilter;
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { ListItemButton } from '@mui/material';
|
import { ListItemButton } from '@mui/material';
|
||||||
import { EditTextPreferenceProps } from '@/typings';
|
import { EditTextPreferenceProps } from '@/typings';
|
||||||
|
|
||||||
export default function EditTextPreference(props: EditTextPreferenceProps) {
|
export function EditTextPreference(props: EditTextPreferenceProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ function ListDialog(props: IListDialogProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ListPreference(props: ListPreferenceProps) {
|
export function ListPreference(props: ListPreferenceProps) {
|
||||||
const {
|
const {
|
||||||
ListPreferenceTitle: title,
|
ListPreferenceTitle: title,
|
||||||
summary,
|
summary,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import Button from '@mui/material/Button';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ListItemButton } from '@mui/material';
|
import { ListItemButton } from '@mui/material';
|
||||||
import { MultiSelectListPreferenceProps } from '@/typings';
|
import { MultiSelectListPreferenceProps } from '@/typings';
|
||||||
import cloneObject from '@/util/cloneObject';
|
import { cloneObject } from '@/util/cloneObject';
|
||||||
|
|
||||||
interface IListDialogProps {
|
interface IListDialogProps {
|
||||||
selectedValues: string[];
|
selectedValues: string[];
|
||||||
@@ -98,7 +98,7 @@ function ListDialog(props: IListDialogProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MultiSelectListPreference(props: MultiSelectListPreferenceProps) {
|
export function MultiSelectListPreference(props: MultiSelectListPreferenceProps) {
|
||||||
const {
|
const {
|
||||||
MultiSelectListPreferenceTitle: title,
|
MultiSelectListPreferenceTitle: title,
|
||||||
summary,
|
summary,
|
||||||
|
|||||||
@@ -80,5 +80,3 @@ export function CheckBoxPreference(props: CheckBoxPreferenceProps) {
|
|||||||
export function SwitchPreferenceCompat(props: SwitchPreferenceCompatProps) {
|
export function SwitchPreferenceCompat(props: SwitchPreferenceCompatProps) {
|
||||||
return <TwoSatePreference {...props} twoStateType="Switch" />;
|
return <TwoSatePreference {...props} twoStateType="Switch" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default { CheckBoxPreference, SwitchPreferenceCompat };
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const defaultProps = {
|
|||||||
autoOpen: false,
|
autoOpen: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
|
export const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
|
||||||
const { autoOpen } = props;
|
const { autoOpen } = props;
|
||||||
const [query, setQuery] = useQueryParam('query', StringParam);
|
const [query, setQuery] = useQueryParam('query', StringParam);
|
||||||
const [searchOpen, setSearchOpen] = useState(!!query);
|
const [searchOpen, setSearchOpen] = useState(!!query);
|
||||||
@@ -90,5 +90,3 @@ const AppbarSearch: React.FunctionComponent<IProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
AppbarSearch.defaultProps = defaultProps;
|
AppbarSearch.defaultProps = defaultProps;
|
||||||
|
|
||||||
export default AppbarSearch;
|
|
||||||
|
|||||||
@@ -11,6 +11,4 @@ import createSvgIcon from '@mui/material/utils/createSvgIcon';
|
|||||||
const d =
|
const d =
|
||||||
'M 11 1 C 9.3550302 1 8 2.3550302 8 4 L 4 4 C 2.9069372 4 2 4.9069372 2 6 L 2 12 L 4 12 C 4.5650302 12 5 12.43497 5 13 C 5 13.56503 4.5650302 14 4 14 L 2 14 L 2 20 C 2 21.093063 2.9069372 22 4 22 L 10 22 L 10 20 C 10 19.43497 10.43497 19 11 19 C 11.56503 19 12 19.43497 12 20 L 12 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 16 C 21.64497 16 23 14.64497 23 13 C 23 11.35503 21.64497 10 20 10 L 20 6 C 20 4.9069372 19.093063 4 18 4 L 14 4 C 14 2.3550302 12.64497 1 11 1 z M 11 3 C 11.56503 3 12 3.4349698 12 4 L 12 6 L 18 6 L 18 12 L 20 12 C 20.56503 12 21 12.43497 21 13 C 21 13.56503 20.56503 14 20 14 L 18 14 L 18 20 L 14 20 C 14 18.35503 12.64497 17 11 17 C 9.3550302 17 8 18.35503 8 20 L 4 20 L 4 16 C 5.6449698 16 7 14.64497 7 13 C 7 11.35503 5.6449698 10 4 10 L 4 6 L 10 6 L 10 4 C 10 3.4349698 10.43497 3 11 3 z';
|
'M 11 1 C 9.3550302 1 8 2.3550302 8 4 L 4 4 C 2.9069372 4 2 4.9069372 2 6 L 2 12 L 4 12 C 4.5650302 12 5 12.43497 5 13 C 5 13.56503 4.5650302 14 4 14 L 2 14 L 2 20 C 2 21.093063 2.9069372 22 4 22 L 10 22 L 10 20 C 10 19.43497 10.43497 19 11 19 C 11.56503 19 12 19.43497 12 20 L 12 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 16 C 21.64497 16 23 14.64497 23 13 C 23 11.35503 21.64497 10 20 10 L 20 6 C 20 4.9069372 19.093063 4 18 4 L 14 4 C 14 2.3550302 12.64497 1 11 1 z M 11 3 C 11.56503 3 12 3.4349698 12 4 L 12 6 L 18 6 L 18 12 L 20 12 C 20.56503 12 21 12.43497 21 13 C 21 13.56503 20.56503 14 20 14 L 18 14 L 18 20 L 14 20 C 14 18.35503 12.64497 17 11 17 C 9.3550302 17 8 18.35503 8 20 L 4 20 L 4 16 C 5.6449698 16 7 14.64497 7 13 C 7 11.35503 5.6449698 10 4 10 L 4 6 L 10 6 L 10 4 C 10 3.4349698 10.43497 3 11 3 z';
|
||||||
|
|
||||||
const icon = createSvgIcon(<path d={d} />, 'CustomExtensionOutlined');
|
export const ExtensionOutlinedIcon = createSvgIcon(<path d={d} />, 'CustomExtensionOutlined');
|
||||||
|
|
||||||
export default icon;
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ interface IProps {
|
|||||||
messageExtra?: JSX.Element | string;
|
messageExtra?: JSX.Element | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function EmptyView({ message, messageExtra }: IProps) {
|
export function EmptyView({ message, messageExtra }: IProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
|
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { ListItemButton, ListItemButtonProps } from '@mui/material';
|
import { ListItemButton, ListItemButtonProps } from '@mui/material';
|
||||||
|
|
||||||
export default function ListItemLink(props: ListItemButtonProps<typeof Link, { directLink?: boolean }>) {
|
export function ListItemLink(props: ListItemButtonProps<typeof Link, { directLink?: boolean }>) {
|
||||||
const { directLink, to } = props;
|
const { directLink, to } = props;
|
||||||
if (directLink) {
|
if (directLink) {
|
||||||
if (typeof to !== 'string') {
|
if (typeof to !== 'string') {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ interface IProps {
|
|||||||
usePadding?: boolean;
|
usePadding?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LoadingPlaceholder(props: IProps) {
|
export function LoadingPlaceholder(props: IProps) {
|
||||||
const { children, shouldRender, component, componentProps, usePadding } = props;
|
const { children, shouldRender, component, componentProps, usePadding } = props;
|
||||||
|
|
||||||
let condition = true;
|
let condition = true;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interface IProps {
|
|||||||
onImageLoad?: () => void;
|
onImageLoad?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SpinnerImage(props: IProps) {
|
export function SpinnerImage(props: IProps) {
|
||||||
const { src, alt, onImageLoad, imgRef, spinnerStyle, imgStyle } = props;
|
const { src, alt, onImageLoad, imgRef, spinnerStyle, imgStyle } = props;
|
||||||
const [imageSrc, setImagsrc] = useState<string>('');
|
const [imageSrc, setImagsrc] = useState<string>('');
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ export const DEFAULT_FAB_STYLE = {
|
|||||||
|
|
||||||
export const DEFAULT_FULL_FAB_HEIGHT = `calc(${DEFAULT_FAB_STYLE.bottom} + ${DEFAULT_FAB_STYLE.height})`;
|
export const DEFAULT_FULL_FAB_HEIGHT = `calc(${DEFAULT_FAB_STYLE.bottom} + ${DEFAULT_FAB_STYLE.height})`;
|
||||||
|
|
||||||
const StyledFab = styled(Fab)({
|
export const StyledFab = styled(Fab)({
|
||||||
...DEFAULT_FAB_STYLE,
|
...DEFAULT_FAB_STYLE,
|
||||||
}) as typeof Fab;
|
}) as typeof Fab;
|
||||||
|
|
||||||
export default StyledFab;
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface IProps {
|
|||||||
currentIndex: any;
|
currentIndex: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TabPanel(props: IProps) {
|
export function TabPanel(props: IProps) {
|
||||||
const { children, index, currentIndex } = props;
|
const { children, index, currentIndex } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function Toast(props: IToastProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function makeToast(message: string, severity: Severity) {
|
export function makeToast(message: string, severity: Severity) {
|
||||||
const id = Math.floor(Math.random() * 1000);
|
const id = Math.floor(Math.random() * 1000);
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.id = `alert-${id}`;
|
container.id = `alert-${id}`;
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
import { use } from 'i18next';
|
import { use } from 'i18next';
|
||||||
import { initReactI18next } from 'react-i18next';
|
import { initReactI18next } from 'react-i18next';
|
||||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
import resources from '@/i18n/translations';
|
import { resources } from '@/i18n/translations';
|
||||||
|
|
||||||
const i18n = use(initReactI18next)
|
export const i18n = use(initReactI18next)
|
||||||
.use(LanguageDetector)
|
.use(LanguageDetector)
|
||||||
.init({
|
.init({
|
||||||
resources,
|
resources,
|
||||||
@@ -23,5 +23,3 @@ const i18n = use(initReactI18next)
|
|||||||
returnNull: false,
|
returnNull: false,
|
||||||
debug: process.env.NODE_ENV !== 'production',
|
debug: process.env.NODE_ENV !== 'production',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default i18n;
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const translationHelper = <T>(lng: T) => ({
|
|||||||
* Keys have to match {@link ISOLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.<br/>
|
* Keys have to match {@link ISOLanguages} codes, they're used for showing the language name in the dropdown in the {@link Settings}.<br/>
|
||||||
* In case there is no language code for the key in {@link ISOLanguages}, the corresponding language has to be added
|
* In case there is no language code for the key in {@link ISOLanguages}, the corresponding language has to be added
|
||||||
*/
|
*/
|
||||||
const resources = {
|
export const resources = {
|
||||||
ar: translationHelper(ar),
|
ar: translationHelper(ar),
|
||||||
de: translationHelper(de),
|
de: translationHelper(de),
|
||||||
es: translationHelper(es),
|
es: translationHelper(es),
|
||||||
@@ -45,5 +45,3 @@ const resources = {
|
|||||||
'zh-Hans': translationHelper(zh_Hans),
|
'zh-Hans': translationHelper(zh_Hans),
|
||||||
'zh-Hant': translationHelper(zh_Hant),
|
'zh-Hant': translationHelper(zh_Hant),
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default resources;
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import App from '@/App';
|
import { App } from '@/App';
|
||||||
import '@/index.css';
|
import '@/index.css';
|
||||||
// roboto font
|
// roboto font
|
||||||
import '@fontsource/roboto';
|
import '@fontsource/roboto';
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { Droppable, DroppableProps } from 'react-beautiful-dnd';
|
|||||||
|
|
||||||
// issue: https://github.com/atlassian/react-beautiful-dnd/issues/2399
|
// issue: https://github.com/atlassian/react-beautiful-dnd/issues/2399
|
||||||
// credit for fix: https://github.com/atlassian/react-beautiful-dnd/issues/2399#issuecomment-1175638194
|
// credit for fix: https://github.com/atlassian/react-beautiful-dnd/issues/2399#issuecomment-1175638194
|
||||||
export default function StrictModeDroppable({ children, ...props }: DroppableProps) {
|
export function StrictModeDroppable({ children, ...props }: DroppableProps) {
|
||||||
const [enabled, setEnabled] = useState(false);
|
const [enabled, setEnabled] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments';
|
import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const UPDATE_WEBUI = gql`
|
export const UPDATE_WEBUI = gql`
|
||||||
${WEBUI_UPDATE_STATUS}
|
${WEBUI_UPDATE_STATUS}
|
||||||
mutation UPDATE_WEBUI($input: WebUIUpdateInput = {}) {
|
mutation UPDATE_WEBUI($input: WebUIUpdateInput = {}) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments';
|
import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GET_DOWNLOAD_STATUS = gql`
|
export const GET_DOWNLOAD_STATUS = gql`
|
||||||
${FULL_DOWNLOAD_STATUS}
|
${FULL_DOWNLOAD_STATUS}
|
||||||
query GET_DOWNLOAD_STATUS {
|
query GET_DOWNLOAD_STATUS {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { SERVER_SETTINGS } from '@/lib/graphql/Fragments';
|
import { SERVER_SETTINGS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GET_SERVER_SETTINGS = gql`
|
export const GET_SERVER_SETTINGS = gql`
|
||||||
${SERVER_SETTINGS}
|
${SERVER_SETTINGS}
|
||||||
query GET_SERVER_SETTINGS {
|
query GET_SERVER_SETTINGS {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments';
|
import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const GET_UPDATE_STATUS = gql`
|
export const GET_UPDATE_STATUS = gql`
|
||||||
${FULL_UPDATER_STATUS}
|
${FULL_UPDATER_STATUS}
|
||||||
query GET_UPDATE_STATUS {
|
query GET_UPDATE_STATUS {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments';
|
import { FULL_DOWNLOAD_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const DOWNLOAD_STATUS_SUBSCRIPTION = gql`
|
export const DOWNLOAD_STATUS_SUBSCRIPTION = gql`
|
||||||
${FULL_DOWNLOAD_STATUS}
|
${FULL_DOWNLOAD_STATUS}
|
||||||
subscription DOWNLOAD_STATUS_SUBSCRIPTION {
|
subscription DOWNLOAD_STATUS_SUBSCRIPTION {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments';
|
import { WEBUI_UPDATE_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const WEBUI_UPDATE_SUBSCRIPTION = gql`
|
export const WEBUI_UPDATE_SUBSCRIPTION = gql`
|
||||||
${WEBUI_UPDATE_STATUS}
|
${WEBUI_UPDATE_STATUS}
|
||||||
subscription WEBUI_UPDATE_SUBSCRIPTION {
|
subscription WEBUI_UPDATE_SUBSCRIPTION {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
import gql from 'graphql-tag';
|
import gql from 'graphql-tag';
|
||||||
import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments';
|
import { FULL_UPDATER_STATUS } from '@/lib/graphql/Fragments';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const UPDATER_SUBSCRIPTION = gql`
|
export const UPDATER_SUBSCRIPTION = gql`
|
||||||
${FULL_UPDATER_STATUS}
|
${FULL_UPDATER_STATUS}
|
||||||
subscription UPDATER_SUBSCRIPTION {
|
subscription UPDATER_SUBSCRIPTION {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export class CustomCache {
|
export class CustomCache {
|
||||||
private keyToResponseMap = new Map<string, unknown>();
|
private keyToResponseMap = new Map<string, unknown>();
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import {
|
|||||||
import { OperationVariables } from '@apollo/client/core';
|
import { OperationVariables } from '@apollo/client/core';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { IRestClient, RestClient } from '@/lib/requests/client/RestClient.ts';
|
import { IRestClient, RestClient } from '@/lib/requests/client/RestClient.ts';
|
||||||
import storage from '@/util/localStorage.tsx';
|
import * as storage from '@/util/localStorage.tsx';
|
||||||
import { GraphQLClient } from '@/lib/requests/client/GraphQLClient.ts';
|
import { GraphQLClient } from '@/lib/requests/client/GraphQLClient.ts';
|
||||||
import {
|
import {
|
||||||
CategoryOrderBy,
|
CategoryOrderBy,
|
||||||
@@ -1795,5 +1795,4 @@ export class RequestManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestManager = new RequestManager();
|
export const requestManager = new RequestManager();
|
||||||
export default requestManager;
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@
|
|||||||
* 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 storage from '@/util/localStorage.tsx';
|
import * as storage from '@/util/localStorage.tsx';
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export abstract class BaseClient<Client, ClientConfig, Fetcher> {
|
export abstract class BaseClient<Client, ClientConfig, Fetcher> {
|
||||||
protected client!: Client;
|
protected client!: Client;
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ const typePolicies: StrictTypedTypePolicies = {
|
|||||||
};
|
};
|
||||||
/* eslint-enable no-underscore-dangle */
|
/* eslint-enable no-underscore-dangle */
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export class GraphQLClient extends BaseClient<
|
export class GraphQLClient extends BaseClient<
|
||||||
ApolloClient<NormalizedCacheObject>,
|
ApolloClient<NormalizedCacheObject>,
|
||||||
ApolloClientOptions<NormalizedCacheObject>,
|
ApolloClientOptions<NormalizedCacheObject>,
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import { useState } from 'react';
|
|||||||
import Tabs from '@mui/material/Tabs';
|
import Tabs from '@mui/material/Tabs';
|
||||||
import Tab from '@mui/material/Tab';
|
import Tab from '@mui/material/Tab';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Sources from '@/screens/Sources';
|
import { Sources } from '@/screens/Sources';
|
||||||
import Extensions from '@/screens/Extensions';
|
import { Extensions } from '@/screens/Extensions';
|
||||||
import TabPanel from '@/components/util/TabPanel';
|
import { TabPanel } from '@/components/util/TabPanel';
|
||||||
|
|
||||||
export default function Browse() {
|
export function Browse() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [tabNum, setTabNum] = useState<number>(0);
|
const [tabNum, setTabNum] = useState<number>(0);
|
||||||
|
|||||||
@@ -18,24 +18,24 @@ import { DragDropContext, Draggable } from 'react-beautiful-dnd';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import StrictModeDroppable from '@/lib/StrictModeDroppable';
|
import { StrictModeDroppable } from '@/lib/StrictModeDroppable';
|
||||||
import makeToast from '@/components/util/Toast';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
import { NavbarToolbar } from '@/components/navbar/DefaultNavBar';
|
import { NavbarToolbar } from '@/components/navbar/DefaultNavBar';
|
||||||
import DownloadStateIndicator from '@/components/molecules/DownloadStateIndicator';
|
import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import { EmptyView } from '@/components/util/EmptyView';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
|
||||||
import { DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
import { DownloadType } from '@/lib/graphql/generated/graphql.ts';
|
||||||
import { TChapter } from '@/typings.ts';
|
import { TChapter } from '@/typings.ts';
|
||||||
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
const DownloadQueue: React.FC = () => {
|
export const DownloadQueue: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { data: downloaderData } = requestManager.useDownloadSubscription();
|
const { data: downloaderData } = requestManager.useDownloadSubscription();
|
||||||
const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? [];
|
const queue = (downloaderData?.downloadChanged.queue as DownloadType[]) ?? [];
|
||||||
const status = downloaderData?.downloadChanged.state ?? 'STARTED';
|
const status = downloaderData?.downloadChanged.state ?? 'STARTED';
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
|
|
||||||
const toggleQueueStatus = () => {
|
const toggleQueueStatus = () => {
|
||||||
if (status === 'STOPPED') {
|
if (status === 'STOPPED') {
|
||||||
@@ -155,5 +155,3 @@ const DownloadQueue: React.FC = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DownloadQueue;
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import { StringParam, useQueryParam } from 'use-query-params';
|
|||||||
import { Virtuoso } from 'react-virtuoso';
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
import { Typography, useMediaQuery, useTheme } from '@mui/material';
|
import { Typography, useMediaQuery, useTheme } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { extensionDefaultLangs, DefaultLanguage, langSortCmp } from '@/util/language';
|
import { extensionDefaultLangs, DefaultLanguage, langSortCmp } from '@/util/language';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import {
|
import {
|
||||||
ExtensionState,
|
ExtensionState,
|
||||||
GroupedExtensions,
|
GroupedExtensions,
|
||||||
@@ -24,13 +24,13 @@ import {
|
|||||||
isExtensionStateOrLanguage,
|
isExtensionStateOrLanguage,
|
||||||
translateExtensionLanguage,
|
translateExtensionLanguage,
|
||||||
} from '@/screens/util/Extensions';
|
} from '@/screens/util/Extensions';
|
||||||
import AppbarSearch from '@/components/util/AppbarSearch';
|
import { AppbarSearch } from '@/components/util/AppbarSearch';
|
||||||
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
||||||
import { makeToaster } from '@/components/util/Toast';
|
import { makeToaster } from '@/components/util/Toast';
|
||||||
import LangSelect from '@/components/navbar/action/LangSelect';
|
import { LangSelect } from '@/components/navbar/action/LangSelect';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
import { ExtensionCard } from '@/components/ExtensionCard';
|
||||||
import ExtensionCard from '@/components/ExtensionCard';
|
|
||||||
import { PartialExtension } from '@/typings.ts';
|
import { PartialExtension } from '@/typings.ts';
|
||||||
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
const LANGUAGE = 0;
|
const LANGUAGE = 0;
|
||||||
const EXTENSIONS = 1;
|
const EXTENSIONS = 1;
|
||||||
@@ -89,11 +89,11 @@ function getExtensionsInfo(extensions: PartialExtension[]): {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MangaExtensions() {
|
export function Extensions() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownExtensionLangs', extensionDefaultLangs());
|
const [shownLangs, setShownLangs] = useLocalStorage<string[]>('shownExtensionLangs', extensionDefaultLangs());
|
||||||
const [showNsfw] = useLocalStorage<boolean>('showNsfw', true);
|
const [showNsfw] = useLocalStorage<boolean>('showNsfw', true);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|||||||
@@ -10,16 +10,16 @@ import { Chip, Tab, Tabs, styled, Box } from '@mui/material';
|
|||||||
import React, { useCallback, useContext, useEffect, useMemo } from 'react';
|
import React, { useCallback, useContext, useEffect, useMemo } from 'react';
|
||||||
import { useQueryParam, NumberParam } from 'use-query-params';
|
import { useQueryParam, NumberParam } from 'use-query-params';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
import { EmptyView } from '@/components/util/EmptyView';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
||||||
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
import { TabPanel } from '@/components/util/TabPanel';
|
||||||
import TabPanel from '@/components/util/TabPanel';
|
import { LibraryToolbarMenu } from '@/components/library/LibraryToolbarMenu';
|
||||||
import LibraryToolbarMenu from '@/components/library/LibraryToolbarMenu';
|
import { LibraryMangaGrid } from '@/components/library/LibraryMangaGrid';
|
||||||
import LibraryMangaGrid from '@/components/library/LibraryMangaGrid';
|
import { AppbarSearch } from '@/components/util/AppbarSearch';
|
||||||
import AppbarSearch from '@/components/util/AppbarSearch';
|
import { UpdateChecker } from '@/components/library/UpdateChecker';
|
||||||
import UpdateChecker from '@/components/library/UpdateChecker';
|
|
||||||
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||||
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
const StyledGridWrapper = styled(Box)(({ theme }) => ({
|
const StyledGridWrapper = styled(Box)(({ theme }) => ({
|
||||||
// TabsMenu height + TabsMenu bottom padding - grid item top padding
|
// TabsMenu height + TabsMenu bottom padding - grid item top padding
|
||||||
@@ -58,7 +58,7 @@ const TitleSizeTag = (props: React.ComponentProps<typeof Chip>) => (
|
|||||||
<Chip {...props} size="small" sx={{ marginLeft: '5px' }} />
|
<Chip {...props} size="small" sx={{ marginLeft: '5px' }} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function Library() {
|
export function Library() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { options } = useLibraryOptionsContext();
|
const { options } = useLibraryOptionsContext();
|
||||||
@@ -91,7 +91,7 @@ export default function Library() {
|
|||||||
refetch();
|
refetch();
|
||||||
}, [refetch]);
|
}, [refetch]);
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const title = t('library.title');
|
const title = t('library.title');
|
||||||
const navBarTitle = (
|
const navBarTitle = (
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ import React, { useContext, useEffect, useRef } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
|
import { isNetworkRequestInFlight } from '@apollo/client/core/networkStatus';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import NavbarContext, { useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext';
|
||||||
import ChapterList from '@/components/manga/ChapterList';
|
import { ChapterList } from '@/components/manga/ChapterList';
|
||||||
import { useRefreshManga } from '@/components/manga/hooks';
|
import { useRefreshManga } from '@/components/manga/hooks';
|
||||||
import MangaDetails from '@/components/manga/MangaDetails';
|
import { MangaDetails } from '@/components/manga/MangaDetails';
|
||||||
import MangaToolbarMenu from '@/components/manga/MangaToolbarMenu';
|
import { MangaToolbarMenu } from '@/components/manga/MangaToolbarMenu';
|
||||||
import EmptyView from '@/components/util/EmptyView';
|
import { EmptyView } from '@/components/util/EmptyView';
|
||||||
import LoadingPlaceholder from '@/components/util/LoadingPlaceholder';
|
import { LoadingPlaceholder } from '@/components/util/LoadingPlaceholder';
|
||||||
|
|
||||||
const AUTOFETCH_AGE = 1000 * 60 * 60 * 24; // 24 hours
|
const AUTOFETCH_AGE = 1000 * 60 * 60 * 24; // 24 hours
|
||||||
|
|
||||||
const Manga: React.FC = () => {
|
export const Manga: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const autofetchedRef = useRef(false);
|
const autofetchedRef = useRef(false);
|
||||||
|
|
||||||
@@ -100,5 +100,3 @@ const Manga: React.FC = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Manga;
|
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ChapterOffset, IReaderSettings, ReaderType, TChapter, TManga, TranslationKey } from '@/typings';
|
import { ChapterOffset, IReaderSettings, ReaderType, TChapter, TManga, TranslationKey } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import {
|
import {
|
||||||
checkAndHandleMissingStoredReaderSettings,
|
checkAndHandleMissingStoredReaderSettings,
|
||||||
getReaderSettingsFor,
|
getReaderSettingsFor,
|
||||||
useDefaultReaderSettings,
|
useDefaultReaderSettings,
|
||||||
} from '@/util/readerSettings';
|
} from '@/util/readerSettings';
|
||||||
import { requestUpdateMangaMetadata } from '@/util/metadata';
|
import { requestUpdateMangaMetadata } from '@/util/metadata';
|
||||||
import HorizontalPager from '@/components/reader/pager/HorizontalPager';
|
import { HorizontalPager } from '@/components/reader/pager/HorizontalPager';
|
||||||
import PageNumber from '@/components/reader/PageNumber';
|
import { PageNumber } from '@/components/reader/PageNumber';
|
||||||
import PagedPager from '@/components/reader/pager/PagedPager';
|
import { PagedPager } from '@/components/reader/pager/PagedPager';
|
||||||
import DoublePagedPager from '@/components/reader/pager/DoublePagedPager';
|
import { DoublePagedPager } from '@/components/reader/pager/DoublePagedPager';
|
||||||
import VerticalPager from '@/components/reader/pager/VerticalPager';
|
import { VerticalPager } from '@/components/reader/pager/VerticalPager';
|
||||||
import ReaderNavBar from '@/components/navbar/ReaderNavBar';
|
import { ReaderNavBar } from '@/components/navbar/ReaderNavBar';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
import { makeToast } from '@/components/util/Toast';
|
||||||
import makeToast from '@/components/util/Toast';
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
const isDupChapter = async (chapterIndex: number, currentChapter: TChapter) => {
|
const isDupChapter = async (chapterIndex: number, currentChapter: TChapter) => {
|
||||||
const nextChapter = await requestManager.getChapter(currentChapter.manga.id, chapterIndex).response;
|
const nextChapter = await requestManager.getChapter(currentChapter.manga.id, chapterIndex).response;
|
||||||
@@ -87,7 +87,7 @@ const initialChapter = {
|
|||||||
name: 'Loading...',
|
name: 'Loading...',
|
||||||
} as unknown as TChapter;
|
} as unknown as TChapter;
|
||||||
|
|
||||||
export default function Reader() {
|
export function Reader() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -148,7 +148,7 @@ export default function Reader() {
|
|||||||
const [wasLastPageReadSet, setWasLastPageReadSet] = useState(false);
|
const [wasLastPageReadSet, setWasLastPageReadSet] = useState(false);
|
||||||
const [curPage, setCurPage] = useState<number>(0);
|
const [curPage, setCurPage] = useState<number>(0);
|
||||||
const [pageToScrollTo, setPageToScrollTo] = useState<number | undefined>(undefined);
|
const [pageToScrollTo, setPageToScrollTo] = useState<number | undefined>(undefined);
|
||||||
const { setOverride, setTitle } = useContext(NavbarContext);
|
const { setOverride, setTitle } = useContext(NavBarContext);
|
||||||
const [retrievingNextChapter, setRetrievingNextChapter] = useState(false);
|
const [retrievingNextChapter, setRetrievingNextChapter] = useState(false);
|
||||||
|
|
||||||
const { settings: defaultSettings, loading: areDefaultSettingsLoading } = useDefaultReaderSettings();
|
const { settings: defaultSettings, loading: areDefaultSettingsLoading } = useDefaultReaderSettings();
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ import { Link } from 'react-router-dom';
|
|||||||
import { StringParam, useQueryParam } from 'use-query-params';
|
import { StringParam, useQueryParam } from 'use-query-params';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ISource } from '@/typings';
|
import { ISource } from '@/typings';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import { langSortCmp, sourceDefualtLangs, sourceForcedDefaultLangs } from '@/util/language';
|
import { langSortCmp, sourceDefualtLangs, sourceForcedDefaultLangs } from '@/util/language';
|
||||||
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
import { translateExtensionLanguage } from '@/screens/util/Extensions';
|
||||||
import AppbarSearch from '@/components/util/AppbarSearch';
|
import { AppbarSearch } from '@/components/util/AppbarSearch';
|
||||||
import LangSelect from '@/components/navbar/action/LangSelect';
|
import { LangSelect } from '@/components/navbar/action/LangSelect';
|
||||||
import MangaGrid from '@/components/MangaGrid';
|
import { MangaGrid } from '@/components/MangaGrid';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
|
||||||
import { useDebounce } from '@/components/manga/hooks';
|
import { useDebounce } from '@/components/manga/hooks';
|
||||||
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
type SourceLoadingState = { isLoading: boolean; hasResults: boolean; emptySearch: boolean };
|
||||||
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
type SourceToLoadingStateMap = Map<string, SourceLoadingState>;
|
||||||
@@ -155,10 +155,10 @@ const SourceSearchPreview = React.memo(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const SearchAll: React.FC = () => {
|
export const SearchAll: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
|
|
||||||
const [query] = useQueryParam('query', StringParam);
|
const [query] = useQueryParam('query', StringParam);
|
||||||
const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD);
|
const searchString = useDebounce(query, TRIGGER_SEARCH_THRESHOLD);
|
||||||
@@ -236,5 +236,3 @@ const SearchAll: React.FC = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SearchAll;
|
|
||||||
|
|||||||
@@ -35,17 +35,17 @@ import ViewModuleIcon from '@mui/icons-material/ViewModule';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import LanguageIcon from '@mui/icons-material/Language';
|
import LanguageIcon from '@mui/icons-material/Language';
|
||||||
import CollectionsOutlinedBookmarkIcon from '@mui/icons-material/CollectionsBookmarkOutlined';
|
import CollectionsOutlinedBookmarkIcon from '@mui/icons-material/CollectionsBookmarkOutlined';
|
||||||
import requestManager from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { langCodeToName } from '@/util/language';
|
import { langCodeToName } from '@/util/language';
|
||||||
import useLocalStorage from '@/util/useLocalStorage';
|
import { useLocalStorage } from '@/util/useLocalStorage';
|
||||||
import ListItemLink from '@/components/util/ListItemLink';
|
import { ListItemLink } from '@/components/util/ListItemLink';
|
||||||
import DarkTheme from '@/components/context/DarkTheme';
|
import { DarkTheme } from '@/components/context/DarkTheme';
|
||||||
import NavbarContext from '@/components/context/NavbarContext';
|
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
|
||||||
|
|
||||||
export default function Settings() {
|
export function Settings() {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
|
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavBarContext);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTitle(t('settings.title'));
|
setTitle(t('settings.title'));
|
||||||
setAction(null);
|
setAction(null);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user