refacto: tentative de refacto
This commit is contained in:
@@ -1,11 +1,38 @@
|
|||||||
{
|
{
|
||||||
"extends": ["next/core-web-vitals", "prettier"],
|
"extends": ["next/core-web-vitals", "prettier"],
|
||||||
"parser": "@typescript-eslint/parser",
|
"parser": "@typescript-eslint/parser",
|
||||||
"plugins": ["@typescript-eslint"],
|
"plugins": ["@typescript-eslint", "unused-imports"],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": [
|
||||||
"no-console": "off",
|
"warn",
|
||||||
|
{
|
||||||
|
"argsIgnorePattern": "^_",
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"caughtErrorsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-console": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"allow": ["warn", "error"]
|
||||||
|
}
|
||||||
|
],
|
||||||
"@next/next/no-html-link-for-pages": "off",
|
"@next/next/no-html-link-for-pages": "off",
|
||||||
"react/no-unescaped-entities": "off"
|
"react/no-unescaped-entities": "off",
|
||||||
|
"no-unreachable": "error",
|
||||||
|
"no-unused-expressions": "warn",
|
||||||
|
"no-unused-private-class-members": "warn",
|
||||||
|
"unused-imports/no-unused-imports": "warn",
|
||||||
|
"unused-imports/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"vars": "all",
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"args": "after-used",
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-empty-function": "warn",
|
||||||
|
"no-empty": ["warn", { "allowEmptyCatch": true }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,13 @@
|
|||||||
"@types/node": "20.11.16",
|
"@types/node": "20.11.16",
|
||||||
"@types/react": "18.2.52",
|
"@types/react": "18.2.52",
|
||||||
"@types/react-dom": "18.2.18",
|
"@types/react-dom": "18.2.18",
|
||||||
"@typescript-eslint/eslint-plugin": "6.21.0",
|
"@typescript-eslint/eslint-plugin": "^8.24.0",
|
||||||
"@typescript-eslint/parser": "6.21.0",
|
"@typescript-eslint/parser": "6.21.0",
|
||||||
"autoprefixer": "10.4.17",
|
"autoprefixer": "10.4.17",
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.56.0",
|
||||||
"eslint-config-next": "14.1.0",
|
"eslint-config-next": "14.1.0",
|
||||||
"eslint-config-prettier": "10.0.1",
|
"eslint-config-prettier": "10.0.1",
|
||||||
|
"eslint-plugin-unused-imports": "^4.1.4",
|
||||||
"postcss": "8.4.33",
|
"postcss": "8.4.33",
|
||||||
"tailwindcss": "3.4.1",
|
"tailwindcss": "3.4.1",
|
||||||
"typescript": "5.3.3"
|
"typescript": "5.3.3"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { ConfigDBService } from "@/lib/services/config-db.service";
|
import { ConfigDBService } from "@/lib/services/config-db.service";
|
||||||
|
|
||||||
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
try {
|
try {
|
||||||
const data = await request.json();
|
const data = await request.json();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export async function GET(
|
|||||||
try {
|
try {
|
||||||
// Convertir le numéro de page en nombre
|
// Convertir le numéro de page en nombre
|
||||||
const pageNumber = parseInt(params.pageNumber);
|
const pageNumber = parseInt(params.pageNumber);
|
||||||
if (isNaN(pageNumber) || pageNumber < 1) {
|
if (isNaN(pageNumber) || pageNumber < 0) {
|
||||||
return NextResponse.json({ error: "Numéro de page invalide" }, { status: 400 });
|
return NextResponse.json({ error: "Numéro de page invalide" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,8 +18,11 @@ export async function GET(
|
|||||||
return response;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("API Book Page Thumbnail - Erreur:", error);
|
console.error("API Book Page Thumbnail - Erreur:", error);
|
||||||
|
if (error instanceof Error) {
|
||||||
|
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||||
|
}
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Erreur lors de la récupération de la miniature" },
|
{ error: "Une erreur est survenue lors de la récupération de la miniature" },
|
||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import { ConfigDBService } from "@/lib/services/config-db.service";
|
import { ConfigDBService } from "@/lib/services/config-db.service";
|
||||||
import { ClientSettings } from "@/components/settings/ClientSettings";
|
import { ClientSettings } from "@/components/settings/ClientSettings";
|
||||||
|
import { Metadata } from "next";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Préférences",
|
||||||
|
description: "Configurez vos préférences StripStream",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viewport = {
|
||||||
|
colorScheme: "dark light",
|
||||||
|
};
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
let config = null;
|
let config = null;
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ export function HomeContent({ data }: HomeContentProps) {
|
|||||||
await router.push(path);
|
await router.push(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSeriesClick = (seriesId: string) => {
|
|
||||||
router.push(`/series/${seriesId}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Vérification des données pour le debug
|
// Vérification des données pour le debug
|
||||||
// console.log("HomeContent - Données reçues:", {
|
// console.log("HomeContent - Données reçues:", {
|
||||||
// ongoingCount: data.ongoing?.length || 0,
|
// ongoingCount: data.ongoing?.length || 0,
|
||||||
|
|||||||
@@ -86,18 +86,9 @@ function MediaCard({ item, onClick }: MediaCardProps) {
|
|||||||
? item.metadata.title
|
? item.metadata.title
|
||||||
: item.metadata.title || `Tome ${item.metadata.number}`;
|
: item.metadata.title || `Tome ${item.metadata.number}`;
|
||||||
|
|
||||||
const handleClick = () => {
|
|
||||||
console.log("MediaCard - handleClick:", {
|
|
||||||
itemType: isSeries ? "series" : "book",
|
|
||||||
itemId: item.id,
|
|
||||||
itemTitle: title,
|
|
||||||
});
|
|
||||||
onClick?.();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={handleClick}
|
onClick={onClick}
|
||||||
className="flex-shrink-0 w-[200px] relative flex flex-col rounded-lg border bg-card text-card-foreground shadow-sm hover:bg-accent hover:text-accent-foreground transition-colors overflow-hidden cursor-pointer"
|
className="flex-shrink-0 w-[200px] relative flex flex-col rounded-lg border bg-card text-card-foreground shadow-sm hover:bg-accent hover:text-accent-foreground transition-colors overflow-hidden cursor-pointer"
|
||||||
>
|
>
|
||||||
{/* Image de couverture */}
|
{/* Image de couverture */}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import { Header } from "@/components/layout/Header";
|
|||||||
import { Sidebar } from "@/components/layout/Sidebar";
|
import { Sidebar } from "@/components/layout/Sidebar";
|
||||||
import { InstallPWA } from "../ui/InstallPWA";
|
import { InstallPWA } from "../ui/InstallPWA";
|
||||||
import { Toaster } from "@/components/ui/toaster";
|
import { Toaster } from "@/components/ui/toaster";
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { authService } from "@/lib/services/auth.service";
|
|
||||||
import { PreferencesProvider } from "@/contexts/PreferencesContext";
|
import { PreferencesProvider } from "@/contexts/PreferencesContext";
|
||||||
|
|
||||||
// Routes qui ne nécessitent pas d'authentification
|
// Routes qui ne nécessitent pas d'authentification
|
||||||
@@ -15,7 +14,6 @@ const publicRoutes = ["/login", "/register"];
|
|||||||
|
|
||||||
export default function ClientLayout({ children }: { children: React.ReactNode }) {
|
export default function ClientLayout({ children }: { children: React.ReactNode }) {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
const router = useRouter();
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
const handleCloseSidebar = () => {
|
const handleCloseSidebar = () => {
|
||||||
@@ -56,8 +54,8 @@ export default function ClientLayout({ children }: { children: React.ReactNode }
|
|||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register("/sw.js")
|
.register("/sw.js")
|
||||||
.then((registration) => {
|
.then(() => {
|
||||||
console.log("Service Worker enregistré avec succès:", registration);
|
// Succès silencieux
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Erreur lors de l'enregistrement du Service Worker:", error);
|
console.error("Erreur lors de l'enregistrement du Service Worker:", error);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { BookOpen, Home, Library, Settings, LogOut, RefreshCw, Star } from "lucide-react";
|
import { Home, Library, Settings, LogOut, RefreshCw, Star } from "lucide-react";
|
||||||
import Link from "next/link";
|
|
||||||
import { usePathname, useRouter } from "next/navigation";
|
import { usePathname, useRouter } from "next/navigation";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { authService } from "@/lib/services/auth.service";
|
import { authService } from "@/lib/services/auth.service";
|
||||||
@@ -32,7 +31,9 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
setLibraries(data);
|
setLibraries(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur:", error);
|
if (error instanceof Error) {
|
||||||
|
console.error("Erreur de chargement des bibliothèques:", error.message);
|
||||||
|
}
|
||||||
setLibraries([]);
|
setLibraries([]);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -43,7 +44,6 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
|
|||||||
const fetchFavorites = useCallback(async () => {
|
const fetchFavorites = useCallback(async () => {
|
||||||
setIsLoadingFavorites(true);
|
setIsLoadingFavorites(true);
|
||||||
try {
|
try {
|
||||||
// Récupérer les IDs des favoris depuis l'API
|
|
||||||
const favoritesResponse = await fetch("/api/komga/favorites");
|
const favoritesResponse = await fetch("/api/komga/favorites");
|
||||||
if (!favoritesResponse.ok) {
|
if (!favoritesResponse.ok) {
|
||||||
throw new Error("Erreur lors de la récupération des favoris");
|
throw new Error("Erreur lors de la récupération des favoris");
|
||||||
@@ -55,7 +55,6 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupérer les détails des séries pour chaque ID
|
|
||||||
const promises = favoriteIds.map(async (id: string) => {
|
const promises = favoriteIds.map(async (id: string) => {
|
||||||
const response = await fetch(`/api/komga/series/${id}`);
|
const response = await fetch(`/api/komga/series/${id}`);
|
||||||
if (!response.ok) return null;
|
if (!response.ok) return null;
|
||||||
@@ -65,7 +64,9 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
|
|||||||
const results = await Promise.all(promises);
|
const results = await Promise.all(promises);
|
||||||
setFavorites(results.filter((series): series is KomgaSeries => series !== null));
|
setFavorites(results.filter((series): series is KomgaSeries => series !== null));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors de la récupération des favoris:", error);
|
if (error instanceof Error) {
|
||||||
|
console.error("Erreur de chargement des favoris:", error.message);
|
||||||
|
}
|
||||||
setFavorites([]);
|
setFavorites([]);
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoadingFavorites(false);
|
setIsLoadingFavorites(false);
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import { useRouter, usePathname, useSearchParams } from "next/navigation";
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Loader2, Filter } from "lucide-react";
|
import { Loader2, Filter } from "lucide-react";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { KomgaSeries } from "@/types/komga";
|
||||||
|
|
||||||
interface PaginatedSeriesGridProps {
|
interface PaginatedSeriesGridProps {
|
||||||
series: any[];
|
series: KomgaSeries[];
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
totalElements: number;
|
totalElements: number;
|
||||||
@@ -61,10 +62,6 @@ export function PaginatedSeriesGrid({
|
|||||||
await router.push(`${pathname}?${params.toString()}`);
|
await router.push(`${pathname}?${params.toString()}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSeriesClick = (seriesId: string) => {
|
|
||||||
router.push(`/series/${seriesId}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calcul des indices de début et de fin pour l'affichage
|
// Calcul des indices de début et de fin pour l'affichage
|
||||||
const startIndex = (currentPage - 1) * pageSize + 1;
|
const startIndex = (currentPage - 1) * pageSize + 1;
|
||||||
const endIndex = Math.min(currentPage * pageSize, totalElements);
|
const endIndex = Math.min(currentPage * pageSize, totalElements);
|
||||||
|
|||||||
@@ -24,12 +24,9 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
setIsLoading,
|
setIsLoading,
|
||||||
secondPageLoading,
|
secondPageLoading,
|
||||||
setSecondPageLoading,
|
setSecondPageLoading,
|
||||||
imageError,
|
|
||||||
setImageError,
|
|
||||||
handlePreviousPage,
|
handlePreviousPage,
|
||||||
handleNextPage,
|
handleNextPage,
|
||||||
shouldShowDoublePage,
|
shouldShowDoublePage,
|
||||||
syncReadProgress,
|
|
||||||
} = usePageNavigation({
|
} = usePageNavigation({
|
||||||
book,
|
book,
|
||||||
pages,
|
pages,
|
||||||
@@ -66,9 +63,12 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors du chargement des URLs:", error);
|
if (error instanceof Error) {
|
||||||
setImageError(true);
|
console.error(
|
||||||
} finally {
|
`Erreur de chargement des URLs pour la page ${currentPage}:`,
|
||||||
|
error.message
|
||||||
|
);
|
||||||
|
}
|
||||||
// On s'assure que le chargement est terminé même en cas d'erreur
|
// On s'assure que le chargement est terminé même en cas d'erreur
|
||||||
if (isMounted) {
|
if (isMounted) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -91,7 +91,6 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
getPageUrl,
|
getPageUrl,
|
||||||
setIsLoading,
|
setIsLoading,
|
||||||
setSecondPageLoading,
|
setSecondPageLoading,
|
||||||
setImageError,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Effet pour précharger la page courante et les pages adjacentes
|
// Effet pour précharger la page courante et les pages adjacentes
|
||||||
@@ -205,6 +204,13 @@ export function BookReader({ book, pages, onClose }: BookReaderProps) {
|
|||||||
{/* Pages */}
|
{/* Pages */}
|
||||||
<div className="relative flex-1 flex items-center justify-center overflow-hidden p-1">
|
<div className="relative flex-1 flex items-center justify-center overflow-hidden p-1">
|
||||||
<div className="relative w-full h-[calc(100vh-2rem)] flex items-center justify-center gap-0">
|
<div className="relative w-full h-[calc(100vh-2rem)] flex items-center justify-center gap-0">
|
||||||
|
{/*
|
||||||
|
Note: Nous utilisons intentionnellement des balises <img> natives au lieu de next/image pour :
|
||||||
|
1. Avoir un contrôle précis sur le chargement et le préchargement des pages
|
||||||
|
2. Gérer efficacement le mode double page et les transitions
|
||||||
|
3. Les images sont déjà optimisées côté serveur
|
||||||
|
4. La performance est critique pour une lecture fluide
|
||||||
|
*/}
|
||||||
{/* Page courante */}
|
{/* Page courante */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
import { KomgaBook } from "@/types/komga";
|
import { KomgaBook } from "@/types/komga";
|
||||||
import { BookReader } from "./BookReader";
|
import { BookReader } from "./BookReader";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
|
||||||
|
|
||||||
interface ClientBookWrapperProps {
|
interface ClientBookWrapperProps {
|
||||||
book: KomgaBook;
|
book: KomgaBook;
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ export const ControlButtons = ({
|
|||||||
"absolute top-4 left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 transition-all duration-300",
|
"absolute top-4 left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 transition-all duration-300",
|
||||||
showControls ? "opacity-100" : "opacity-0 pointer-events-none"
|
showControls ? "opacity-100" : "opacity-0 pointer-events-none"
|
||||||
)}
|
)}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onToggleControls();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { NavigationBarProps } from "../types";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { Thumbnail } from "./Thumbnail";
|
import { Thumbnail } from "./Thumbnail";
|
||||||
import { useThumbnails } from "../hooks/useThumbnails";
|
import { useThumbnails } from "../hooks/useThumbnails";
|
||||||
import { useEffect } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
export const NavigationBar = ({
|
export const NavigationBar = ({
|
||||||
currentPage,
|
currentPage,
|
||||||
@@ -11,16 +11,13 @@ export const NavigationBar = ({
|
|||||||
showControls,
|
showControls,
|
||||||
book,
|
book,
|
||||||
}: NavigationBarProps) => {
|
}: NavigationBarProps) => {
|
||||||
const {
|
const { loadedThumbnails, handleThumbnailLoad, getThumbnailUrl, visibleThumbnails } =
|
||||||
loadedThumbnails,
|
useThumbnails({
|
||||||
handleThumbnailLoad,
|
book,
|
||||||
getThumbnailUrl,
|
currentPage,
|
||||||
visibleThumbnails,
|
});
|
||||||
scrollToActiveThumbnail,
|
|
||||||
} = useThumbnails({
|
const thumbnailsContainerRef = useRef<HTMLDivElement>(null);
|
||||||
book,
|
|
||||||
currentPage,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Scroll à l'ouverture des contrôles et au changement de page
|
// Scroll à l'ouverture des contrôles et au changement de page
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -53,6 +50,7 @@ export const NavigationBar = ({
|
|||||||
onTouchStart={(e) => e.stopPropagation()}
|
onTouchStart={(e) => e.stopPropagation()}
|
||||||
onTouchMove={(e) => e.stopPropagation()}
|
onTouchMove={(e) => e.stopPropagation()}
|
||||||
onTouchEnd={(e) => e.stopPropagation()}
|
onTouchEnd={(e) => e.stopPropagation()}
|
||||||
|
ref={thumbnailsContainerRef}
|
||||||
>
|
>
|
||||||
<div className="w-[calc(50vw-18rem)] flex-shrink-0" />
|
<div className="w-[calc(50vw-18rem)] flex-shrink-0" />
|
||||||
{pages.map((_, index) => {
|
{pages.map((_, index) => {
|
||||||
|
|||||||
@@ -6,15 +6,7 @@ import { forwardRef, useEffect, useState, useCallback, useRef } from "react";
|
|||||||
|
|
||||||
export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
||||||
(
|
(
|
||||||
{
|
{ pageNumber, currentPage, onPageChange, getThumbnailUrl, loadedThumbnails, onThumbnailLoad },
|
||||||
pageNumber,
|
|
||||||
currentPage,
|
|
||||||
onPageChange,
|
|
||||||
getThumbnailUrl,
|
|
||||||
loadedThumbnails,
|
|
||||||
onThumbnailLoad,
|
|
||||||
isVisible,
|
|
||||||
},
|
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
||||||
@@ -59,9 +51,6 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
|||||||
if (loadAttempts.current < maxAttempts) {
|
if (loadAttempts.current < maxAttempts) {
|
||||||
// Réessayer avec un délai croissant
|
// Réessayer avec un délai croissant
|
||||||
const delay = Math.min(1000 * Math.pow(2, loadAttempts.current - 1), 5000);
|
const delay = Math.min(1000 * Math.pow(2, loadAttempts.current - 1), 5000);
|
||||||
console.log(
|
|
||||||
`Réessai ${loadAttempts.current}/${maxAttempts} dans ${delay}ms pour la page ${pageNumber}`
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setImageUrl((prev) => (prev ? `${prev}?retry=${loadAttempts.current}` : null));
|
setImageUrl((prev) => (prev ? `${prev}?retry=${loadAttempts.current}` : null));
|
||||||
}, delay);
|
}, delay);
|
||||||
@@ -94,7 +83,7 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
|
|||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
alt={`Miniature page ${pageNumber}`}
|
alt={`Miniature page ${pageNumber}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
"object-cover transition-opacity duration-300",
|
"object-contain transition-opacity duration-300",
|
||||||
isLoading ? "opacity-0" : "opacity-100"
|
isLoading ? "opacity-0" : "opacity-100"
|
||||||
)}
|
)}
|
||||||
fill
|
fill
|
||||||
|
|||||||
@@ -12,12 +12,11 @@ export const usePageNavigation = ({
|
|||||||
book,
|
book,
|
||||||
pages,
|
pages,
|
||||||
isDoublePage,
|
isDoublePage,
|
||||||
onClose = () => {},
|
onClose,
|
||||||
}: UsePageNavigationProps) => {
|
}: UsePageNavigationProps) => {
|
||||||
const [currentPage, setCurrentPage] = useState(book.readProgress?.page || 1);
|
const [currentPage, setCurrentPage] = useState(book.readProgress?.page || 1);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [secondPageLoading, setSecondPageLoading] = useState(true);
|
const [secondPageLoading, setSecondPageLoading] = useState(true);
|
||||||
const [imageError, setImageError] = useState(false);
|
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const touchStartXRef = useRef<number | null>(null);
|
const touchStartXRef = useRef<number | null>(null);
|
||||||
const touchStartYRef = useRef<number | null>(null);
|
const touchStartYRef = useRef<number | null>(null);
|
||||||
@@ -39,7 +38,12 @@ export const usePageNavigation = ({
|
|||||||
body: JSON.stringify({ page, completed }),
|
body: JSON.stringify({ page, completed }),
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors de la synchronisation de la progression:", error);
|
if (error instanceof Error) {
|
||||||
|
console.error(
|
||||||
|
`Erreur de synchronisation de la progression pour le livre ${book.id} à la page ${page}:`,
|
||||||
|
error.message
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[book.id, pages.length]
|
[book.id, pages.length]
|
||||||
@@ -73,7 +77,6 @@ export const usePageNavigation = ({
|
|||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setSecondPageLoading(true);
|
setSecondPageLoading(true);
|
||||||
setImageError(false);
|
|
||||||
debouncedSyncReadProgress(page);
|
debouncedSyncReadProgress(page);
|
||||||
},
|
},
|
||||||
[debouncedSyncReadProgress]
|
[debouncedSyncReadProgress]
|
||||||
@@ -167,11 +170,8 @@ export const usePageNavigation = ({
|
|||||||
setIsLoading,
|
setIsLoading,
|
||||||
secondPageLoading,
|
secondPageLoading,
|
||||||
setSecondPageLoading,
|
setSecondPageLoading,
|
||||||
imageError,
|
|
||||||
setImageError,
|
|
||||||
handlePreviousPage,
|
handlePreviousPage,
|
||||||
handleNextPage,
|
handleNextPage,
|
||||||
shouldShowDoublePage,
|
shouldShowDoublePage,
|
||||||
syncReadProgress: debouncedSyncReadProgress,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ export const useThumbnails = ({ book, currentPage }: UseThumbnailsProps) => {
|
|||||||
|
|
||||||
const getThumbnailUrl = useCallback(
|
const getThumbnailUrl = useCallback(
|
||||||
(pageNumber: number) => {
|
(pageNumber: number) => {
|
||||||
return `/api/komga/images/books/${book.id}/pages/${pageNumber}/thumbnail`;
|
const zeroBasedPage = pageNumber - 1;
|
||||||
|
return `/api/komga/images/books/${book.id}/pages/${zeroBasedPage}/thumbnail?zero_based=true`;
|
||||||
},
|
},
|
||||||
[book.id]
|
[book.id]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -70,10 +70,6 @@ export function PaginatedBookGrid({
|
|||||||
const startIndex = (currentPage - 1) * pageSize + 1;
|
const startIndex = (currentPage - 1) * pageSize + 1;
|
||||||
const endIndex = Math.min(currentPage * pageSize, totalElements);
|
const endIndex = Math.min(currentPage * pageSize, totalElements);
|
||||||
|
|
||||||
const getBookThumbnailUrl = (bookId: string) => {
|
|
||||||
return `/api/komga/images/books/${bookId}/thumbnail`;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="flex items-center justify-between flex-wrap gap-4">
|
<div className="flex items-center justify-between flex-wrap gap-4">
|
||||||
@@ -115,11 +111,7 @@ export function PaginatedBookGrid({
|
|||||||
isChangingPage ? "opacity-25" : "opacity-100"
|
isChangingPage ? "opacity-25" : "opacity-100"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<BookGrid
|
<BookGrid books={books} onBookClick={handleBookClick} />
|
||||||
books={books}
|
|
||||||
onBookClick={handleBookClick}
|
|
||||||
getBookThumbnailUrl={getBookThumbnailUrl}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,13 @@ import { KomgaSeries } from "@/types/komga";
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { Cover } from "@/components/ui/cover";
|
import { Cover } from "@/components/ui/cover";
|
||||||
|
|
||||||
interface SeriesHeaderProps {
|
interface SeriesHeaderProps {
|
||||||
series: KomgaSeries;
|
series: KomgaSeries;
|
||||||
onSeriesUpdate?: (series: KomgaSeries) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SeriesHeader = ({ series, onSeriesUpdate }: SeriesHeaderProps) => {
|
export const SeriesHeader = ({ series }: SeriesHeaderProps) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const [isFavorite, setIsFavorite] = useState(false);
|
const [isFavorite, setIsFavorite] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ import { usePreferences } from "@/contexts/PreferencesContext";
|
|||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
||||||
interface ErrorMessage {
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface KomgaConfig {
|
interface KomgaConfig {
|
||||||
url: string;
|
url: string;
|
||||||
username: string;
|
username: string;
|
||||||
@@ -256,7 +252,10 @@ export function ClientSettings({ initialConfig, initialTTLConfig }: ClientSettin
|
|||||||
toast({
|
toast({
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
title: "Erreur",
|
title: "Erreur",
|
||||||
description: "Une erreur est survenue lors de la mise à jour des préférences",
|
description:
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "Une erreur est survenue lors de la mise à jour des préférences",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface ImageLoaderProps {
|
interface ImageLoaderProps {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ type ToasterToast = ToastProps & {
|
|||||||
action?: ToastActionElement;
|
action?: ToastActionElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
const actionTypes = {
|
const _actionTypes = {
|
||||||
ADD_TOAST: "ADD_TOAST",
|
ADD_TOAST: "ADD_TOAST",
|
||||||
UPDATE_TOAST: "UPDATE_TOAST",
|
UPDATE_TOAST: "UPDATE_TOAST",
|
||||||
DISMISS_TOAST: "DISMISS_TOAST",
|
DISMISS_TOAST: "DISMISS_TOAST",
|
||||||
@@ -26,7 +26,7 @@ function genId() {
|
|||||||
return count.toString();
|
return count.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActionType = typeof actionTypes;
|
type ActionType = typeof _actionTypes;
|
||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
| {
|
| {
|
||||||
|
|||||||
@@ -2,16 +2,13 @@
|
|||||||
|
|
||||||
import { AuthError } from "@/types/auth";
|
import { AuthError } from "@/types/auth";
|
||||||
|
|
||||||
interface AuthUser {
|
|
||||||
id: string;
|
|
||||||
email: string;
|
|
||||||
roles: string[];
|
|
||||||
authenticated: boolean;
|
|
||||||
}
|
|
||||||
class AuthService {
|
class AuthService {
|
||||||
private static instance: AuthService;
|
private static instance: AuthService;
|
||||||
|
|
||||||
private constructor() {}
|
// Constructeur privé pour le pattern Singleton
|
||||||
|
private constructor() {
|
||||||
|
// Pas d'initialisation nécessaire
|
||||||
|
}
|
||||||
|
|
||||||
public static getInstance(): AuthService {
|
public static getInstance(): AuthService {
|
||||||
if (!AuthService.instance) {
|
if (!AuthService.instance) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { cookies } from "next/headers";
|
|
||||||
import { AuthConfig } from "@/types/auth";
|
import { AuthConfig } from "@/types/auth";
|
||||||
import { serverCacheService } from "./server-cache.service";
|
import { serverCacheService } from "./server-cache.service";
|
||||||
import { ConfigDBService } from "./config-db.service";
|
import { ConfigDBService } from "./config-db.service";
|
||||||
@@ -71,18 +70,12 @@ export abstract class BaseApiService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log de l'URL finale
|
|
||||||
console.log(`🔄 [Komga API] ${url.toString()}`);
|
|
||||||
|
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static async fetchFromApi<T>(url: string, headers: Headers): Promise<T> {
|
protected static async fetchFromApi<T>(url: string, headers: Headers): Promise<T> {
|
||||||
const response = await fetch(url, { headers });
|
const response = await fetch(url, { headers });
|
||||||
|
|
||||||
// Log du résultat de la requête
|
|
||||||
console.log(`📡 [Komga API] ${response.status} ${response.statusText} - ${url}`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`);
|
throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ export class ImageService extends BaseApiService {
|
|||||||
async () => {
|
async () => {
|
||||||
const response = await fetch(url, { headers });
|
const response = await fetch(url, { headers });
|
||||||
|
|
||||||
// Log du résultat de la requête
|
|
||||||
console.log(`📡 [Komga API] ${response.status} ${response.statusText} - ${url}`);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`);
|
throw new Error(`Erreur HTTP: ${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
type CacheEntry = {
|
|
||||||
data: any;
|
|
||||||
timestamp: number;
|
|
||||||
ttl: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ServerCacheService {
|
class ServerCacheService {
|
||||||
private static instance: ServerCacheService;
|
private static instance: ServerCacheService;
|
||||||
private cache: Map<string, { data: unknown; expiry: number }> = new Map();
|
private cache: Map<string, { data: unknown; expiry: number }> = new Map();
|
||||||
@@ -94,14 +88,11 @@ class ServerCacheService {
|
|||||||
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
|
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
console.log("👀 Getting or setting cache for key:", key);
|
|
||||||
const cached = this.cache.get(key);
|
const cached = this.cache.get(key);
|
||||||
|
|
||||||
if (cached && cached.expiry > now) {
|
if (cached && cached.expiry > now) {
|
||||||
console.log("✅ Cache hit for key:", key);
|
|
||||||
return cached.data as T;
|
return cached.data as T;
|
||||||
}
|
}
|
||||||
console.log("❌ Cache not hit for key:", key);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await fetcher();
|
const data = await fetcher();
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ export interface Series {
|
|||||||
booksUnreadCount: number;
|
booksUnreadCount: number;
|
||||||
booksInProgressCount: number;
|
booksInProgressCount: number;
|
||||||
metadata: {
|
metadata: {
|
||||||
status: string;
|
status: "ENDED" | "ONGOING" | "ABANDONED" | "HIATUS";
|
||||||
created: string;
|
created: string;
|
||||||
lastModified: string;
|
lastModified: string;
|
||||||
title: string;
|
title: string;
|
||||||
titleSort: string;
|
titleSort: string;
|
||||||
summary: string;
|
summary: string;
|
||||||
readingDirection: string;
|
readingDirection: "LEFT_TO_RIGHT" | "RIGHT_TO_LEFT" | "VERTICAL" | "WEBTOON";
|
||||||
publisher: string;
|
publisher: string;
|
||||||
ageRating: number;
|
ageRating: number;
|
||||||
language: string;
|
language: string;
|
||||||
@@ -47,4 +47,6 @@ export interface Series {
|
|||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
deleted: boolean;
|
deleted: boolean;
|
||||||
|
oneshot: boolean;
|
||||||
|
favorite: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
123
yarn.lock
123
yarn.lock
@@ -28,7 +28,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
eslint-visitor-keys "^3.4.3"
|
eslint-visitor-keys "^3.4.3"
|
||||||
|
|
||||||
"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1":
|
"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1":
|
||||||
version "4.12.1"
|
version "4.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||||
@@ -741,11 +741,6 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@types/json-schema@^7.0.12":
|
|
||||||
version "7.0.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
|
||||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
|
||||||
|
|
||||||
"@types/json5@^0.0.29":
|
"@types/json5@^0.0.29":
|
||||||
version "0.0.29"
|
version "0.0.29"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||||
@@ -798,11 +793,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.23.0.tgz#0a6655b3e2708eaabca00b7372fafd7a792a7b09"
|
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.23.0.tgz#0a6655b3e2708eaabca00b7372fafd7a792a7b09"
|
||||||
integrity sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==
|
integrity sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw==
|
||||||
|
|
||||||
"@types/semver@^7.5.0":
|
|
||||||
version "7.5.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
|
||||||
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
|
|
||||||
|
|
||||||
"@types/webidl-conversions@*":
|
"@types/webidl-conversions@*":
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859"
|
resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859"
|
||||||
@@ -815,22 +805,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/webidl-conversions" "*"
|
"@types/webidl-conversions" "*"
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin@6.21.0":
|
"@typescript-eslint/eslint-plugin@^8.24.0":
|
||||||
version "6.21.0"
|
version "8.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.0.tgz#574a95d67660a1e4544ae131d672867a5b40abb3"
|
||||||
integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==
|
integrity sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/regexpp" "^4.5.1"
|
"@eslint-community/regexpp" "^4.10.0"
|
||||||
"@typescript-eslint/scope-manager" "6.21.0"
|
"@typescript-eslint/scope-manager" "8.24.0"
|
||||||
"@typescript-eslint/type-utils" "6.21.0"
|
"@typescript-eslint/type-utils" "8.24.0"
|
||||||
"@typescript-eslint/utils" "6.21.0"
|
"@typescript-eslint/utils" "8.24.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
"@typescript-eslint/visitor-keys" "8.24.0"
|
||||||
debug "^4.3.4"
|
|
||||||
graphemer "^1.4.0"
|
graphemer "^1.4.0"
|
||||||
ignore "^5.2.4"
|
ignore "^5.3.1"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
semver "^7.5.4"
|
ts-api-utils "^2.0.1"
|
||||||
ts-api-utils "^1.0.1"
|
|
||||||
|
|
||||||
"@typescript-eslint/parser@6.21.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0":
|
"@typescript-eslint/parser@6.21.0", "@typescript-eslint/parser@^5.4.2 || ^6.0.0":
|
||||||
version "6.21.0"
|
version "6.21.0"
|
||||||
@@ -851,21 +839,34 @@
|
|||||||
"@typescript-eslint/types" "6.21.0"
|
"@typescript-eslint/types" "6.21.0"
|
||||||
"@typescript-eslint/visitor-keys" "6.21.0"
|
"@typescript-eslint/visitor-keys" "6.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/type-utils@6.21.0":
|
"@typescript-eslint/scope-manager@8.24.0":
|
||||||
version "6.21.0"
|
version "8.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.24.0.tgz#2e34b3eb2ce768f2ffb109474174ced5417002b1"
|
||||||
integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==
|
integrity sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
"@typescript-eslint/types" "8.24.0"
|
||||||
"@typescript-eslint/utils" "6.21.0"
|
"@typescript-eslint/visitor-keys" "8.24.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/type-utils@8.24.0":
|
||||||
|
version "8.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.24.0.tgz#6ee3ec4db06f9e5e7b01ca6c2b5dd5843a9fd1e8"
|
||||||
|
integrity sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/typescript-estree" "8.24.0"
|
||||||
|
"@typescript-eslint/utils" "8.24.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
ts-api-utils "^1.0.1"
|
ts-api-utils "^2.0.1"
|
||||||
|
|
||||||
"@typescript-eslint/types@6.21.0":
|
"@typescript-eslint/types@6.21.0":
|
||||||
version "6.21.0"
|
version "6.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
|
||||||
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
|
integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
|
||||||
|
|
||||||
|
"@typescript-eslint/types@8.24.0":
|
||||||
|
version "8.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.24.0.tgz#694e7fb18d70506c317b816de9521300b0f72c8e"
|
||||||
|
integrity sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@6.21.0":
|
"@typescript-eslint/typescript-estree@6.21.0":
|
||||||
version "6.21.0"
|
version "6.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
|
||||||
@@ -880,18 +881,29 @@
|
|||||||
semver "^7.5.4"
|
semver "^7.5.4"
|
||||||
ts-api-utils "^1.0.1"
|
ts-api-utils "^1.0.1"
|
||||||
|
|
||||||
"@typescript-eslint/utils@6.21.0":
|
"@typescript-eslint/typescript-estree@8.24.0":
|
||||||
version "6.21.0"
|
version "8.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.0.tgz#0487349be174097bb329a58273100a9629e03c6c"
|
||||||
integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==
|
integrity sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "8.24.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "8.24.0"
|
||||||
|
debug "^4.3.4"
|
||||||
|
fast-glob "^3.3.2"
|
||||||
|
is-glob "^4.0.3"
|
||||||
|
minimatch "^9.0.4"
|
||||||
|
semver "^7.6.0"
|
||||||
|
ts-api-utils "^2.0.1"
|
||||||
|
|
||||||
|
"@typescript-eslint/utils@8.24.0":
|
||||||
|
version "8.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.24.0.tgz#21cb1195ae79230af825bfeed59574f5cb70a749"
|
||||||
|
integrity sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint-community/eslint-utils" "^4.4.0"
|
"@eslint-community/eslint-utils" "^4.4.0"
|
||||||
"@types/json-schema" "^7.0.12"
|
"@typescript-eslint/scope-manager" "8.24.0"
|
||||||
"@types/semver" "^7.5.0"
|
"@typescript-eslint/types" "8.24.0"
|
||||||
"@typescript-eslint/scope-manager" "6.21.0"
|
"@typescript-eslint/typescript-estree" "8.24.0"
|
||||||
"@typescript-eslint/types" "6.21.0"
|
|
||||||
"@typescript-eslint/typescript-estree" "6.21.0"
|
|
||||||
semver "^7.5.4"
|
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@6.21.0":
|
"@typescript-eslint/visitor-keys@6.21.0":
|
||||||
version "6.21.0"
|
version "6.21.0"
|
||||||
@@ -901,6 +913,14 @@
|
|||||||
"@typescript-eslint/types" "6.21.0"
|
"@typescript-eslint/types" "6.21.0"
|
||||||
eslint-visitor-keys "^3.4.1"
|
eslint-visitor-keys "^3.4.1"
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys@8.24.0":
|
||||||
|
version "8.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.0.tgz#36ecf0b9b1d819ad88a3bd4157ab7d594cb797c9"
|
||||||
|
integrity sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "8.24.0"
|
||||||
|
eslint-visitor-keys "^4.2.0"
|
||||||
|
|
||||||
"@ungap/structured-clone@^1.2.0":
|
"@ungap/structured-clone@^1.2.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8"
|
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8"
|
||||||
@@ -1720,6 +1740,11 @@ eslint-plugin-react@^7.33.2:
|
|||||||
string.prototype.matchall "^4.0.12"
|
string.prototype.matchall "^4.0.12"
|
||||||
string.prototype.repeat "^1.0.0"
|
string.prototype.repeat "^1.0.0"
|
||||||
|
|
||||||
|
eslint-plugin-unused-imports@^4.1.4:
|
||||||
|
version "4.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738"
|
||||||
|
integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==
|
||||||
|
|
||||||
eslint-scope@^7.2.2:
|
eslint-scope@^7.2.2:
|
||||||
version "7.2.2"
|
version "7.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
|
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
|
||||||
@@ -1733,6 +1758,11 @@ eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
|
|||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
|
|
||||||
|
eslint-visitor-keys@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
|
||||||
|
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
||||||
|
|
||||||
eslint@8.56.0:
|
eslint@8.56.0:
|
||||||
version "8.56.0"
|
version "8.56.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15"
|
||||||
@@ -1815,7 +1845,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||||
|
|
||||||
fast-glob@^3.2.9, fast-glob@^3.3.0:
|
fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.2:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
|
||||||
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
|
||||||
@@ -2115,7 +2145,7 @@ hasown@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.2"
|
function-bind "^1.1.2"
|
||||||
|
|
||||||
ignore@^5.2.0, ignore@^5.2.4:
|
ignore@^5.2.0, ignore@^5.3.1:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||||
@@ -3246,7 +3276,7 @@ semver@^6.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.5.4, semver@^7.6.3:
|
semver@^7.5.4, semver@^7.6.0, semver@^7.6.3:
|
||||||
version "7.7.1"
|
version "7.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
|
||||||
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||||
@@ -3661,6 +3691,11 @@ ts-api-utils@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064"
|
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.3.tgz#bfc2215fe6528fecab2b0fba570a2e8a4263b064"
|
||||||
integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==
|
integrity sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==
|
||||||
|
|
||||||
|
ts-api-utils@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd"
|
||||||
|
integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==
|
||||||
|
|
||||||
ts-interface-checker@^0.1.9:
|
ts-interface-checker@^0.1.9:
|
||||||
version "0.1.13"
|
version "0.1.13"
|
||||||
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
|
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
|
||||||
|
|||||||
Reference in New Issue
Block a user