Support file-less scenes. Add scene split, merge and reassign file (#3006)

* Reassign scene file functionality
* Implement scene create
* Add scene create UI
* Add sceneMerge backend support
* Add merge scene to UI
* Populate split create with scene details
* Add merge button to duplicate checker
* Handle file-less scenes in marker preview generate
* Make unique file name for file-less scene exports
* Add o-counter to scene update input
* Hide rescan for file-less scenes
* Generate heatmap if no speed set on file
* Fix count in scene/image queries
This commit is contained in:
WithoutPants
2022-11-14 16:35:09 +11:00
committed by GitHub
parent d0b0be4dd4
commit 4a054ab081
60 changed files with 2550 additions and 412 deletions

View File

@@ -746,7 +746,7 @@ func (qb *ImageStore) queryGroupedFields(ctx context.Context, options models.Ima
aggregateQuery := qb.newQuery()
if options.Count {
aggregateQuery.addColumn("COUNT(temp.id) as total")
aggregateQuery.addColumn("COUNT(DISTINCT temp.id) as total")
}
// TODO - this doesn't work yet

View File

@@ -975,7 +975,7 @@ func (qb *SceneStore) queryGroupedFields(ctx context.Context, options models.Sce
aggregateQuery := qb.newQuery()
if options.Count {
aggregateQuery.addColumn("COUNT(temp.id) as total")
aggregateQuery.addColumn("COUNT(DISTINCT temp.id) as total")
}
if options.TotalDuration {
@@ -1432,6 +1432,22 @@ func (qb *SceneStore) DestroyCover(ctx context.Context, sceneID int) error {
return qb.imageRepository().destroy(ctx, []int{sceneID})
}
func (qb *SceneStore) AssignFiles(ctx context.Context, sceneID int, fileIDs []file.ID) error {
// assuming a file can only be assigned to a single scene
if err := scenesFilesTableMgr.destroyJoins(ctx, fileIDs); err != nil {
return err
}
// assign primary only if destination has no files
existingFileIDs, err := qb.filesRepository().get(ctx, sceneID)
if err != nil {
return err
}
firstPrimary := len(existingFileIDs) == 0
return scenesFilesTableMgr.insertJoins(ctx, sceneID, firstPrimary, fileIDs)
}
func (qb *SceneStore) moviesRepository() *repository {
return &repository{
tx: qb.tx,

View File

@@ -4077,5 +4077,47 @@ func TestSceneStore_FindDuplicates(t *testing.T) {
})
}
func TestSceneStore_AssignFiles(t *testing.T) {
tests := []struct {
name string
sceneID int
fileID file.ID
wantErr bool
}{
{
"valid",
sceneIDs[sceneIdx1WithPerformer],
sceneFileIDs[sceneIdx1WithStudio],
false,
},
{
"invalid file id",
sceneIDs[sceneIdx1WithPerformer],
invalidFileID,
true,
},
{
"invalid scene id",
invalidID,
sceneFileIDs[sceneIdx1WithStudio],
true,
},
}
qb := db.Scene
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
withRollbackTxn(func(ctx context.Context) error {
if err := qb.AssignFiles(ctx, tt.sceneID, []file.ID{tt.fileID}); (err != nil) != tt.wantErr {
t.Errorf("SceneStore.AssignFiles() error = %v, wantErr %v", err, tt.wantErr)
}
return nil
})
})
}
}
// TODO Count
// TODO SizeCount

View File

@@ -529,6 +529,17 @@ func (t *relatedFilesTable) replaceJoins(ctx context.Context, id int, fileIDs []
return t.insertJoins(ctx, id, firstPrimary, fileIDs)
}
// destroyJoins destroys all entries in the table with the provided fileIDs
func (t *relatedFilesTable) destroyJoins(ctx context.Context, fileIDs []file.ID) error {
q := dialect.Delete(t.table.table).Where(t.table.table.Col("file_id").In(fileIDs))
if _, err := exec(ctx, q); err != nil {
return fmt.Errorf("destroying file joins in %s: %w", t.table.table.GetTable(), err)
}
return nil
}
func (t *relatedFilesTable) setPrimary(ctx context.Context, id int, fileID file.ID) error {
table := t.table.table