Files
suwayomi-material-you-webui/src/features/tracker/components/cards/SettingsTrackerCard.tsx

157 lines
6.9 KiB
TypeScript
Raw Normal View History

2024-02-16 19:55:54 +01:00
/*
* 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 { useTranslation } from 'react-i18next';
import { useState } from 'react';
import PopupState, { bindDialog, bindTrigger } from 'material-ui-popup-state';
import ListItemButton from '@mui/material/ListItemButton';
import Chip from '@mui/material/Chip';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
2024-02-16 19:55:54 +01:00
import Avatar from '@mui/material/Avatar';
import ListItemText from '@mui/material/ListItemText';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import TextField from '@mui/material/TextField';
import DialogActions from '@mui/material/DialogActions';
import Button from '@mui/material/Button';
import { PasswordTextField } from '@/base/components/inputs/PasswordTextField.tsx';
import { makeToast } from '@/base/utils/Toast.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts';
2025-08-15 22:02:58 +02:00
import { Trackers } from '@/features/tracker/services/Trackers.ts';
2024-12-20 17:24:40 +01:00
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
import { useLocalStorage } from '@/base/hooks/useStorage.tsx';
2025-08-15 22:02:58 +02:00
import { TTrackerSearch } from '@/features/tracker/Tracker.types.ts';
2024-02-16 19:55:54 +01:00
export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) => {
2024-02-16 19:55:54 +01:00
const { t } = useTranslation();
2025-08-02 23:13:50 +02:00
const [serverAddress] = useLocalStorage('serverBaseURL', import.meta.env.VITE_SERVER_URL_DEFAULT);
2024-02-16 19:55:54 +01:00
const [loginTrackerCredentials, { loading: isCredentialLoginInProgress }] =
requestManager.useLoginToTrackerCredentials();
const [logoutFromTracker] = requestManager.useLogoutFromTracker();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const isOAuthLogin = !tracker.isLoggedIn && !!tracker.authUrl;
const handleLogout = async () => {
try {
await logoutFromTracker({ variables: { trackerId: tracker.id } });
} catch (e) {
2024-12-20 17:24:40 +01:00
makeToast(t('tracking.action.logout.label.failure', { name: tracker.name }), 'error', getErrorMessage(e));
2024-02-16 19:55:54 +01:00
}
};
const handleLogin = async () => {
if (isOAuthLogin) {
const state = {
redirectUrl: `${serverAddress}/tracker/login/oauth`,
2024-02-16 19:55:54 +01:00
clientName: 'Suwayomi-WebUI',
trackerId: tracker.id,
trackerName: tracker.name,
};
window.open(`${tracker.authUrl}&state=${JSON.stringify(state)}`, '_self');
return;
}
try {
await loginTrackerCredentials({ variables: { input: { trackerId: tracker.id, username, password } } });
} catch (e) {
2024-12-20 17:24:40 +01:00
makeToast(t('tracking.action.login.label.failure', { name: tracker.name }), 'error', getErrorMessage(e));
2024-02-16 19:55:54 +01:00
}
};
2024-03-10 17:36:22 +01:00
const onClick = (openPopup: () => void) => {
if (!isOAuthLogin) {
openPopup();
return;
}
handleLogin();
};
2024-02-16 19:55:54 +01:00
return (
<PopupState variant="popover" popupId="tracker-dialog">
{(popupState) => (
<>
<ListItemButton {...bindTrigger(popupState)} onClick={() => onClick(popupState.open)}>
2024-02-16 19:55:54 +01:00
<ListItemAvatar sx={{ paddingRight: '20px' }}>
<Avatar
alt={`${tracker.name}`}
src={requestManager.getValidImgUrlFor(tracker.icon)}
variant="rounded"
sx={{ width: 64, height: 64 }}
/>
</ListItemAvatar>
<ListItemText primary={tracker.name} />
{Trackers.isLoggedIn(tracker) && (
2024-02-16 19:55:54 +01:00
<ListItemSecondaryAction>
<Chip label={t('global.label.logged_in')} color="success" />
</ListItemSecondaryAction>
)}
</ListItemButton>
<Dialog
{...bindDialog(popupState)}
open={(Trackers.isLoggedIn(tracker) || !tracker.authUrl) && popupState.isOpen}
2024-02-16 19:55:54 +01:00
disableRestoreFocus
>
<DialogTitle>
{t(
Trackers.isLoggedIn(tracker)
2024-02-16 19:55:54 +01:00
? 'tracking.settings.dialog.title.log_out'
: 'tracking.settings.dialog.title.log_in',
{ name: tracker.name },
)}
</DialogTitle>
{!isOAuthLogin && !tracker.isLoggedIn && (
<DialogContent>
<TextField
autoFocus
margin="dense"
id="username"
name="username"
label={t('global.label.username')}
type="text"
fullWidth
variant="standard"
onChange={(e) => setUsername(e.target.value)}
/>
<PasswordTextField
margin="dense"
fullWidth
variant="standard"
onChange={(e) => setPassword(e.target.value)}
/>
</DialogContent>
)}
<DialogActions>
<Button onClick={popupState.close}>{t('global.button.cancel')}</Button>
<Button
variant="contained"
disabled={
!isOAuthLogin &&
!tracker.isLoggedIn &&
(isCredentialLoginInProgress || !username.length || !password.length)
}
onClick={() => (Trackers.isLoggedIn(tracker) ? handleLogout() : handleLogin())}
2024-02-16 19:55:54 +01:00
>
{t(Trackers.isLoggedIn(tracker) ? 'global.button.log_out' : 'global.button.log_in')}
2024-02-16 19:55:54 +01:00
</Button>
</DialogActions>
</Dialog>
</>
)}
</PopupState>
);
};