import { API_ENDPOINTS } from "@/api/generated/endpoints" import { __scanner_modalIsOpen } from "@/app/(main)/(library)/_containers/scanner-modal" import { useWebsocketMessageListener } from "@/app/(main)/_hooks/handle-websockets" import { useServerStatus } from "@/app/(main)/_hooks/use-server-status" import { PageWrapper } from "@/components/shared/page-wrapper" import { Button, CloseButton } from "@/components/ui/button" import { Card, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card" import { Spinner } from "@/components/ui/loading-spinner" import { useBoolean } from "@/hooks/use-disclosure" import { WSEvents } from "@/lib/server/ws-events" import { useQueryClient } from "@tanstack/react-query" import { useSetAtom } from "jotai/react" import React, { useState } from "react" import { BiSolidBinoculars } from "react-icons/bi" import { FiSearch } from "react-icons/fi" import { toast } from "sonner" type LibraryWatcherProps = { children?: React.ReactNode } export function LibraryWatcher(props: LibraryWatcherProps) { const { children, ...rest } = props const qc = useQueryClient() const serverStatus = useServerStatus() const [fileEvent, setFileEvent] = useState(null) const fileAdded = useBoolean(false) const fileRemoved = useBoolean(false) const autoScanning = useBoolean(false) const [progress, setProgress] = useState(0) const setScannerModalOpen = useSetAtom(__scanner_modalIsOpen) useWebsocketMessageListener({ type: WSEvents.LIBRARY_WATCHER_FILE_ADDED, onMessage: data => { console.log("Library watcher", data) if (!serverStatus?.settings?.library?.autoScan) { // Only show the notification if auto scan is disabled fileAdded.on() setFileEvent(data) } }, }) useWebsocketMessageListener({ type: WSEvents.LIBRARY_WATCHER_FILE_REMOVED, onMessage: data => { console.log("Library watcher", data) if (!serverStatus?.settings?.library?.autoScan) { // Only show the notification if auto scan is disabled fileRemoved.on() setFileEvent(data) } }, }) // Scan progress event useWebsocketMessageListener({ type: WSEvents.SCAN_PROGRESS, onMessage: data => { // Remove notification of file added or removed setFileEvent(null) fileAdded.off() fileRemoved.off() setProgress(data) // reset progress if (data === 100) { setTimeout(() => { setProgress(0) }, 2000) } }, }) // Auto scan event started useWebsocketMessageListener({ type: WSEvents.AUTO_SCAN_STARTED, onMessage: _ => { autoScanning.on() }, }) // Auto scan event completed useWebsocketMessageListener({ type: WSEvents.AUTO_SCAN_COMPLETED, onMessage: _ => { autoScanning.off() toast.success("Library scanned") qc.invalidateQueries({ queryKey: [API_ENDPOINTS.ANIME_COLLECTION.GetLibraryCollection.key] }) qc.invalidateQueries({ queryKey: [API_ENDPOINTS.ANIME_ENTRIES.GetMissingEpisodes.key] }) qc.invalidateQueries({ queryKey: [API_ENDPOINTS.AUTO_DOWNLOADER.GetAutoDownloaderItems.key] }) }, }) function handleCancel() { setFileEvent(null) fileAdded.off() fileRemoved.off() } if (autoScanning.active && progress > 0) { return (
{progress}% Refreshing your library...
) } else if (!!fileEvent) { return (
Library watcher A change has been detected in your library, refresh your entries.
) } return null }