Update manga page styling
This commit is contained in:
@@ -8,14 +8,17 @@
|
||||
|
||||
import FavoriteIcon from '@mui/icons-material/Favorite';
|
||||
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
|
||||
import PublicIcon from '@mui/icons-material/Public';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import { ComponentProps, useEffect, useMemo } from 'react';
|
||||
import { ComponentProps, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { t as translate } from 'i18next';
|
||||
import Link from '@mui/material/Link';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { useLongPress } from 'use-long-press';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import LaunchIcon from '@mui/icons-material/Launch';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { makeToast } from '@/components/util/Toast';
|
||||
import { Mangas, MangaThumbnailInfo, MangaTrackRecordInfo } from '@/lib/data/Mangas.ts';
|
||||
import { SpinnerImage } from '@/components/util/SpinnerImage.tsx';
|
||||
@@ -27,132 +30,66 @@ import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts
|
||||
import { MangaType, SourceType } from '@/lib/graphql/generated/graphql.ts';
|
||||
|
||||
const DetailsWrapper = styled('div')(({ theme }) => ({
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(2),
|
||||
padding: theme.spacing(1),
|
||||
[theme.breakpoints.up('md')]: {
|
||||
position: 'sticky',
|
||||
top: '64px',
|
||||
left: '0px',
|
||||
width: '50vw',
|
||||
flexBasis: '40%',
|
||||
height: 'calc(100vh - 64px)',
|
||||
alignSelf: 'flex-start',
|
||||
overflowY: 'auto',
|
||||
},
|
||||
}));
|
||||
|
||||
const TopContentWrapper = styled('div')(() => ({
|
||||
padding: '10px',
|
||||
// [theme.breakpoints.up('md')]: {
|
||||
// minWidth: '50%',
|
||||
// },
|
||||
}));
|
||||
const TopContentWrapper = styled('div')(() => ({}));
|
||||
|
||||
const ThumbnailMetadataWrapper = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
}));
|
||||
|
||||
const Thumbnail = styled('div')(() => ({
|
||||
const Thumbnail = styled('div')(({ theme }) => ({
|
||||
'& img': {
|
||||
borderRadius: 4,
|
||||
maxWidth: '100%',
|
||||
minWidth: '100%',
|
||||
width: '150px',
|
||||
height: 'auto',
|
||||
},
|
||||
maxWidth: '50%',
|
||||
// [theme.breakpoints.up('md')]: {
|
||||
// minWidth: '100px',
|
||||
// },
|
||||
}));
|
||||
|
||||
const MetadataContainer = styled('div')(({ theme }) => ({
|
||||
marginLeft: 15,
|
||||
maxWidth: '100%',
|
||||
'& span': {
|
||||
fontWeight: '400',
|
||||
},
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
fontSize: '1.3em',
|
||||
},
|
||||
}));
|
||||
|
||||
const Metadata = (props: ComponentProps<typeof BaseMetadata>) => (
|
||||
<BaseMetadata {...props} titleProps={{ variant: 'h6' }} valueProps={{ variant: 'h6' }} />
|
||||
);
|
||||
|
||||
const MangaButtonsContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-around',
|
||||
'& button, a': {
|
||||
borderRadius: '25px',
|
||||
textTransform: 'none',
|
||||
paddingLeft: '20px',
|
||||
paddingRight: '20px',
|
||||
fontSize: 'x-large',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
fontSize: 'larger',
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
width: '200px',
|
||||
},
|
||||
[theme.breakpoints.up('xl')]: {
|
||||
width: '300px',
|
||||
},
|
||||
},
|
||||
}));
|
||||
const BottomContentWrapper = styled('div')(({ theme }) => ({
|
||||
paddingLeft: '10px',
|
||||
paddingRight: '10px',
|
||||
[theme.breakpoints.up('md')]: {
|
||||
fontSize: '1.2em',
|
||||
// maxWidth: '50%',
|
||||
},
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
fontSize: '1.3em',
|
||||
},
|
||||
|
||||
const MetadataContainer = styled('div')(({ theme }) => ({
|
||||
marginLeft: theme.spacing(1),
|
||||
}));
|
||||
const Description = styled('div')(() => ({
|
||||
'& h4': {
|
||||
marginTop: '1em',
|
||||
marginBottom: 0,
|
||||
},
|
||||
'& p': {
|
||||
textAlign: 'justify',
|
||||
textJustify: 'inter-word',
|
||||
},
|
||||
}));
|
||||
const Genres = styled('div')(() => ({
|
||||
|
||||
const Metadata = (props: ComponentProps<typeof BaseMetadata>) => <BaseMetadata {...props} />;
|
||||
|
||||
const MangaButtonsContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
'& h5': {
|
||||
border: '2px solid #2196f3',
|
||||
borderRadius: '1.13em',
|
||||
marginRight: '1em',
|
||||
marginTop: 0,
|
||||
marginBottom: '10px',
|
||||
padding: '0.3em',
|
||||
color: '#2196f3',
|
||||
},
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const OpenSourceButton = ({ url }: { url?: string | null }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const button = useMemo(
|
||||
() => (
|
||||
return (
|
||||
<Tooltip title={t('global.button.open_site')}>
|
||||
<CustomIconButton
|
||||
size="large"
|
||||
size="medium"
|
||||
disabled={!url}
|
||||
sx={{ color: 'inherit' }}
|
||||
component={Link}
|
||||
href={url ?? undefined}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
variant="outlined"
|
||||
>
|
||||
<PublicIcon />
|
||||
{t('global.button.open_site')}
|
||||
<LaunchIcon />
|
||||
</CustomIconButton>
|
||||
),
|
||||
[url],
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
if (!url) {
|
||||
return button;
|
||||
}
|
||||
|
||||
return button;
|
||||
};
|
||||
|
||||
function getSourceName(source?: Pick<SourceType, 'id' | 'displayName'> | null): string {
|
||||
@@ -167,6 +104,30 @@ function getValueOrUnknown(val?: string | null) {
|
||||
return val ?? translate('global.label.unknown');
|
||||
}
|
||||
|
||||
const DescriptionGenre = ({
|
||||
manga: { description, genre: genres },
|
||||
}: {
|
||||
manga: Pick<MangaType, 'description' | 'genre'>;
|
||||
}) => (
|
||||
<>
|
||||
<Typography style={{ whiteSpace: 'pre-line', textAlign: 'justify', textJustify: 'inter-word' }}>
|
||||
{description}
|
||||
</Typography>
|
||||
<Stack
|
||||
sx={{
|
||||
flexDirection: 'row',
|
||||
flexWrap: isCollapsed ? 'no-wrap' : 'wrap',
|
||||
gap: 1,
|
||||
overflowX: isCollapsed ? 'auto' : null,
|
||||
}}
|
||||
>
|
||||
{genres.map((genre) => (
|
||||
<Chip label={genre} variant="outlined" />
|
||||
))}
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
|
||||
export const MangaDetails = ({
|
||||
manga,
|
||||
}: {
|
||||
@@ -208,8 +169,8 @@ export const MangaDetails = ({
|
||||
</Thumbnail>
|
||||
<MetadataContainer>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h1"
|
||||
variant="h5"
|
||||
component="h2"
|
||||
sx={{ mb: 1, '@media not (pointer: fine)': { userSelect: 'none' } }}
|
||||
{...copyTitleLongPressBind()}
|
||||
>
|
||||
@@ -223,9 +184,9 @@ export const MangaDetails = ({
|
||||
</ThumbnailMetadataWrapper>
|
||||
<MangaButtonsContainer>
|
||||
<CustomIconButton
|
||||
size="medium"
|
||||
onClick={updateLibraryState}
|
||||
size="large"
|
||||
sx={{ color: manga.inLibrary ? '#2196f3' : 'inherit' }}
|
||||
variant={manga.inLibrary ? 'contained' : 'outlined'}
|
||||
>
|
||||
{manga.inLibrary ? <FavoriteIcon /> : <FavoriteBorderIcon />}
|
||||
{manga.inLibrary ? t('manga.button.in_library') : t('manga.button.add_to_library')}
|
||||
@@ -234,17 +195,7 @@ export const MangaDetails = ({
|
||||
<OpenSourceButton url={manga.realUrl} />
|
||||
</MangaButtonsContainer>
|
||||
</TopContentWrapper>
|
||||
<BottomContentWrapper>
|
||||
<Description>
|
||||
<h4>{t('settings.about.title')}</h4>
|
||||
<p style={{ whiteSpace: 'pre-line' }}>{manga.description}</p>
|
||||
</Description>
|
||||
<Genres>
|
||||
{manga.genre.map((g) => (
|
||||
<h5 key={g}>{g}</h5>
|
||||
))}
|
||||
</Genres>
|
||||
</BottomContentWrapper>
|
||||
<DescriptionGenre manga={manga} />
|
||||
</DetailsWrapper>
|
||||
{CategorySelectComponent}
|
||||
</>
|
||||
|
||||
@@ -52,11 +52,11 @@ export const TrackMangaButton = ({ manga }: { manga: MangaTrackRecordInfo & Pick
|
||||
<>
|
||||
<CustomIconButton
|
||||
{...bindTrigger(popupState)}
|
||||
size="medium"
|
||||
disabled={trackerList.loading || !!trackerList.error}
|
||||
onClick={() => handleClick(popupState.open)}
|
||||
onTouchStart={() => handleClick(popupState.open)}
|
||||
size="large"
|
||||
sx={{ color: trackersInUse.length ? '#2196f3' : 'inherit' }}
|
||||
variant={trackersInUse.length ? 'contained' : 'outlined'}
|
||||
>
|
||||
{trackersInUse.length ? <CheckIcon /> : <SyncIcon />}
|
||||
{trackersInUse.length
|
||||
|
||||
Reference in New Issue
Block a user