Move core files into new folder

This commit is contained in:
schroda
2024-10-05 16:09:34 +02:00
parent 996bb62888
commit 23a86a77f0
173 changed files with 514 additions and 481 deletions

View File

@@ -0,0 +1,16 @@
/*
* 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 { styled } from '@mui/material/styles';
export const CheckboxContainer = styled('div')({
display: 'flex',
flexDirection: 'column',
maxHeight: '170px',
overflow: 'auto',
});

View File

@@ -0,0 +1,19 @@
/*
* 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 Checkbox, { CheckboxProps } from '@mui/material/Checkbox';
import FormControlLabel from '@mui/material/FormControlLabel';
import React from 'react';
interface IProps extends CheckboxProps {
label?: string;
}
export const CheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
<FormControlLabel control={<Checkbox {...rest} />} label={label} sx={sx} />
);

View File

@@ -0,0 +1,122 @@
/*
* 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 React, { useState } from 'react';
import Button from '@mui/material/Button';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import Dialog from '@mui/material/Dialog';
import Switch from '@mui/material/Switch';
import IconButton from '@mui/material/IconButton';
import FilterListIcon from '@mui/icons-material/FilterList';
import List from '@mui/material/List';
import ListItemText from '@mui/material/ListItemText';
import Tooltip from '@mui/material/Tooltip';
import ListItem from '@mui/material/ListItem';
import { useTranslation } from 'react-i18next';
import { cloneObject } from '@/util/cloneObject.tsx';
import { translateExtensionLanguage } from '@/screens/util/Extensions.ts';
function removeAll(firstList: any[], secondList: any[]) {
secondList.forEach((item) => {
const index = firstList.indexOf(item);
if (index !== -1) {
firstList.splice(index, 1);
}
});
return firstList;
}
interface IProps {
shownLangs: string[];
setShownLangs: (arg0: string[]) => void;
allLangs: string[];
forcedLangs?: string[];
}
export function LangSelect(props: IProps) {
const { t } = useTranslation();
const { shownLangs, setShownLangs, allLangs, forcedLangs = [] } = props;
// hold a copy and only sate state on parent when OK pressed, improves performance
const [mShownLangs, setMShownLangs] = useState(removeAll(cloneObject(shownLangs), forcedLangs));
const [open, setOpen] = useState<boolean>(false);
const handleCancel = () => {
setOpen(false);
};
const handleOk = () => {
setOpen(false);
setShownLangs(mShownLangs);
};
const handleChange = (event: React.ChangeEvent<HTMLInputElement>, lang: string) => {
const { checked } = event.target as HTMLInputElement;
if (checked) {
setMShownLangs([...mShownLangs, lang]);
} else {
const clone = cloneObject(mShownLangs);
clone.splice(clone.indexOf(lang), 1);
setMShownLangs(clone);
}
};
return (
<>
<Tooltip title={t('settings.title')}>
<IconButton
onClick={() => setOpen(true)}
aria-label="display more actions"
edge="end"
color="inherit"
size="large"
>
<FilterListIcon />
</IconButton>
</Tooltip>
<Dialog
sx={{
'.MuiDialog-paper': {
maxHeight: 435,
width: '80%',
},
}}
maxWidth="xs"
open={open}
>
<DialogTitle>{t('global.language.title.enabled_languages')}</DialogTitle>
<DialogContent dividers sx={{ padding: 0 }}>
<List>
{allLangs.map((lang) => (
<ListItem key={lang}>
<ListItemText primary={translateExtensionLanguage(lang)} />
<Switch
checked={mShownLangs.indexOf(lang) !== -1}
onChange={(e) => handleChange(e, lang)}
/>
</ListItem>
))}
</List>
</DialogContent>
<DialogActions>
<Button autoFocus onClick={handleCancel} color="primary">
{t('global.button.cancel')}
</Button>
<Button onClick={handleOk} color="primary">
{t('global.button.ok')}
</Button>
</DialogActions>
</Dialog>
</>
);
}

View File

@@ -0,0 +1,47 @@
/*
* 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 InputAdornment from '@mui/material/InputAdornment';
import TextField, { TextFieldProps } from '@mui/material/TextField';
import { useState } from 'react';
import IconButton from '@mui/material/IconButton';
import Visibility from '@mui/icons-material/Visibility';
import VisibilityOff from '@mui/icons-material/VisibilityOff';
import { useTranslation } from 'react-i18next';
export const PasswordTextField = (props: TextFieldProps) => {
const { t } = useTranslation();
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword((show) => !show);
return (
<TextField
id="password"
name="password"
label={t('global.label.password')}
type={showPassword ? 'text' : 'password'}
slotProps={{
input: {
endAdornment: (
<InputAdornment position="start">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
edge="end"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
},
}}
{...props}
/>
);
};

View File

@@ -0,0 +1,19 @@
/*
* 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 FormControlLabel from '@mui/material/FormControlLabel';
import Radio, { RadioProps } from '@mui/material/Radio';
import React from 'react';
export interface RadioInputProps extends RadioProps {
label?: string;
}
export const RadioInput: React.FC<RadioInputProps> = ({ label, sx, ...rest }) => (
<FormControlLabel control={<Radio {...rest} />} label={label} sx={sx} />
);

View File

@@ -0,0 +1,37 @@
/*
* 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 TextField, { TextFieldProps } from '@mui/material/TextField';
import IconButton, { IconButtonProps } from '@mui/material/IconButton';
import InputAdornment from '@mui/material/InputAdornment';
import CancelIcon from '@mui/icons-material/Cancel';
export const SearchTextField = ({
onCancel,
cancelButtonProps,
...textFieldProps
}: TextFieldProps & { onCancel: () => void; cancelButtonProps?: IconButtonProps }) => (
<TextField
{...textFieldProps}
slotProps={{
input: {
...textFieldProps.InputProps,
sx: {
color: 'inherit',
},
endAdornment: textFieldProps.InputProps?.endAdornment ?? (
<InputAdornment position="end">
<IconButton {...cancelButtonProps} onClick={() => onCancel()}>
<CancelIcon />
</IconButton>
</InputAdornment>
),
},
}}
/>
);

View File

@@ -0,0 +1,19 @@
/*
* 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 MuiSelect from '@mui/material/Select';
export const Select = <Value,>({
children,
maxSelectionHeightPx = 250,
...props
}: React.ComponentProps<typeof MuiSelect<Value>> & { maxSelectionHeightPx?: number }) => (
<MuiSelect<Value> MenuProps={{ PaperProps: { style: { maxHeight: maxSelectionHeightPx } } }} {...props}>
{children}
</MuiSelect>
);

View File

@@ -0,0 +1,23 @@
/*
* 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 ArrowDownward from '@mui/icons-material/ArrowDownward';
import ArrowUpward from '@mui/icons-material/ArrowUpward';
import { memo } from 'react';
import { RadioInput, RadioInputProps } from '@/modules/core/components/inputs/RadioInput.tsx';
interface IProps extends RadioInputProps {
sortDescending?: boolean | null | undefined;
}
export const SortRadioInput = memo(({ sortDescending, ...rest }: IProps) => (
<RadioInput
checkedIcon={sortDescending ? <ArrowDownward color="primary" /> : <ArrowUpward color="primary" />}
{...rest}
/>
));

View File

@@ -0,0 +1,48 @@
/*
* 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 DisabledByDefaultRounded from '@mui/icons-material/DisabledByDefaultRounded';
import Checkbox, { CheckboxProps } from '@mui/material/Checkbox';
import React, { useCallback } from 'react';
type CheckState = boolean | undefined | null;
function nextState(state: CheckState): CheckState {
if (state === true) return false;
if (state === false) return undefined;
return true;
}
export interface ThreeStateCheckboxProps extends Omit<CheckboxProps, 'checked' | 'onChange'> {
checked?: boolean | undefined | null;
onChange?: (checked: boolean | undefined | null) => void;
}
/**
* When checked is true, checkbox contains checkmark
* When checked is false, checkbox contains cross
* When checked is null or undefined, checkbox is empty
*/
export const ThreeStateCheckbox: React.FC<ThreeStateCheckboxProps> = ({ checked, onChange, ...rest }) => {
const handleChange = useCallback(() => {
if (onChange) {
const newState = nextState(checked);
onChange(newState);
}
}, [onChange]);
return (
<Checkbox
indeterminateIcon={<DisabledByDefaultRounded />}
checked={checked === true}
indeterminate={checked === false}
onChange={handleChange}
{...rest}
/>
);
};

View File

@@ -0,0 +1,19 @@
/*
* 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 FormControlLabel from '@mui/material/FormControlLabel';
import React from 'react';
import { ThreeStateCheckbox, ThreeStateCheckboxProps } from '@/modules/core/components/inputs/ThreeStateCheckbox.tsx';
interface IProps extends ThreeStateCheckboxProps {
label?: string;
}
export const ThreeStateCheckboxInput: React.FC<IProps> = ({ label, sx, ...rest }) => (
<FormControlLabel control={<ThreeStateCheckbox {...rest} />} label={label} sx={sx} />
);