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 ListItemButton from '@mui/material/ListItemButton';
|
2024-04-14 15:50:12 +02:00
|
|
|
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 ListItemText from '@mui/material/ListItemText';
|
2026-01-10 19:45:02 +01:00
|
|
|
import { useLingui } from '@lingui/react/macro';
|
2025-08-16 02:48:46 +02:00
|
|
|
import { makeToast } from '@/base/utils/Toast.ts';
|
2024-10-06 01:27:51 +02:00
|
|
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
2025-08-15 22:02:58 +02:00
|
|
|
import { Trackers } from '@/features/tracker/services/Trackers.ts';
|
2025-12-06 12:59:39 -06:00
|
|
|
import { getErrorMessage, noOp } from '@/lib/HelperFunctions.ts';
|
2025-08-15 22:02:58 +02:00
|
|
|
import { TTrackerSearch } from '@/features/tracker/Tracker.types.ts';
|
2025-07-27 00:03:51 +02:00
|
|
|
import { AvatarSpinner } from '@/base/components/AvatarSpinner.tsx';
|
2025-12-06 12:59:39 -06:00
|
|
|
import { CredentialsLogin } from '@/base/components/modals/LoginDialog.tsx';
|
2024-02-16 19:55:54 +01:00
|
|
|
|
2024-07-04 22:00:39 +02:00
|
|
|
export const SettingsTrackerCard = ({ tracker }: { tracker: TTrackerSearch }) => {
|
2026-01-10 19:45:02 +01:00
|
|
|
const { t } = useLingui();
|
2024-02-16 19:55:54 +01:00
|
|
|
|
|
|
|
|
const isOAuthLogin = !tracker.isLoggedIn && !!tracker.authUrl;
|
|
|
|
|
|
|
|
|
|
const handleLogout = async () => {
|
|
|
|
|
try {
|
2025-12-06 12:59:39 -06:00
|
|
|
await requestManager.logoutFromTracker(tracker.id).response;
|
2024-02-16 19:55:54 +01:00
|
|
|
} catch (e) {
|
2026-01-10 19:45:02 +01:00
|
|
|
makeToast(t`Could not log out from ${tracker.name}`, 'error', getErrorMessage(e));
|
2024-02-16 19:55:54 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-12-06 12:59:39 -06:00
|
|
|
const handleLogin = async (username: string, password: string) => {
|
2024-02-16 19:55:54 +01:00
|
|
|
if (isOAuthLogin) {
|
|
|
|
|
const state = {
|
2025-10-19 20:17:07 +02:00
|
|
|
redirectUrl: `${window.location.origin}/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 {
|
2025-12-06 12:59:39 -06:00
|
|
|
await requestManager.loginTrackerCredentials(tracker.id, username, password).response;
|
2024-02-16 19:55:54 +01:00
|
|
|
} catch (e) {
|
2026-01-10 19:45:02 +01:00
|
|
|
makeToast(t`Could not log in to ${tracker.name}`, 'error', getErrorMessage(e));
|
2024-02-16 19:55:54 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-12-06 12:59:39 -06:00
|
|
|
const login = async (initialUsername?: string, initialPassword?: string) => {
|
|
|
|
|
if (isOAuthLogin) {
|
|
|
|
|
const state = {
|
|
|
|
|
redirectUrl: `${window.location.origin}/tracker/login/oauth`,
|
|
|
|
|
clientName: 'Suwayomi-WebUI',
|
|
|
|
|
trackerId: tracker.id,
|
|
|
|
|
trackerName: tracker.name,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.open(`${tracker.authUrl}&state=${JSON.stringify(state)}`, '_self');
|
2024-03-10 17:36:22 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-06 12:59:39 -06:00
|
|
|
const controlled = CredentialsLogin.showControlled(
|
|
|
|
|
{
|
2026-01-10 19:45:02 +01:00
|
|
|
title: Trackers.isLoggedIn(tracker) ? t`Log out from ${tracker.name}` : t`Log in to ${tracker.name}`,
|
2025-12-06 12:59:39 -06:00
|
|
|
isLoading: false,
|
|
|
|
|
isLoggedIn: Trackers.isLoggedIn(tracker),
|
|
|
|
|
username: initialUsername,
|
|
|
|
|
password: initialPassword,
|
|
|
|
|
loginLogout: async (username, password) => {
|
|
|
|
|
controlled.update({
|
|
|
|
|
isLoading: true,
|
|
|
|
|
loginLogout: noOp,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (Trackers.isLoggedIn(tracker)) {
|
|
|
|
|
try {
|
|
|
|
|
await handleLogout();
|
|
|
|
|
|
|
|
|
|
controlled.submit();
|
|
|
|
|
} catch (e) {
|
2026-01-10 19:45:02 +01:00
|
|
|
makeToast(t`Could not log out from ${tracker.name}`, 'error', getErrorMessage(e));
|
2025-12-06 12:59:39 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await handleLogin(username, password);
|
|
|
|
|
|
|
|
|
|
controlled.submit();
|
|
|
|
|
} catch (e) {
|
2026-01-10 19:45:02 +01:00
|
|
|
makeToast(t`Could not log in to ${tracker.name}`, 'error', getErrorMessage(e));
|
2025-12-06 12:59:39 -06:00
|
|
|
|
|
|
|
|
const RETRY_KEY = '__retry__';
|
|
|
|
|
const retry = await Promise.race([controlled.promise, Promise.resolve(RETRY_KEY)]);
|
|
|
|
|
if (retry === RETRY_KEY) {
|
|
|
|
|
login(username, password);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{ id: 'tracker-login-dialog' },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await controlled.promise;
|
2024-03-10 17:36:22 +01:00
|
|
|
};
|
|
|
|
|
|
2024-02-16 19:55:54 +01:00
|
|
|
return (
|
2025-12-06 12:59:39 -06:00
|
|
|
<ListItemButton onClick={() => login()}>
|
|
|
|
|
<ListItemAvatar sx={{ paddingRight: '20px' }}>
|
|
|
|
|
<AvatarSpinner
|
|
|
|
|
alt={`${tracker.name}`}
|
|
|
|
|
iconUrl={requestManager.getValidImgUrlFor(tracker.icon)}
|
|
|
|
|
slots={{
|
|
|
|
|
avatarProps: {
|
|
|
|
|
variant: 'rounded',
|
|
|
|
|
sx: { width: 64, height: 64 },
|
|
|
|
|
},
|
|
|
|
|
spinnerImageProps: {
|
|
|
|
|
ignoreQueue: true,
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</ListItemAvatar>
|
|
|
|
|
<ListItemText primary={tracker.name} />
|
|
|
|
|
{Trackers.isLoggedIn(tracker) && (
|
|
|
|
|
<ListItemSecondaryAction>
|
2026-01-10 19:45:02 +01:00
|
|
|
<Chip label={t`Logged in`} color="success" />
|
2025-12-06 12:59:39 -06:00
|
|
|
</ListItemSecondaryAction>
|
2024-02-16 19:55:54 +01:00
|
|
|
)}
|
2025-12-06 12:59:39 -06:00
|
|
|
</ListItemButton>
|
2024-02-16 19:55:54 +01:00
|
|
|
);
|
|
|
|
|
};
|