diff --git a/pkg/sqlite/scene.go b/pkg/sqlite/scene.go index a727c7bfd..2ded07b9c 100644 --- a/pkg/sqlite/scene.go +++ b/pkg/sqlite/scene.go @@ -673,6 +673,9 @@ func (qb *sceneQueryBuilder) setSceneSort(query *queryBuilder, findFilter *model sort := findFilter.GetSort("title") direction := findFilter.GetDirection() switch sort { + case "movie_scene_number": + query.join(moviesScenesTable, "movies_join", "scenes.id") + query.sortAndPagination += fmt.Sprintf(" ORDER BY movies_join.scene_index %s", getSortDirection(direction)) case "tag_count": query.sortAndPagination += getCountSort(sceneTable, scenesTagsTable, sceneIDColumn, direction) case "performer_count": diff --git a/ui/v2.5/src/components/Changelog/versions/v070.md b/ui/v2.5/src/components/Changelog/versions/v070.md index 83c9afc60..170198522 100644 --- a/ui/v2.5/src/components/Changelog/versions/v070.md +++ b/ui/v2.5/src/components/Changelog/versions/v070.md @@ -11,6 +11,7 @@ * Added scene queue. ### 🎨 Improvements +* Sort movie scenes by scene number by default. * Support http request headers in scrapers. * Sort performers by gender in scene/image/gallery cards and details. * Add popover buttons for scenes/images/galleries on performer/studio/tag cards. diff --git a/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx b/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx index 8a6f8c7be..aae203f8b 100644 --- a/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx +++ b/ui/v2.5/src/components/Movies/MovieDetails/MovieScenesPanel.tsx @@ -42,7 +42,9 @@ export const MovieScenesPanel: React.FC = ({ movie }) => { } if (movie && movie.id) { - return ; + return ( + + ); } return <>; }; diff --git a/ui/v2.5/src/components/Scenes/SceneList.tsx b/ui/v2.5/src/components/Scenes/SceneList.tsx index 7dc01c2c6..22b8a18e0 100644 --- a/ui/v2.5/src/components/Scenes/SceneList.tsx +++ b/ui/v2.5/src/components/Scenes/SceneList.tsx @@ -23,11 +23,13 @@ import { SceneCardsGrid } from "./SceneCardsGrid"; interface ISceneList { filterHook?: (filter: ListFilterModel) => ListFilterModel; + defaultSort?: string; persistState?: PersistanceLevel.ALL; } export const SceneList: React.FC = ({ filterHook, + defaultSort, persistState, }) => { const history = useHistory(); @@ -83,6 +85,7 @@ export const SceneList: React.FC = ({ zoomable: true, selectable: true, otherOperations, + defaultSort, renderContent, renderEditDialog: renderEditScenesDialog, renderDeleteDialog, diff --git a/ui/v2.5/src/hooks/ListHook.tsx b/ui/v2.5/src/hooks/ListHook.tsx index 1365da170..5aec643ff 100644 --- a/ui/v2.5/src/hooks/ListHook.tsx +++ b/ui/v2.5/src/hooks/ListHook.tsx @@ -88,6 +88,7 @@ export enum PersistanceLevel { interface IListHookOptions { persistState?: PersistanceLevel; persistanceKey?: string; + defaultSort?: string; filterHook?: (filter: ListFilterModel) => ListFilterModel; zoomable?: boolean; selectable?: boolean; @@ -431,7 +432,11 @@ const useList = ( const persistanceKey = options.persistanceKey ?? options.filterMode; const [filter, setFilter] = useState( - new ListFilterModel(options.filterMode, queryString.parse(location.search)) + new ListFilterModel( + options.filterMode, + queryString.parse(location.search), + options.defaultSort + ) ); const updateInterfaceConfig = useCallback( diff --git a/ui/v2.5/src/models/list-filter/filter.ts b/ui/v2.5/src/models/list-filter/filter.ts index 2aad3672f..917aa07e2 100644 --- a/ui/v2.5/src/models/list-filter/filter.ts +++ b/ui/v2.5/src/models/list-filter/filter.ts @@ -111,11 +111,15 @@ export class ListFilterModel { return new CriterionOption(Criterion.getLabel(criterion), criterion); } - public constructor(filterMode: FilterMode, rawParms?: ParsedQuery) { + public constructor( + filterMode: FilterMode, + rawParms?: ParsedQuery, + defaultSort?: string + ) { const params = rawParms as IQueryParameters; switch (filterMode) { case FilterMode.Scenes: - this.sortBy = "date"; + this.sortBy = defaultSort ?? "date"; this.sortByOptions = [ "title", "path", @@ -131,6 +135,7 @@ export class ListFilterModel { "tag_count", "performer_count", "random", + "movie_scene_number", ]; this.displayModeOptions = [ DisplayMode.Grid, @@ -159,7 +164,7 @@ export class ListFilterModel { ]; break; case FilterMode.Images: - this.sortBy = "path"; + this.sortBy = defaultSort ?? "path"; this.sortByOptions = [ "title", "path", @@ -189,7 +194,7 @@ export class ListFilterModel { ]; break; case FilterMode.Performers: { - this.sortBy = "name"; + this.sortBy = defaultSort ?? "name"; this.sortByOptions = [ "name", "height", @@ -239,7 +244,7 @@ export class ListFilterModel { break; } case FilterMode.Studios: - this.sortBy = "name"; + this.sortBy = defaultSort ?? "name"; this.sortByOptions = [ "name", "scenes_count", @@ -259,7 +264,7 @@ export class ListFilterModel { ]; break; case FilterMode.Movies: - this.sortBy = "name"; + this.sortBy = defaultSort ?? "name"; this.sortByOptions = ["name", "scenes_count", "random"]; this.displayModeOptions = [DisplayMode.Grid]; this.criterionOptions = [ @@ -270,7 +275,7 @@ export class ListFilterModel { ]; break; case FilterMode.Galleries: - this.sortBy = "path"; + this.sortBy = defaultSort ?? "path"; this.sortByOptions = [ "path", "file_mod_time", @@ -302,7 +307,7 @@ export class ListFilterModel { ]; break; case FilterMode.SceneMarkers: - this.sortBy = "title"; + this.sortBy = defaultSort ?? "title"; this.sortByOptions = [ "title", "seconds", @@ -319,7 +324,7 @@ export class ListFilterModel { ]; break; case FilterMode.Tags: - this.sortBy = "name"; + this.sortBy = defaultSort ?? "name"; // scene markers count has been disabled for now due to performance // issues this.sortByOptions = [