134 lines
5.4 KiB
TypeScript
134 lines
5.4 KiB
TypeScript
/*
|
|
* 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 CardActionArea from '@mui/material/CardActionArea';
|
|
import Button from '@mui/material/Button';
|
|
import Card from '@mui/material/Card';
|
|
import Typography from '@mui/material/Typography';
|
|
import React from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import Stack from '@mui/material/Stack';
|
|
import PushPinIcon from '@mui/icons-material/PushPin';
|
|
import PushPinOutlinedIcon from '@mui/icons-material/PushPinOutlined';
|
|
import IconButton from '@mui/material/IconButton';
|
|
import { useLingui } from '@lingui/react/macro';
|
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
|
import type { GetSourcesListQuery } from '@/lib/graphql/generated/graphql.ts';
|
|
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
|
import { MUIUtil } from '@/lib/mui/MUI.util.ts';
|
|
import { Sources } from '@/features/source/services/Sources.ts';
|
|
import { ListCardAvatar } from '@/base/components/lists/cards/ListCardAvatar.tsx';
|
|
import { ListCardContent } from '@/base/components/lists/cards/ListCardContent.tsx';
|
|
import { CustomTooltip } from '@/base/components/CustomTooltip.tsx';
|
|
import { createUpdateSourceMetadata, useGetSourceMetadata } from '@/features/source/services/SourceMetadata.ts';
|
|
import { makeToast } from '@/base/utils/Toast.ts';
|
|
import { getErrorMessage } from '@/lib/HelperFunctions.ts';
|
|
import { languageCodeToName } from '@/base/utils/Languages.ts';
|
|
import { SourceContentType } from '@/features/source/Source.types.ts';
|
|
|
|
interface IProps {
|
|
source: GetSourcesListQuery['sources']['nodes'][number];
|
|
showSourceRepo: boolean;
|
|
showLanguage: boolean;
|
|
}
|
|
|
|
export const SourceCard: React.FC<IProps> = (props: IProps) => {
|
|
const { t } = useLingui();
|
|
|
|
const { source, showSourceRepo, showLanguage } = props;
|
|
const {
|
|
id,
|
|
name,
|
|
lang,
|
|
iconUrl,
|
|
supportsLatest,
|
|
isNsfw,
|
|
extension: { repo },
|
|
} = source;
|
|
|
|
const { isPinned } = useGetSourceMetadata(source);
|
|
|
|
const sourceName = Sources.isLocalSource(source) ? t`Local source` : name;
|
|
|
|
const updateSetting = createUpdateSourceMetadata(source, (e) =>
|
|
makeToast(t`Failed to save changes`, 'error', getErrorMessage(e)),
|
|
);
|
|
|
|
return (
|
|
<Card>
|
|
<CardActionArea
|
|
component={Link}
|
|
to={AppRoutes.sources.children.browse.path(id)}
|
|
state={AppRoutes.sources.children.browse.state({
|
|
contentType: SourceContentType.POPULAR,
|
|
clearCache: true,
|
|
})}
|
|
>
|
|
<ListCardContent>
|
|
<ListCardAvatar
|
|
iconUrl={requestManager.getValidImgUrlFor(iconUrl)}
|
|
alt={sourceName}
|
|
slots={{
|
|
spinnerImageProps: {
|
|
ignoreQueue: true,
|
|
},
|
|
}}
|
|
/>
|
|
<Stack
|
|
sx={{
|
|
justifyContent: 'center',
|
|
flexGrow: 1,
|
|
flexShrink: 1,
|
|
wordBreak: 'break-word',
|
|
}}
|
|
>
|
|
<Typography variant="h6" component="h3">
|
|
{sourceName}
|
|
</Typography>
|
|
<Typography variant="caption">
|
|
{showLanguage && languageCodeToName(lang)}
|
|
{isNsfw && (
|
|
<Typography variant="caption" color="error">
|
|
{' 18+'}
|
|
</Typography>
|
|
)}
|
|
</Typography>
|
|
{showSourceRepo && <Typography variant="caption">{repo}</Typography>}
|
|
</Stack>
|
|
{supportsLatest && (
|
|
<Button
|
|
{...MUIUtil.preventRippleProp()}
|
|
variant="outlined"
|
|
component={Link}
|
|
to={AppRoutes.sources.children.browse.path(id)}
|
|
state={AppRoutes.sources.children.browse.state({
|
|
contentType: SourceContentType.LATEST,
|
|
clearCache: true,
|
|
})}
|
|
>
|
|
{t`Latest`}
|
|
</Button>
|
|
)}
|
|
<CustomTooltip title={isPinned ? t`Unpin source` : t`Pin source`}>
|
|
<IconButton
|
|
{...MUIUtil.preventRippleProp()}
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
updateSetting('isPinned', !isPinned);
|
|
}}
|
|
color={isPinned ? 'primary' : 'inherit'}
|
|
>
|
|
{isPinned ? <PushPinIcon /> : <PushPinOutlinedIcon />}
|
|
</IconButton>
|
|
</CustomTooltip>
|
|
</ListCardContent>
|
|
</CardActionArea>
|
|
</Card>
|
|
);
|
|
};
|