From 6f5a7d1f0a2f63fc35c8a3f3ef9e034c8db3cbc8 Mon Sep 17 00:00:00 2001 From: WeedLordVegeta420 <81525421+WeedLordVegeta420@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:24:14 -0500 Subject: [PATCH] Add latest scene sort for performers and studios. (#6501) --- pkg/sqlite/performer.go | 25 ++++++++++++++++++++ pkg/sqlite/scene.go | 1 + pkg/sqlite/studio.go | 23 ++++++++++++++++++ ui/v2.5/src/locales/en-GB.json | 1 + ui/v2.5/src/models/list-filter/performers.ts | 1 + ui/v2.5/src/models/list-filter/studios.ts | 1 + 6 files changed, 52 insertions(+) diff --git a/pkg/sqlite/performer.go b/pkg/sqlite/performer.go index 4e06b5b29..bc4461f5f 100644 --- a/pkg/sqlite/performer.go +++ b/pkg/sqlite/performer.go @@ -706,6 +706,28 @@ func (qb *PerformerStore) sortByLastOAt(direction string) string { return " ORDER BY (" + selectPerformerLastOAtSQL + ") " + direction } +// used for sorting on performer latest scene +var selectPerformerLatestSceneSQL = utils.StrFormat( + "SELECT MAX(date) FROM ("+ + "SELECT {date} FROM {performers_scenes} s "+ + "LEFT JOIN {scenes} ON {scenes}.id = s.{scene_id} "+ + "WHERE s.{performer_id} = {performers}.id"+ + ")", + map[string]interface{}{ + "performer_id": performerIDColumn, + "performers": performerTable, + "performers_scenes": performersScenesTable, + "scenes": sceneTable, + "scene_id": sceneIDColumn, + "date": sceneDateColumn, + }, +) + +func (qb *PerformerStore) sortByLatestScene(direction string) string { + // need to get the latest date from scenes + return " ORDER BY (" + selectPerformerLatestSceneSQL + ") " + direction +} + // used for sorting on performer last view_date var selectPerformerLastPlayedAtSQL = utils.StrFormat( "SELECT MAX(view_date) FROM ("+ @@ -762,6 +784,7 @@ var performerSortOptions = sortOptions{ "images_count", "last_o_at", "last_played_at", + "latest_scene", "measurements", "name", "o_counter", @@ -812,6 +835,8 @@ func (qb *PerformerStore) getPerformerSort(findFilter *models.FindFilterType) (s sortQuery += qb.sortByLastPlayedAt(direction) case "last_o_at": sortQuery += qb.sortByLastOAt(direction) + case "latest_scene": + sortQuery += qb.sortByLatestScene(direction) default: sortQuery += getSort(sort, direction, "performers") } diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index a0b9005a5..d92800317 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -26,6 +26,7 @@ const ( sceneTable = "scenes" scenesFilesTable = "scenes_files" sceneIDColumn = "scene_id" + sceneDateColumn = "date" performersScenesTable = "performers_scenes" scenesTagsTable = "scenes_tags" scenesGalleriesTable = "scenes_galleries" diff --git a/pkg/sqlite/studio.go b/pkg/sqlite/studio.go index 1a05be6f3..e328818da 100644 --- a/pkg/sqlite/studio.go +++ b/pkg/sqlite/studio.go @@ -15,6 +15,7 @@ import ( "github.com/stashapp/stash/pkg/models" "github.com/stashapp/stash/pkg/studio" + "github.com/stashapp/stash/pkg/utils" ) const ( @@ -601,12 +602,32 @@ func (qb *StudioStore) sortByScenesDuration(direction string) string { ) %s`, sceneTable, scenesFilesTable, scenesFilesTable, sceneIDColumn, sceneTable, scenesFilesTable, sceneTable, studioIDColumn, studioTable, getSortDirection(direction)) } +// used for sorting on performer latest scene +var selectStudioLatestSceneSQL = utils.StrFormat( + "SELECT MAX(date) FROM ("+ + "SELECT {date} FROM {scenes} s "+ + "WHERE s.{studio_id} = {studios}.id"+ + ")", + map[string]interface{}{ + "scenes": sceneTable, + "studios": studioTable, + "studio_id": studioIDColumn, + "date": sceneDateColumn, + }, +) + +func (qb *StudioStore) sortByLatestScene(direction string) string { + // need to get the latest date from scenes + return " ORDER BY (" + selectStudioLatestSceneSQL + ") " + direction +} + var studioSortOptions = sortOptions{ "child_count", "created_at", "galleries_count", "id", "images_count", + "latest_scene", "name", "scenes_count", "scenes_duration", @@ -646,6 +667,8 @@ func (qb *StudioStore) getStudioSort(findFilter *models.FindFilterType) (string, sortQuery += getCountSort(studioTable, galleryTable, studioIDColumn, direction) case "child_count": sortQuery += getCountSort(studioTable, studioTable, studioParentIDColumn, direction) + case "latest_scene": + sortQuery += qb.sortByLatestScene(direction) default: sortQuery += getSort(sort, direction, "studios") } diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index e417e8cbb..b4eb8a6bc 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -1203,6 +1203,7 @@ "last_o_at": "Last O At", "last_o_at_sfw": "Last Like At", "last_played_at": "Last Played At", + "latest_scene": "Latest Scene", "library": "Library", "loading": { "generic": "Loading…", diff --git a/ui/v2.5/src/models/list-filter/performers.ts b/ui/v2.5/src/models/list-filter/performers.ts index fcc152d01..c0bcb3bba 100644 --- a/ui/v2.5/src/models/list-filter/performers.ts +++ b/ui/v2.5/src/models/list-filter/performers.ts @@ -31,6 +31,7 @@ const sortByOptions = [ "penis_length", "play_count", "last_played_at", + "latest_scene", "career_length", "weight", "measurements", diff --git a/ui/v2.5/src/models/list-filter/studios.ts b/ui/v2.5/src/models/list-filter/studios.ts index 02dfae2f6..42ac1b4dc 100644 --- a/ui/v2.5/src/models/list-filter/studios.ts +++ b/ui/v2.5/src/models/list-filter/studios.ts @@ -21,6 +21,7 @@ const sortByOptions = [ "random", "rating", "scenes_duration", + "latest_scene", ] .map(ListFilterOptions.createSortBy) .concat([