import { Tab, Nav, Dropdown } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { useParams, useHistory, Link } from "react-router-dom"; import { Helmet } from "react-helmet"; import { useFindImage, useImageIncrementO, useImageDecrementO, useImageResetO, useImageUpdate, mutateMetadataScan, } from "src/core/StashService"; import { ErrorMessage } from "src/components/Shared/ErrorMessage"; import { LoadingIndicator } from "src/components/Shared/LoadingIndicator"; import { Icon } from "src/components/Shared/Icon"; import { Counter } from "src/components/Shared/Counter"; import { useToast } from "src/hooks/Toast"; import * as Mousetrap from "mousetrap"; import { OCounterButton } from "src/components/Scenes/SceneDetails/OCounterButton"; import { OrganizedButton } from "src/components/Scenes/SceneDetails/OrganizedButton"; import { ImageFileInfoPanel } from "./ImageFileInfoPanel"; import { ImageEditPanel } from "./ImageEditPanel"; import { ImageDetailPanel } from "./ImageDetailPanel"; import { DeleteImagesDialog } from "../DeleteImagesDialog"; import { faEllipsisV } from "@fortawesome/free-solid-svg-icons"; import { objectPath, objectTitle } from "src/core/files"; interface IImageParams { id?: string; } export const Image: React.FC = () => { const { id = "new" } = useParams(); const history = useHistory(); const Toast = useToast(); const intl = useIntl(); const { data, error, loading } = useFindImage(id); const image = data?.findImage; const [incrementO] = useImageIncrementO(image?.id ?? "0"); const [decrementO] = useImageDecrementO(image?.id ?? "0"); const [resetO] = useImageResetO(image?.id ?? "0"); const [updateImage] = useImageUpdate(); const [organizedLoading, setOrganizedLoading] = useState(false); const [activeTabKey, setActiveTabKey] = useState("image-details-panel"); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); async function onRescan() { if (!image || !image.files.length) { return; } await mutateMetadataScan({ paths: [objectPath(image)], }); Toast.success({ content: intl.formatMessage( { id: "toast.rescanning_entity" }, { count: 1, singularEntity: intl.formatMessage({ id: "image" }), } ), }); } const onOrganizedClick = async () => { try { setOrganizedLoading(true); await updateImage({ variables: { input: { id: image?.id ?? "", organized: !image?.organized, }, }, }); } catch (e) { Toast.error(e); } finally { setOrganizedLoading(false); } }; const onIncrementClick = async () => { try { await incrementO(); } catch (e) { Toast.error(e); } }; const onDecrementClick = async () => { try { await decrementO(); } catch (e) { Toast.error(e); } }; const onResetClick = async () => { try { await resetO(); } catch (e) { Toast.error(e); } }; function onDeleteDialogClosed(deleted: boolean) { setIsDeleteAlertOpen(false); if (deleted) { history.push("/images"); } } function maybeRenderDeleteDialog() { if (isDeleteAlertOpen && image) { return ( ); } } function renderOperations() { return ( onRescan()} > setIsDeleteAlertOpen(true)} > ); } function renderTabs() { if (!image) { return; } return ( k && setActiveTabKey(k)} >
setIsDeleteAlertOpen(true)} />
); } // set up hotkeys useEffect(() => { Mousetrap.bind("a", () => setActiveTabKey("image-details-panel")); Mousetrap.bind("e", () => setActiveTabKey("image-edit-panel")); Mousetrap.bind("f", () => setActiveTabKey("image-file-info-panel")); Mousetrap.bind("o", () => { onIncrementClick(); }); return () => { Mousetrap.unbind("a"); Mousetrap.unbind("e"); Mousetrap.unbind("f"); Mousetrap.unbind("o"); }; }); if (loading) { return ; } if (error) return ; if (!image) { return ; } const title = objectTitle(image); return (
{title} {maybeRenderDeleteDialog()}
{image.studio && (

{`${image.studio.name}

)}

{title}

{renderTabs()}
{title}
); };