Add options to delete file and generated files

This commit is contained in:
WithoutPants
2019-08-16 07:21:35 +10:00
parent cfe2636837
commit 7ee1b3f052
7 changed files with 141 additions and 19 deletions

View File

@@ -26,6 +26,6 @@ mutation SceneUpdate(
} }
} }
mutation SceneDestroy($id: ID!, $delete_file: Boolean) { mutation SceneDestroy($id: ID!, $delete_file: Boolean, $delete_generated : Boolean) {
sceneDestroy(input: {id: $id, delete_file: $delete_file}) sceneDestroy(input: {id: $id, delete_file: $delete_file, delete_generated: $delete_generated})
} }

View File

@@ -56,6 +56,7 @@ input SceneUpdateInput {
input SceneDestroyInput { input SceneDestroyInput {
id: ID! id: ID!
delete_file: Boolean delete_file: Boolean
delete_generated: Boolean
} }
type FindScenesResultType { type FindScenesResultType {

View File

@@ -4,12 +4,15 @@ import (
"context" "context"
"database/sql" "database/sql"
"os" "os"
"path/filepath"
"strconv" "strconv"
"time" "time"
"github.com/stashapp/stash/pkg/database" "github.com/stashapp/stash/pkg/database"
"github.com/stashapp/stash/pkg/logger" "github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/manager"
"github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/utils"
) )
func (r *mutationResolver) SceneUpdate(ctx context.Context, input models.SceneUpdateInput) (*models.Scene, error) { func (r *mutationResolver) SceneUpdate(ctx context.Context, input models.SceneUpdateInput) (*models.Scene, error) {
@@ -145,6 +148,12 @@ func (r *mutationResolver) SceneDestroy(ctx context.Context, input models.SceneD
return false, err return false, err
} }
// if delete generated is true, then delete the generated files
// for the scene
if input.DeleteGenerated != nil && *input.DeleteGenerated {
deleteGeneratedSceneFiles(scene)
}
// if delete file is true, then delete the file as well // if delete file is true, then delete the file as well
// if it fails, just log a message // if it fails, just log a message
if input.DeleteFile != nil && *input.DeleteFile { if input.DeleteFile != nil && *input.DeleteFile {
@@ -157,6 +166,81 @@ func (r *mutationResolver) SceneDestroy(ctx context.Context, input models.SceneD
return true, nil return true, nil
} }
func deleteGeneratedSceneFiles(scene *models.Scene) {
markersFolder := filepath.Join(manager.GetInstance().Paths.Generated.Markers, scene.Checksum)
exists, _ := utils.FileExists(markersFolder)
if exists {
err := os.RemoveAll(markersFolder)
if err != nil {
logger.Warnf("Could not delete file %s: %s", scene.Path, err.Error())
}
}
thumbPath := manager.GetInstance().Paths.Scene.GetThumbnailScreenshotPath(scene.Checksum)
exists, _ = utils.FileExists(thumbPath)
if exists {
err := os.Remove(thumbPath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", thumbPath, err.Error())
}
}
normalPath := manager.GetInstance().Paths.Scene.GetScreenshotPath(scene.Checksum)
exists, _ = utils.FileExists(normalPath)
if exists {
err := os.Remove(normalPath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", normalPath, err.Error())
}
}
streamPreviewPath := manager.GetInstance().Paths.Scene.GetStreamPreviewPath(scene.Checksum)
exists, _ = utils.FileExists(streamPreviewPath)
if exists {
err := os.Remove(streamPreviewPath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", streamPreviewPath, err.Error())
}
}
streamPreviewImagePath := manager.GetInstance().Paths.Scene.GetStreamPreviewImagePath(scene.Checksum)
exists, _ = utils.FileExists(streamPreviewImagePath)
if exists {
err := os.Remove(streamPreviewImagePath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", streamPreviewImagePath, err.Error())
}
}
transcodePath := manager.GetInstance().Paths.Scene.GetTranscodePath(scene.Checksum)
exists, _ = utils.FileExists(transcodePath)
if exists {
err := os.Remove(transcodePath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", transcodePath, err.Error())
}
}
spritePath := manager.GetInstance().Paths.Scene.GetSpriteImageFilePath(scene.Checksum)
exists, _ = utils.FileExists(spritePath)
if exists {
err := os.Remove(spritePath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", spritePath, err.Error())
}
}
vttPath := manager.GetInstance().Paths.Scene.GetSpriteVttFilePath(scene.Checksum)
exists, _ = utils.FileExists(vttPath)
if exists {
err := os.Remove(vttPath)
if err != nil {
logger.Warnf("Could not delete file %s: %s", vttPath, err.Error())
}
}
}
func (r *mutationResolver) SceneMarkerCreate(ctx context.Context, input models.SceneMarkerCreateInput) (*models.SceneMarker, error) { func (r *mutationResolver) SceneMarkerCreate(ctx context.Context, input models.SceneMarkerCreateInput) (*models.SceneMarker, error) {
primaryTagID, _ := strconv.Atoi(input.PrimaryTagID) primaryTagID, _ := strconv.Atoi(input.PrimaryTagID)
sceneID, _ := strconv.Atoi(input.SceneID) sceneID, _ := strconv.Atoi(input.SceneID)

View File

@@ -2176,6 +2176,7 @@ input SceneUpdateInput {
input SceneDestroyInput { input SceneDestroyInput {
id: ID! id: ID!
delete_file: Boolean delete_file: Boolean
delete_generated: Boolean
} }
type FindScenesResultType { type FindScenesResultType {
@@ -8355,6 +8356,12 @@ func (ec *executionContext) unmarshalInputSceneDestroyInput(ctx context.Context,
if err != nil { if err != nil {
return it, err return it, err
} }
case "delete_generated":
var err error
it.DeleteGenerated, err = ec.unmarshalOBoolean2ᚖbool(ctx, v)
if err != nil {
return it, err
}
} }
} }

View File

@@ -139,6 +139,7 @@ type PerformerUpdateInput struct {
type SceneDestroyInput struct { type SceneDestroyInput struct {
ID string `json:"id"` ID string `json:"id"`
DeleteFile *bool `json:"delete_file"` DeleteFile *bool `json:"delete_file"`
DeleteGenerated *bool `json:"delete_generated"`
} }
type SceneFileType struct { type SceneFileType struct {

View File

@@ -1,6 +1,8 @@
import { import {
Alert,
Button, Button,
Classes,
Checkbox,
Dialog,
FormGroup, FormGroup,
HTMLSelect, HTMLSelect,
InputGroup, InputGroup,
@@ -37,6 +39,7 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
const [deleteFile, setDeleteFile] = useState<boolean>(false); const [deleteFile, setDeleteFile] = useState<boolean>(false);
const [deleteGenerated, setDeleteGenerated] = useState<boolean>(true);
// Network state // Network state
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -98,7 +101,8 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
function getSceneDeleteInput(): GQL.SceneDestroyInput { function getSceneDeleteInput(): GQL.SceneDestroyInput {
return { return {
id: props.scene.id, id: props.scene.id,
delete_file: deleteFile delete_file: deleteFile,
delete_generated: deleteGenerated
}; };
} }
@@ -134,19 +138,31 @@ export const SceneEditPanel: FunctionComponent<IProps> = (props: IProps) => {
function renderDeleteAlert() { function renderDeleteAlert() {
return ( return (
<Alert <>
cancelButtonText="Cancel" <Dialog
confirmButtonText="Delete" canOutsideClickClose={false}
canEscapeKeyClose={false}
icon="trash" icon="trash"
intent="danger" isCloseButtonShown={false}
isOpen={isDeleteAlertOpen} isOpen={isDeleteAlertOpen}
onCancel={() => setIsDeleteAlertOpen(false)} title="Delete Scene?"
onConfirm={() => onDelete()}
> >
<div className={Classes.DIALOG_BODY}>
<p> <p>
Are you sure you want to delete this scene? Unless the file is also deleted, this scene will be re-added when scan is performed. Are you sure you want to delete this scene? Unless the file is also deleted, this scene will be re-added when scan is performed.
</p> </p>
</Alert> <Checkbox checked={deleteFile} label="Delete file" onChange={() => setDeleteFile(!deleteFile)} />
<Checkbox checked={deleteGenerated} label="Delete generated supporting files" onChange={() => setDeleteGenerated(!deleteGenerated)} />
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button intent="danger" onClick={() => onDelete()}>Delete</Button>
<Button onClick={() => setIsDeleteAlertOpen(false)}>Cancel</Button>
</div>
</div>
</Dialog>
</>
); );
} }

View File

@@ -1,6 +1,6 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
// Generated in 2019-08-15T13:55:54+10:00 // Generated in 2019-08-15T18:05:18+10:00
export type Maybe<T> = T | undefined; export type Maybe<T> = T | undefined;
export interface SceneFilterType { export interface SceneFilterType {
@@ -92,6 +92,8 @@ export interface SceneDestroyInput {
id: string; id: string;
delete_file?: Maybe<boolean>; delete_file?: Maybe<boolean>;
delete_generated?: Maybe<boolean>;
} }
export interface SceneMarkerCreateInput { export interface SceneMarkerCreateInput {
@@ -399,6 +401,7 @@ export type SceneUpdateSceneUpdate = SceneDataFragment;
export type SceneDestroyVariables = { export type SceneDestroyVariables = {
id: string; id: string;
delete_file?: Maybe<boolean>; delete_file?: Maybe<boolean>;
delete_generated?: Maybe<boolean>;
}; };
export type SceneDestroyMutation = { export type SceneDestroyMutation = {
@@ -1792,8 +1795,18 @@ export function useSceneUpdate(
>(SceneUpdateDocument, baseOptions); >(SceneUpdateDocument, baseOptions);
} }
export const SceneDestroyDocument = gql` export const SceneDestroyDocument = gql`
mutation SceneDestroy($id: ID!, $delete_file: Boolean) { mutation SceneDestroy(
sceneDestroy(input: { id: $id, delete_file: $delete_file }) $id: ID!
$delete_file: Boolean
$delete_generated: Boolean
) {
sceneDestroy(
input: {
id: $id
delete_file: $delete_file
delete_generated: $delete_generated
}
)
} }
`; `;
export function useSceneDestroy( export function useSceneDestroy(