mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 12:24:38 +03:00
Add Handy / Funscript support (#1377)
* Add funscript route to scenes Adds a /scene/:id/funscript route which serves a funscript file, if present. Current convention is that these are files stored with the same path, but with the extension ".funscript". * Look for funscript during scan This is stored in the Scene record and used to drive UI changes for funscript support. Currently, that's limited to a funscript link in the Scene's file info. * Add filtering and sorting for interactive * Add Handy connection key to interface config * Add Handy client and placeholder component. Uses defucilis/thehandy, but not thehandy-react as I had difficulty integrating the context with the existing components. Instead, the expensive calculation for the server time offset is put in localStorage for reuse. A debounce was added when scrubbing the video, as otherwise it spammed the Handy API with updates to the current offset.
This commit is contained in:
committed by
GitHub
parent
33999d3e93
commit
547f6d79ad
@@ -295,6 +295,12 @@ func (t *ScanTask) getFileModTime() (time.Time, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (t *ScanTask) getInteractive() bool {
|
||||
_, err := os.Stat(utils.GetFunscriptPath(t.FilePath))
|
||||
return err == nil
|
||||
|
||||
}
|
||||
|
||||
func (t *ScanTask) isFileModified(fileModTime time.Time, modTime models.NullSQLiteTimestamp) bool {
|
||||
return !modTime.Timestamp.Equal(fileModTime)
|
||||
}
|
||||
@@ -376,6 +382,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||
if err != nil {
|
||||
return logError(err)
|
||||
}
|
||||
interactive := t.getInteractive()
|
||||
|
||||
if s != nil {
|
||||
// if file mod time is not set, set it now
|
||||
@@ -484,6 +491,20 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||
}
|
||||
}
|
||||
|
||||
if s.Interactive != interactive {
|
||||
if err := t.TxnManager.WithTxn(context.TODO(), func(r models.Repository) error {
|
||||
qb := r.Scene()
|
||||
scenePartial := models.ScenePartial{
|
||||
ID: s.ID,
|
||||
Interactive: &interactive,
|
||||
}
|
||||
_, err := qb.Update(scenePartial)
|
||||
return err
|
||||
}); err != nil {
|
||||
return logError(err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -549,8 +570,9 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||
} else {
|
||||
logger.Infof("%s already exists. Updating path...", t.FilePath)
|
||||
scenePartial := models.ScenePartial{
|
||||
ID: s.ID,
|
||||
Path: &t.FilePath,
|
||||
ID: s.ID,
|
||||
Path: &t.FilePath,
|
||||
Interactive: &interactive,
|
||||
}
|
||||
if err := t.TxnManager.WithTxn(context.TODO(), func(r models.Repository) error {
|
||||
_, err := r.Scene().Update(scenePartial)
|
||||
@@ -580,8 +602,9 @@ func (t *ScanTask) scanScene() *models.Scene {
|
||||
Timestamp: fileModTime,
|
||||
Valid: true,
|
||||
},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
CreatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
UpdatedAt: models.SQLiteTimestamp{Timestamp: currentTime},
|
||||
Interactive: interactive,
|
||||
}
|
||||
|
||||
if t.UseFileMetadata {
|
||||
|
||||
Reference in New Issue
Block a user