diff --git a/src/app/libraries/[libraryId]/page.tsx b/src/app/libraries/[libraryId]/page.tsx index c346a51..3731c57 100644 --- a/src/app/libraries/[libraryId]/page.tsx +++ b/src/app/libraries/[libraryId]/page.tsx @@ -1,6 +1,8 @@ import { PaginatedSeriesGrid } from "@/components/library/PaginatedSeriesGrid"; import { LibraryService } from "@/lib/services/library.service"; import { PreferencesService } from "@/lib/services/preferences.service"; +import { revalidatePath } from "next/cache"; +import { RefreshButton } from "@/components/library/RefreshButton"; interface PageProps { params: { libraryId: string }; @@ -9,6 +11,20 @@ interface PageProps { const PAGE_SIZE = 20; +async function refreshLibrary(libraryId: string) { + "use server"; + + try { + await LibraryService.clearLibrarySeriesCache(libraryId); + + revalidatePath(`/libraries/${libraryId}`); + return { success: true }; + } catch (error) { + console.error("Erreur lors du rafraîchissement:", error); + return { success: false, error: "Erreur lors du rafraîchissement de la bibliothèque" }; + } +} + async function getLibrarySeries(libraryId: string, page: number = 1, unreadOnly: boolean = false) { try { const pageIndex = page - 1; @@ -46,11 +62,14 @@ export default async function LibraryPage({ params, searchParams }: PageProps) {

{library.name}

- {series.totalElements > 0 && ( -

- {series.totalElements} série{series.totalElements > 1 ? "s" : ""} -

- )} +
+ {series.totalElements > 0 && ( +

+ {series.totalElements} série{series.totalElements > 1 ? "s" : ""} +

+ )} + +
-

Séries

+
+

Séries

+ +

{error instanceof Error ? error.message : "Erreur lors de la récupération des séries"} diff --git a/src/app/series/[seriesId]/page.tsx b/src/app/series/[seriesId]/page.tsx index 8ff71a4..429a9d2 100644 --- a/src/app/series/[seriesId]/page.tsx +++ b/src/app/series/[seriesId]/page.tsx @@ -2,6 +2,8 @@ import { PaginatedBookGrid } from "@/components/series/PaginatedBookGrid"; import { SeriesHeader } from "@/components/series/SeriesHeader"; import { SeriesService } from "@/lib/services/series.service"; import { PreferencesService } from "@/lib/services/preferences.service"; +import { revalidatePath } from "next/cache"; +import { RefreshButton } from "@/components/library/RefreshButton"; interface PageProps { params: { seriesId: string }; @@ -23,6 +25,20 @@ async function getSeriesBooks(seriesId: string, page: number = 1, unreadOnly: bo } } +async function refreshSeries(seriesId: string) { + "use server"; + + try { + await SeriesService.clearSeriesBooksCache(seriesId); + await SeriesService.clearSeriesCache(seriesId); + revalidatePath(`/series/${seriesId}`); + return { success: true }; + } catch (error) { + console.error("Erreur lors du rafraîchissement:", error); + return { success: false, error: "Erreur lors du rafraîchissement de la série" }; + } +} + export default async function SeriesPage({ params, searchParams }: PageProps) { const currentPage = searchParams.page ? parseInt(searchParams.page) : 1; const preferences = await PreferencesService.getPreferences(); @@ -36,7 +52,7 @@ export default async function SeriesPage({ params, searchParams }: PageProps) { return (

- + Promise<{ success: boolean; error?: string }>; +} + +export function RefreshButton({ libraryId, refreshLibrary }: RefreshButtonProps) { + const [isRefreshing, setIsRefreshing] = useState(false); + const { toast } = useToast(); + + const handleRefresh = async () => { + setIsRefreshing(true); + try { + const result = await refreshLibrary(libraryId); + + if (result.success) { + toast({ + title: "Bibliothèque rafraîchie", + description: "La bibliothèque a été rafraîchie avec succès", + }); + } else { + throw new Error(result.error); + } + } catch (error) { + toast({ + variant: "destructive", + title: "Erreur", + description: error instanceof Error ? error.message : "Une erreur est survenue", + }); + } finally { + setIsRefreshing(false); + } + }; + + return ( + + ); +} diff --git a/src/components/series/SeriesHeader.tsx b/src/components/series/SeriesHeader.tsx index a6b441d..cdfdfe3 100644 --- a/src/components/series/SeriesHeader.tsx +++ b/src/components/series/SeriesHeader.tsx @@ -6,12 +6,14 @@ import { useState, useEffect } from "react"; import { Button } from "../ui/button"; import { useToast } from "@/components/ui/use-toast"; import { Cover } from "@/components/ui/cover"; +import { RefreshButton } from "@/components/library/RefreshButton"; interface SeriesHeaderProps { series: KomgaSeries; + refreshSeries: (seriesId: string) => Promise<{ success: boolean; error?: string }>; } -export const SeriesHeader = ({ series }: SeriesHeaderProps) => { +export const SeriesHeader = ({ series, refreshSeries }: SeriesHeaderProps) => { const { toast } = useToast(); const [isFavorite, setIsFavorite] = useState(false); @@ -148,6 +150,7 @@ export const SeriesHeader = ({ series }: SeriesHeaderProps) => { )} +
diff --git a/src/lib/services/library.service.ts b/src/lib/services/library.service.ts index 101c4f1..f322883 100644 --- a/src/lib/services/library.service.ts +++ b/src/lib/services/library.service.ts @@ -1,6 +1,7 @@ import { BaseApiService } from "./base-api.service"; import { Library, LibraryResponse } from "@/types/library"; import { Series } from "@/types/series"; +import { serverCacheService } from "./server-cache.service"; export class LibraryService extends BaseApiService { static async getLibraries(): Promise { @@ -53,4 +54,8 @@ export class LibraryService extends BaseApiService { return this.handleError(error, "Impossible de récupérer les séries"); } } + + static async clearLibrarySeriesCache(libraryId: string) { + serverCacheService.delete(`library-${libraryId}-series`); + } } diff --git a/src/lib/services/series.service.ts b/src/lib/services/series.service.ts index 19c47a3..74b39ce 100644 --- a/src/lib/services/series.service.ts +++ b/src/lib/services/series.service.ts @@ -4,6 +4,7 @@ import { KomgaBook, KomgaSeries } from "@/types/komga"; import { BookService } from "./book.service"; import { ImageService } from "./image.service"; import { PreferencesService } from "./preferences.service"; +import { serverCacheService } from "./server-cache.service"; export class SeriesService extends BaseApiService { static async getSeries(seriesId: string): Promise { @@ -22,6 +23,10 @@ export class SeriesService extends BaseApiService { } } + static async clearSeriesCache(seriesId: string) { + serverCacheService.delete(`series-${seriesId}`); + } + static async getSeriesBooks( seriesId: string, page: number = 0, @@ -48,6 +53,10 @@ export class SeriesService extends BaseApiService { } } + static async clearSeriesBooksCache(seriesId: string) { + serverCacheService.deleteAll(`series-${seriesId}-books`); + } + static async getFirstBook(seriesId: string): Promise { try { const config = await this.getKomgaConfig(); diff --git a/src/lib/services/server-cache.service.ts b/src/lib/services/server-cache.service.ts index 0293706..fc98fb3 100644 --- a/src/lib/services/server-cache.service.ts +++ b/src/lib/services/server-cache.service.ts @@ -283,6 +283,24 @@ class ServerCacheService { } } + /** + * Supprime toutes les entrées du cache qui commencent par un préfixe + */ + deleteAll(prefix: string): void { + if (this.config.mode === "memory") { + this.memoryCache.forEach((value, key) => { + if (key.startsWith(prefix)) { + this.memoryCache.delete(key); + } + }); + } else { + const cacheDir = path.join(this.cacheDir, prefix); + if (fs.existsSync(cacheDir)) { + fs.rmdirSync(cacheDir, { recursive: true }); + } + } + } + /** * Vide le cache */