* Skip scanning zip contents when fingerprint is unchanged
When a zip-based gallery's modification time changes but its content
hash (oshash/md5) remains the same, skip walking and rescanning every
file inside the zip. This avoids expensive per-file fingerprint
recalculation when zip metadata changes without actual content changes.
Closes#6512
* Log a debug message when skipping a zip scan due to unchanged
fingerprint
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
* Replace panic with warning if creating a folder hierarchy where parent is equal to current
* Clean stash paths so that comparison works correctly when creating folder hierarchies
* Add basename field to folder
* Add parent_folders field to folder
* Add basename column to folder table
* Add basename filter field
* Create missing folder hierarchies during migration
* Treat files/folders in zips where path can't be made relative as not found
Addresses an issue during clean where corrupt folder entries in zip files could not be removed due to an error during the call to Rel.
* Add root paths parameter to GetOrCreateFolderHierarchy
Ensures that folders are only created up to the root library paths.
* Create full folder hierarchy when scanning a new folder
During a recursive scan, folders should be created as they are encountered (folders are handled in a single thread). This change applies only during a selective scan. Creates up to the root library folder.
* Create folder hierarchy on new file scan
This should only apply when scanning a specific file, as parent folders should be been created during a recursive scan.
* Fix existing folders with missing parents during scan
* Add reveal in file manager button to file info panel
Adds a folder icon button next to the path field in the Scene, Image,
and Gallery file info panels. Clicking it calls a new GraphQL mutation
that opens the file's enclosing directory in the system file manager
(Finder on macOS, Explorer on Windows, xdg-open on Linux).
Also fixes the existing revealInFileManager implementations which were
constructing exec.Command but never calling Run(), making them no-ops:
- darwin: add Run() to open -R
- windows: add Run() and fix flag from \select to /select,<path>
- linux: implement with xdg-open on the parent directory
- desktop.go: use os.Stat instead of FileExists so folders work too
* Disallow reveal operation if request not from loopback
---------
Co-authored-by: 1509x <1509x@users.noreply.github.com>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
* Fix custom field import/export for studio
* Update studio unit tests
* Add tag create and update unit tests
* Add custom fields to tag filter graphql
* Add unit tests for tag filtering
* Add filter unit tests for studio
* fix(dlna): improve activity tracking accuracy and efficiency
- Remove play duration tracking: DLNA clients buffer aggressively and
don't report playback position, making duration estimates unreliable.
Saving inaccurate values corrupts analytics.
- Combine database transactions: Resume time and view count updates
now happen in a single transaction for atomicity and performance.
- Keep resume time tracking: While imprecise, it provides useful
"continue watching" hints. The cost of being wrong is low (user
just seeks).
* remove elasped time check
Adds time-based activity tracking for scenes played via DLNA, enabling
play count, play duration, and resume time tracking similar to the
web frontend.
Key features:
- Uses existing 'trackActivity' UI setting (no new config needed)
- Time-based tracking (elapsed session time / video duration)
- 5-minute session timeout to handle aggressive client buffering
- Minimum thresholds before saving (1% watched or 5 seconds)
- Respects minimumPlayPercent setting for play count increment
Implementation:
- New ActivityTracker in internal/dlna/activity.go
- Session management with automatic expiration
- Integration via DLNA service initialization
Limitations:
- Cannot detect actual playback position (only elapsed time)
- Cannot detect seeking or pause state
- Designed for upstream compatibility (no complex dependencies)
* Implement merging of performers
* Make the tag merge UI consistent with other types of merges
* Add merge action in scene menu
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This was originally done for #3304. The ffmpeg code has been redone since and this is no longer necessary. It was also resulting in the scraper and plugin paths being absolute, despite all the others being relative to the provided config path.