Add manga fetch timestamp to thumbnail url (#598)

In case the fetch timestamp of a manga changed, it's possible that the thumbnail has changed as well, thus, the currently cached image should be ignored
This commit is contained in:
schroda
2024-02-16 19:38:13 +01:00
committed by GitHub
parent 2acf2b6d33
commit c099e01fb7
5 changed files with 13 additions and 19 deletions

View File

@@ -24,6 +24,7 @@ import { MangaOptionButton } from '@/components/manga/MangaOptionButton.tsx';
import { MangaActionMenuItems, SingleModeProps } from '@/components/manga/MangaActionMenuItems.tsx'; import { MangaActionMenuItems, SingleModeProps } from '@/components/manga/MangaActionMenuItems.tsx';
import { Menu } from '@/components/menu/Menu.tsx'; import { Menu } from '@/components/menu/Menu.tsx';
import { MigrateDialog } from '@/components/MigrateDialog.tsx'; import { MigrateDialog } from '@/components/MigrateDialog.tsx';
import { Mangas } from '@/lib/data/Mangas.ts';
const BottomGradient = styled('div')({ const BottomGradient = styled('div')({
position: 'absolute', position: 'absolute',
@@ -96,17 +97,8 @@ export const MangaCard = (props: MangaCardProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { manga, gridLayout, inLibraryIndicator, selected, handleSelection, mode = 'default' } = props; const { manga, gridLayout, inLibraryIndicator, selected, handleSelection, mode = 'default' } = props;
const { const { id, title, downloadCount, unreadCount: unread, inLibrary, latestReadChapter, chapters } = manga;
id, const thumbnailUrl = Mangas.getThumbnailUrl(manga);
title,
thumbnailUrl: tmpThumbnailUrl,
downloadCount,
unreadCount: unread,
inLibrary,
latestReadChapter,
chapters,
} = manga;
const thumbnailUrl = tmpThumbnailUrl ?? 'nonExistingMangaUrl';
const { const {
options: { showContinueReadingButton, showUnreadBadge, showDownloadBadge }, options: { showContinueReadingButton, showUnreadBadge, showDownloadBadge },
} = useLibraryOptionsContext(); } = useLibraryOptionsContext();

View File

@@ -19,6 +19,7 @@ import { requestManager } from '@/lib/requests/RequestManager.ts';
import { makeToast } from '@/components/util/Toast'; import { makeToast } from '@/components/util/Toast';
import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts'; import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts';
import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx'; import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx';
import { Mangas } from '@/lib/data/Mangas.ts';
const DetailsWrapper = styled('div')(({ theme }) => ({ const DetailsWrapper = styled('div')(({ theme }) => ({
width: '100%', width: '100%',
@@ -215,9 +216,7 @@ export const MangaDetails: React.FC<IProps> = ({ manga }) => {
<TopContentWrapper> <TopContentWrapper>
<ThumbnailMetadataWrapper> <ThumbnailMetadataWrapper>
<Thumbnail> <Thumbnail>
{manga.thumbnailUrl && ( {manga.thumbnailUrl && <img src={Mangas.getThumbnailUrl(manga)} alt="Manga Thumbnail" />}
<img src={requestManager.getValidImgUrlFor(manga.thumbnailUrl)} alt="Manga Thumbnail" />
)}
</Thumbnail> </Thumbnail>
<Metadata> <Metadata>
<h1>{manga.title}</h1> <h1>{manga.title}</h1>

View File

@@ -99,6 +99,8 @@ export const actionToTranslationKey: {
export type MangaChapterCountInfo = { chapters: Pick<TManga['chapters'], 'totalCount'> }; export type MangaChapterCountInfo = { chapters: Pick<TManga['chapters'], 'totalCount'> };
export type MangaDownloadInfo = Pick<TManga, 'downloadCount'> & MangaChapterCountInfo; export type MangaDownloadInfo = Pick<TManga, 'downloadCount'> & MangaChapterCountInfo;
export type MangaUnreadInfo = Pick<TManga, 'unreadCount'> & MangaChapterCountInfo; export type MangaUnreadInfo = Pick<TManga, 'unreadCount'> & MangaChapterCountInfo;
export type MangaLastFetchedInfo = Pick<TManga, 'lastFetchedAt'>;
export type MangaThumbnailInfo = Pick<TManga, 'thumbnailUrl'>;
export type MigrateMode = 'copy' | 'migrate'; export type MigrateMode = 'copy' | 'migrate';
@@ -171,6 +173,10 @@ export class Mangas {
return mangas.filter(Mangas.isPartiallyRead); return mangas.filter(Mangas.isPartiallyRead);
} }
static getThumbnailUrl(manga: MangaLastFetchedInfo & Partial<MangaThumbnailInfo>): string {
return manga.thumbnailUrl ? `${manga.thumbnailUrl}?fetchedAt=${manga.lastFetchedAt}` : 'nonExistingMangaUrl';
}
static async getChapterIdsWithState( static async getChapterIdsWithState(
mangaIds: number[], mangaIds: number[],
state: Pick<ChapterConditionInput, 'isRead' | 'isDownloaded' | 'isBookmarked'>, state: Pick<ChapterConditionInput, 'isRead' | 'isDownloaded' | 'isBookmarked'>,

View File

@@ -1499,10 +1499,6 @@ export class RequestManager {
return this.doRequest(GQLMethod.USE_QUERY, GET_MIGRATABLE_SOURCE_MANGAS, { sourceId }, options); return this.doRequest(GQLMethod.USE_QUERY, GET_MIGRATABLE_SOURCE_MANGAS, { sourceId }, options);
} }
public getMangaThumbnailUrl(mangaId: number): string {
return this.getValidImgUrlFor(`manga/${mangaId}/thumbnail`);
}
public useUpdateMangaCategories( public useUpdateMangaCategories(
options?: MutationHookOptions<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables>, options?: MutationHookOptions<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables>,
): AbortableApolloUseMutationResponse<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables> { ): AbortableApolloUseMutationResponse<UpdateMangaCategoriesMutation, UpdateMangaCategoriesMutationVariables> {

View File

@@ -28,6 +28,7 @@ import { UpdateChecker } from '@/components/library/UpdateChecker.tsx';
import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuoso.tsx'; import { StyledGroupedVirtuoso } from '@/components/virtuoso/StyledGroupedVirtuoso.tsx';
import { StyledGroupHeader } from '@/components/virtuoso/StyledGroupHeader.tsx'; import { StyledGroupHeader } from '@/components/virtuoso/StyledGroupHeader.tsx';
import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx'; import { StyledGroupItemWrapper } from '@/components/virtuoso/StyledGroupItemWrapper.tsx';
import { Mangas } from '@/lib/data/Mangas.ts';
function epochToDate(epoch: number) { function epochToDate(epoch: number) {
const date = new Date(0); // The 0 there is the key, which sets the date to the epoch const date = new Date(0); // The 0 there is the key, which sets the date to the epoch
@@ -200,7 +201,7 @@ export const Updates: React.FC = () => {
marginRight: 2, marginRight: 2,
imageRendering: 'pixelated', imageRendering: 'pixelated',
}} }}
src={requestManager.getValidImgUrlFor(manga.thumbnailUrl ?? '')} src={Mangas.getThumbnailUrl(manga)}
/> />
<Box sx={{ display: 'flex', flexDirection: 'column' }}> <Box sx={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2"> <Typography variant="h5" component="h2">