From f7a8899d901bcbec1f8cb7f41e169c00e9a1e291 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Tue, 23 Feb 2021 12:56:01 +1100 Subject: [PATCH] Add rescan option to overflow dropdown (#1119) * Make scan options optional * Add scene rescan * Add image rescan * Add gallery rescan * Add changelog --- graphql/schema/types/metadata.graphql | 10 +++---- pkg/image/image.go | 7 +++++ pkg/manager/manager_tasks.go | 10 +++---- pkg/manager/task_scan.go | 6 +++++ pkg/utils/boolean.go | 5 ++++ .../src/components/Changelog/Changelog.tsx | 11 +++++++- .../src/components/Changelog/versions/v060.md | 2 ++ .../Galleries/GalleryDetails/Gallery.tsx | 27 ++++++++++++++++++- .../components/Images/ImageDetails/Image.tsx | 20 ++++++++++++++ .../components/Scenes/SceneDetails/Scene.tsx | 21 +++++++++++++++ 10 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 ui/v2.5/src/components/Changelog/versions/v060.md diff --git a/graphql/schema/types/metadata.graphql b/graphql/schema/types/metadata.graphql index d00e2846c..f83f3ad78 100644 --- a/graphql/schema/types/metadata.graphql +++ b/graphql/schema/types/metadata.graphql @@ -33,15 +33,15 @@ input GeneratePreviewOptionsInput { input ScanMetadataInput { paths: [String!] """Set name, date, details from metadata (if present)""" - useFileMetadata: Boolean! + useFileMetadata: Boolean """Strip file extension from title""" - stripFileExtension: Boolean! + stripFileExtension: Boolean """Generate previews during scan""" - scanGeneratePreviews: Boolean! + scanGeneratePreviews: Boolean """Generate image previews during scan""" - scanGenerateImagePreviews: Boolean! + scanGenerateImagePreviews: Boolean """Generate sprites during scan""" - scanGenerateSprites: Boolean! + scanGenerateSprites: Boolean } input CleanMetadataInput { diff --git a/pkg/image/image.go b/pkg/image/image.go index ec781afb7..f11579a0f 100644 --- a/pkg/image/image.go +++ b/pkg/image/image.go @@ -59,6 +59,13 @@ func ZipFilename(zipFilename, filenameInZip string) string { return zipFilename + zipSeparator + filenameInZip } +// IsZipPath returns true if the path includes the zip separator byte, +// indicating it is within a zip file. +// TODO - this should be moved to utils +func IsZipPath(p string) bool { + return strings.Contains(p, zipSeparator) +} + type imageReadCloser struct { src io.ReadCloser zrc *zip.ReadCloser diff --git a/pkg/manager/manager_tasks.go b/pkg/manager/manager_tasks.go index cf36f4c67..28e42022b 100644 --- a/pkg/manager/manager_tasks.go +++ b/pkg/manager/manager_tasks.go @@ -215,13 +215,13 @@ func (s *singleton) Scan(input models.ScanMetadataInput) { task := ScanTask{ TxnManager: s.TxnManager, FilePath: path, - UseFileMetadata: input.UseFileMetadata, - StripFileExtension: input.StripFileExtension, + UseFileMetadata: utils.IsTrue(input.UseFileMetadata), + StripFileExtension: utils.IsTrue(input.StripFileExtension), fileNamingAlgorithm: fileNamingAlgo, calculateMD5: calculateMD5, - GeneratePreview: input.ScanGeneratePreviews, - GenerateImagePreview: input.ScanGenerateImagePreviews, - GenerateSprite: input.ScanGenerateSprites, + GeneratePreview: utils.IsTrue(input.ScanGeneratePreviews), + GenerateImagePreview: utils.IsTrue(input.ScanGenerateImagePreviews), + GenerateSprite: utils.IsTrue(input.ScanGenerateSprites), } go task.Start(&wg) diff --git a/pkg/manager/task_scan.go b/pkg/manager/task_scan.go index f89600149..e2ac3834c 100644 --- a/pkg/manager/task_scan.go +++ b/pkg/manager/task_scan.go @@ -1044,6 +1044,12 @@ func walkFilesToScan(s *models.StashConfig, f filepath.WalkFunc) error { excludeVidRegex := generateRegexps(config.GetExcludes()) excludeImgRegex := generateRegexps(config.GetImageExcludes()) + // don't scan zip images directly + if image.IsZipPath(s.Path) { + logger.Warnf("Cannot rescan zip image %s. Rescan zip gallery instead.", s.Path) + return nil + } + generatedPath := config.GetGeneratedPath() return utils.SymWalk(s.Path, func(path string, info os.FileInfo, err error) error { diff --git a/pkg/utils/boolean.go b/pkg/utils/boolean.go index f0abd02c3..a5f23733b 100644 --- a/pkg/utils/boolean.go +++ b/pkg/utils/boolean.go @@ -7,3 +7,8 @@ func Btoi(b bool) int { } return 0 } + +// IsTrue returns true if the bool pointer is not nil and true. +func IsTrue(b *bool) bool { + return b != nil && *b +} diff --git a/ui/v2.5/src/components/Changelog/Changelog.tsx b/ui/v2.5/src/components/Changelog/Changelog.tsx index 1d8d321e8..7d0434a3c 100644 --- a/ui/v2.5/src/components/Changelog/Changelog.tsx +++ b/ui/v2.5/src/components/Changelog/Changelog.tsx @@ -8,6 +8,7 @@ import V021 from "./versions/v021.md"; import V030 from "./versions/v030.md"; import V040 from "./versions/v040.md"; import V050 from "./versions/v050.md"; +import V060 from "./versions/v060.md"; import { MarkdownPage } from "../Shared/MarkdownPage"; const Changelog: React.FC = () => { @@ -37,11 +38,19 @@ const Changelog: React.FC = () => { <>

Changelog:

+ + + diff --git a/ui/v2.5/src/components/Changelog/versions/v060.md b/ui/v2.5/src/components/Changelog/versions/v060.md new file mode 100644 index 000000000..1ffc59935 --- /dev/null +++ b/ui/v2.5/src/components/Changelog/versions/v060.md @@ -0,0 +1,2 @@ +### 🎨 Improvements +* Added Rescan button to scene, image, gallery details overflow button. diff --git a/ui/v2.5/src/components/Galleries/GalleryDetails/Gallery.tsx b/ui/v2.5/src/components/Galleries/GalleryDetails/Gallery.tsx index b4353fdde..f947bd658 100644 --- a/ui/v2.5/src/components/Galleries/GalleryDetails/Gallery.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryDetails/Gallery.tsx @@ -1,7 +1,11 @@ import { Tab, Nav, Dropdown } from "react-bootstrap"; import React, { useEffect, useState } from "react"; import { useParams, useHistory, Link } from "react-router-dom"; -import { useFindGallery, useGalleryUpdate } from "src/core/StashService"; +import { + mutateMetadataScan, + useFindGallery, + useGalleryUpdate, +} from "src/core/StashService"; import { ErrorMessage, LoadingIndicator, Icon } from "src/components/Shared"; import { TextUtils } from "src/utils"; import * as Mousetrap from "mousetrap"; @@ -60,6 +64,18 @@ export const Gallery: React.FC = () => { } }; + async function onRescan() { + if (!gallery || !gallery.path) { + return; + } + + await mutateMetadataScan({ + paths: [gallery.path], + }); + + Toast.success({ content: "Rescanning image" }); + } + const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); function onDeleteDialogClosed(deleted: boolean) { @@ -92,6 +108,15 @@ export const Gallery: React.FC = () => { + {gallery?.path ? ( + onRescan()} + > + Rescan + + ) : undefined} { const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState(false); + async function onRescan() { + if (!image) { + return; + } + + await mutateMetadataScan({ + paths: [image.path], + }); + + Toast.success({ content: "Rescanning image" }); + } + const onOrganizedClick = async () => { try { setOrganizedLoading(true); @@ -121,6 +134,13 @@ export const Image: React.FC = () => { + onRescan()} + > + Rescan + { error: streamableError, loading: streamableLoading, } = useSceneStreams(id); + const [oLoading, setOLoading] = useState(false); const [incrementO] = useSceneIncrementO(scene?.id ?? "0"); const [decrementO] = useSceneDecrementO(scene?.id ?? "0"); @@ -130,6 +132,18 @@ export const Scene: React.FC = () => { setTimestamp(marker.seconds); } + async function onRescan() { + if (!scene) { + return; + } + + await mutateMetadataScan({ + paths: [scene.path], + }); + + Toast.success({ content: "Rescanning scene" }); + } + async function onGenerateScreenshot(at?: number) { if (!scene) { return; @@ -184,6 +198,13 @@ export const Scene: React.FC = () => { + onRescan()} + > + Rescan +