From db5a514ae69ff9cbda72547b881d6bead1bf3b84 Mon Sep 17 00:00:00 2001
From: amit handa <amit.handa@gmail.com>
Date: Wed, 18 Jan 2023 19:10:55 -0800
Subject: [PATCH] only process incremental media and skip non media files

---
 api/scanner/scanner_album.go             | 16 ++++++++--
 api/scanner/scanner_media.go             |  2 +-
 api/scanner/scanner_queue/queue.go       | 40 +++++++++++++++++++-----
 api/scanner/scanner_task/scanner_task.go |  8 ++++-
 4 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/api/scanner/scanner_album.go b/api/scanner/scanner_album.go
index f6abc42..16e7c09 100644
--- a/api/scanner/scanner_album.go
+++ b/api/scanner/scanner_album.go
@@ -149,8 +149,20 @@ func findMediaForAlbum(ctx scanner_task.TaskContext) ([]*models.Media, error) {
 		return nil, err
 	}
 
-	for _, item := range dirContent {
-		mediaPath := path.Join(ctx.GetAlbum().Path, item.Name())
+	var mediaNames = ctx.GetMediaNames()
+	if len(mediaNames) == 0 {
+		for _, item := range dirContent {
+			mediaNames = append(mediaNames, item.Name())
+		}
+	}
+
+	for _, mediaName := range mediaNames {
+		mediaPath := path.Join(ctx.GetAlbum().Path, mediaName)
+		item, err := os.Stat(mediaPath)
+		if err != nil {
+			log.Printf("cannot find file")
+			continue
+		}
 
 		isDirSymlink, err := utils.IsDirSymlink(mediaPath)
 		if err != nil {
diff --git a/api/scanner/scanner_media.go b/api/scanner/scanner_media.go
index eaefb02..f76b1eb 100644
--- a/api/scanner/scanner_media.go
+++ b/api/scanner/scanner_media.go
@@ -81,7 +81,7 @@ func ProcessSingleMedia(db *gorm.DB, media *models.Media) error {
 
 	media_data := media_encoding.NewEncodeMediaData(media)
 
-	task_context := scanner_task.NewTaskContext(context.Background(), db, &album, album_cache)
+	task_context := scanner_task.NewTaskContext(context.Background(), db, &album, []string{}, album_cache)
 	new_ctx, err := scanner_tasks.Tasks.BeforeProcessMedia(task_context, &media_data)
 	if err != nil {
 		return err
diff --git a/api/scanner/scanner_queue/queue.go b/api/scanner/scanner_queue/queue.go
index ccf5f35..83d9727 100644
--- a/api/scanner/scanner_queue/queue.go
+++ b/api/scanner/scanner_queue/queue.go
@@ -4,9 +4,9 @@ import (
 	"container/list"
 	"context"
 	"fmt"
+	"github.com/photoview/photoview/api/scanner/media_type"
 	"log"
 	"path"
-	"reflect"
 	"sync"
 	"time"
 
@@ -23,8 +23,7 @@ import (
 
 // ScannerJob describes a job on the queue to be run by the scanner over a single album
 type ScannerJob struct {
-	ctx         scanner_task.TaskContext
-	media_paths []string
+	ctx scanner_task.TaskContext
 	// album *models.Album
 	// cache *scanner_cache.AlbumScannerCache
 }
@@ -32,7 +31,6 @@ type ScannerJob struct {
 func NewScannerJob(ctx scanner_task.TaskContext) ScannerJob {
 	return ScannerJob{
 		ctx,
-		make([]string, 0),
 	}
 }
 
@@ -155,7 +153,7 @@ func (queue *ScannerQueue) processQueue(notifyThrottle *utils.Throttle) {
 			// Delete finished job from queue
 			queue.mutex.Lock()
 			for i, x := range queue.in_progress {
-				if x.ctx == nextJob.ctx && reflect.DeepEqual(x.media_paths, nextJob.media_paths) {
+				if x.ctx == nextJob.ctx {
 					queue.in_progress[i] = queue.in_progress[len(queue.in_progress)-1]
 					queue.in_progress = queue.in_progress[0 : len(queue.in_progress)-1]
 					break
@@ -243,7 +241,7 @@ func AddUserToQueue(user *models.User) error {
 	global_scanner_queue.mutex.Lock()
 	for _, album := range albums {
 		global_scanner_queue.addJob(&ScannerJob{
-			ctx: scanner_task.NewTaskContext(context.Background(), global_scanner_queue.db, album, album_cache),
+			ctx: scanner_task.NewTaskContext(context.Background(), global_scanner_queue.db, album, make([]string, 0), album_cache),
 		})
 	}
 	global_scanner_queue.mutex.Unlock()
@@ -254,6 +252,14 @@ func AddUserToQueue(user *models.User) error {
 func AddMediaToQueue(mediaPath string) error {
 	var media *models.Media
 
+	mediatype, err := media_type.GetMediaType(mediaPath)
+	if err != nil {
+		return errors.Wrap(err, "not media")
+	}
+	if mediatype == nil || !mediatype.IsSupported() {
+		return errors.New("unsupported media")
+	}
+
 	if err := global_scanner_queue.db.Preload("Album").Where("path = ?", mediaPath).Find(&media).Error; err != nil {
 		return errors.Wrap(err, "media by path database query")
 	}
@@ -262,6 +268,7 @@ func AddMediaToQueue(mediaPath string) error {
 	var album *models.Album
 	var subalbumPath string
 	if media == nil || media.ID == 0 {
+
 		albumPath := path.Dir(mediaPath)
 		for album == nil {
 			if err := global_scanner_queue.db.Where("path = ?", albumPath).Find(&album).Error; err != nil {
@@ -280,14 +287,31 @@ func AddMediaToQueue(mediaPath string) error {
 		return errors.Wrap(err, "find owners for album")
 	}
 
+	album_cache := scanner_cache.MakeAlbumCache()
 	scanQueue := list.New()
 	scanQueue.PushBack(scanner.ScanInfo{
 		Path:   subalbumPath,
 		Parent: album,
 		Ignore: nil,
 	})
-	album_cache := scanner_cache.MakeAlbumCache()
-	scanner.ProcessUserAlbums(scanQueue, global_scanner_queue.db, userAlbumOwner, album_cache)
+	all_albums, album_errors := scanner.ProcessUserAlbums(scanQueue, global_scanner_queue.db, userAlbumOwner, album_cache)
+	for _, err := range album_errors {
+		return errors.Wrapf(err, "find albums")
+	}
+
+	var mediapaths []string
+	if len(all_albums) > 1 {
+		mediapaths = []string{path.Base(mediaPath)}
+	} else {
+		mediapaths = []string{}
+	}
+	global_scanner_queue.mutex.Lock()
+	for _, album := range all_albums {
+		global_scanner_queue.addJob(&ScannerJob{
+			ctx: scanner_task.NewTaskContext(context.Background(), global_scanner_queue.db, album, mediapaths, album_cache),
+		})
+	}
+	global_scanner_queue.mutex.Unlock()
 
 	return nil
 }
diff --git a/api/scanner/scanner_task/scanner_task.go b/api/scanner/scanner_task/scanner_task.go
index 110238a..cee1e38 100644
--- a/api/scanner/scanner_task/scanner_task.go
+++ b/api/scanner/scanner_task/scanner_task.go
@@ -39,9 +39,10 @@ type TaskContext struct {
 	ctx context.Context
 }
 
-func NewTaskContext(parent context.Context, db *gorm.DB, album *models.Album, cache *scanner_cache.AlbumScannerCache) TaskContext {
+func NewTaskContext(parent context.Context, db *gorm.DB, album *models.Album, mediapaths []string, cache *scanner_cache.AlbumScannerCache) TaskContext {
 	ctx := TaskContext{ctx: parent}
 	ctx = ctx.WithValue(taskCtxKeyAlbum, album)
+	ctx = ctx.WithValue(taskCtxKeyMediaNames, mediapaths)
 	ctx = ctx.WithValue(taskCtxKeyAlbumCache, cache)
 	ctx = ctx.WithDB(db)
 
@@ -52,6 +53,7 @@ type taskCtxKeyType string
 
 const (
 	taskCtxKeyAlbum      taskCtxKeyType = "task_album"
+	taskCtxKeyMediaNames taskCtxKeyType = "task_media_names"
 	taskCtxKeyAlbumCache taskCtxKeyType = "task_album_cache"
 	taskCtxKeyDatabase   taskCtxKeyType = "task_database"
 )
@@ -60,6 +62,10 @@ func (c TaskContext) GetAlbum() *models.Album {
 	return c.ctx.Value(taskCtxKeyAlbum).(*models.Album)
 }
 
+func (c TaskContext) GetMediaNames() []string {
+	return c.ctx.Value(taskCtxKeyMediaNames).([]string)
+}
+
 func (c TaskContext) GetCache() *scanner_cache.AlbumScannerCache {
 	return c.ctx.Value(taskCtxKeyAlbumCache).(*scanner_cache.AlbumScannerCache)
 }
