Skip to content

Commit

Permalink
Support patching select sorting function (#4903)
Browse files Browse the repository at this point in the history
* Fix return types for RegisterComponent and PatchFunction
* Add support for patching TagSelect.sort
* Add support for patching PerformerSelect.sort
* Patch other select component sort functions
* Document patchable functions/components
  • Loading branch information
WithoutPants authored May 31, 2024
1 parent eec3172 commit 540e80c
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 37 deletions.
24 changes: 20 additions & 4 deletions ui/v2.5/src/components/Galleries/GallerySelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { useCompare } from "src/hooks/state";
import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query";
import { galleryTitle } from "src/core/galleries";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";
import {
Criterion,
CriterionValue,
Expand All @@ -49,6 +49,24 @@ type ExtraGalleryProps = {
extraCriteria?: Array<Criterion<CriterionValue>>;
};

type FindGalleriesResult = Awaited<
ReturnType<typeof queryFindGalleriesForSelect>
>["data"]["findGalleries"]["galleries"];

function sortGalleriesByRelevance(
input: string,
galleries: FindGalleriesResult
) {
return sortByRelevance(input, galleries, galleryTitle, (g) => {
return g.files.map((f) => f.path).concat(g.folder?.path ?? []);
});
}

const gallerySelectSort = PatchFunction(
"GallerySelect.sort",
sortGalleriesByRelevance
);

const _GallerySelect: React.FC<
IFilterProps & IFilterValueProps<Gallery> & ExtraGalleryProps
> = (props) => {
Expand Down Expand Up @@ -78,9 +96,7 @@ const _GallerySelect: React.FC<
return !exclude.includes(gallery.id.toString());
});

return sortByRelevance(input, ret, galleryTitle, (g) => {
return g.files.map((f) => f.path).concat(g.folder?.path ?? []);
}).map((gallery) => ({
return gallerySelectSort(input, ret).map((gallery) => ({
value: gallery.id,
object: gallery,
}));
Expand Down
27 changes: 20 additions & 7 deletions ui/v2.5/src/components/Movies/MovieSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { useCompare } from "src/hooks/state";
import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";
import { TruncatedText } from "../Shared/TruncatedText";

export type Movie = Pick<
Expand All @@ -38,6 +38,24 @@ export type Movie = Pick<
};
type Option = SelectOption<Movie>;

type FindMoviesResult = Awaited<
ReturnType<typeof queryFindMoviesForSelect>
>["data"]["findMovies"]["movies"];

function sortMoviesByRelevance(input: string, movies: FindMoviesResult) {
return sortByRelevance(
input,
movies,
(m) => m.name,
(m) => (m.aliases ? [m.aliases] : [])
);
}

const movieSelectSort = PatchFunction(
"MovieSelect.sort",
sortMoviesByRelevance
);

const _MovieSelect: React.FC<
IFilterProps &
IFilterValueProps<Movie> & {
Expand Down Expand Up @@ -70,12 +88,7 @@ const _MovieSelect: React.FC<
return !exclude.includes(movie.id.toString());
});

return sortByRelevance(
input,
ret,
(m) => m.name,
(m) => (m.aliases ? [m.aliases] : [])
).map((movie) => ({
return movieSelectSort(input, ret).map((movie) => ({
value: movie.id,
object: movie,
}));
Expand Down
29 changes: 24 additions & 5 deletions ui/v2.5/src/components/Performers/PerformerSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { useCompare } from "src/hooks/state";
import { Link } from "react-router-dom";
import { sortByRelevance } from "src/utils/query";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";

export type SelectObject = {
id: string;
Expand All @@ -41,6 +41,27 @@ export type Performer = Pick<
>;
type Option = SelectOption<Performer>;

type FindPerformersResult = Awaited<
ReturnType<typeof queryFindPerformersForSelect>
>["data"]["findPerformers"]["performers"];

function sortPerformersByRelevance(
input: string,
performers: FindPerformersResult
) {
return sortByRelevance(
input,
performers,
(p) => p.name,
(p) => p.alias_list
);
}

const performerSelectSort = PatchFunction(
"PerformerSelect.sort",
sortPerformersByRelevance
);

const _PerformerSelect: React.FC<
IFilterProps & IFilterValueProps<Performer>
> = (props) => {
Expand All @@ -61,11 +82,9 @@ const _PerformerSelect: React.FC<
filter.sortBy = "name";
filter.sortDirection = GQL.SortDirectionEnum.Asc;
const query = await queryFindPerformersForSelect(filter);
return sortByRelevance(
return performerSelectSort(
input,
query.data.findPerformers.performers,
(p) => p.name,
(p) => p.alias_list
query.data.findPerformers.performers.slice()
).map((performer) => ({
value: performer.id,
object: performer,
Expand Down
21 changes: 17 additions & 4 deletions ui/v2.5/src/components/Scenes/SceneSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { useCompare } from "src/hooks/state";
import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query";
import { objectTitle } from "src/core/files";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";
import {
Criterion,
CriterionValue,
Expand All @@ -48,6 +48,21 @@ type ExtraSceneProps = {
extraCriteria?: Array<Criterion<CriterionValue>>;
};

type FindScenesResult = Awaited<
ReturnType<typeof queryFindScenesForSelect>
>["data"]["findScenes"]["scenes"];

function sortScenesByRelevance(input: string, scenes: FindScenesResult) {
return sortByRelevance(input, scenes, objectTitle, (s) => {
return s.files.map((f) => f.path);
});
}

const sceneSelectSort = PatchFunction(
"SceneSelect.sort",
sortScenesByRelevance
);

const _SceneSelect: React.FC<
IFilterProps & IFilterValueProps<Scene> & ExtraSceneProps
> = (props) => {
Expand Down Expand Up @@ -77,9 +92,7 @@ const _SceneSelect: React.FC<
return !exclude.includes(scene.id.toString());
});

return sortByRelevance(input, ret, objectTitle, (s) => {
return s.files.map((f) => f.path);
}).map((scene) => ({
return sceneSelectSort(input, ret).map((scene) => ({
value: scene.id,
object: scene,
}));
Expand Down
27 changes: 20 additions & 7 deletions ui/v2.5/src/components/Studios/StudioSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { useCompare } from "src/hooks/state";
import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";

export type SelectObject = {
id: string;
Expand All @@ -38,6 +38,24 @@ export type SelectObject = {
export type Studio = Pick<GQL.Studio, "id" | "name" | "aliases" | "image_path">;
type Option = SelectOption<Studio>;

type FindStudiosResult = Awaited<
ReturnType<typeof queryFindStudiosForSelect>
>["data"]["findStudios"]["studios"];

function sortStudiosByRelevance(input: string, studios: FindStudiosResult) {
return sortByRelevance(
input,
studios,
(s) => s.name,
(s) => s.aliases
);
}

const studioSelectSort = PatchFunction(
"StudioSelect.sort",
sortStudiosByRelevance
);

const _StudioSelect: React.FC<
IFilterProps &
IFilterValueProps<Studio> & {
Expand Down Expand Up @@ -70,12 +88,7 @@ const _StudioSelect: React.FC<
return !exclude.includes(studio.id.toString());
});

return sortByRelevance(
input,
ret,
(s) => s.name,
(s) => s.aliases
).map((studio) => ({
return studioSelectSort(input, ret).map((studio) => ({
value: studio.id,
object: studio,
}));
Expand Down
24 changes: 17 additions & 7 deletions ui/v2.5/src/components/Tags/TagSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { useCompare } from "src/hooks/state";
import { TagPopover } from "./TagPopover";
import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query";
import { PatchComponent } from "src/patch";
import { PatchComponent, PatchFunction } from "src/patch";

export type SelectObject = {
id: string;
Expand All @@ -39,6 +39,21 @@ export type SelectObject = {
export type Tag = Pick<GQL.Tag, "id" | "name" | "aliases" | "image_path">;
type Option = SelectOption<Tag>;

type FindTagsResult = Awaited<
ReturnType<typeof queryFindTagsForSelect>
>["data"]["findTags"]["tags"];

function sortTagsByRelevance(input: string, tags: FindTagsResult) {
return sortByRelevance(
input,
tags,
(t) => t.name,
(t) => t.aliases
);
}

const tagSelectSort = PatchFunction("TagSelect.sort", sortTagsByRelevance);

const _TagSelect: React.FC<
IFilterProps &
IFilterValueProps<Tag> & {
Expand Down Expand Up @@ -71,12 +86,7 @@ const _TagSelect: React.FC<
return !exclude.includes(tag.id.toString());
});

return sortByRelevance(
input,
ret,
(t) => t.name,
(t) => t.aliases
).map((tag) => ({
return tagSelectSort(input, ret).map((tag) => ({
value: tag.id,
object: tag,
}));
Expand Down
34 changes: 33 additions & 1 deletion ui/v2.5/src/docs/en/Manual/UIPluginApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,39 @@ Registers an after function. An after function is called after the render functi

Returns `void`.

#### `PluginApi.Event`
#### Patchable components and functions

- `CountrySelect`
- `DateInput`
- `FolderSelect`
- `GalleryIDSelect`
- `GallerySelect`
- `GallerySelect.sort`
- `Icon`
- `MovieIDSelect`
- `MovieSelect`
- `MovieSelect.sort`
- `PerformerIDSelect`
- `PerformerSelect`
- `PerformerSelect.sort`
- `PluginRoutes`
- `SceneCard`
- `SceneCard.Details`
- `SceneCard.Image`
- `SceneCard.Overlays`
- `SceneCard.Popovers`
- `SceneIDSelect`
- `SceneSelect`
- `SceneSelect.sort`
- `Setting`
- `StudioIDSelect`
- `StudioSelect`
- `StudioSelect.sort`
- `TagIDSelect`
- `TagSelect`
- `TagSelect.sort`

### `PluginApi.Event`

Allows plugins to listen for Stash's events.

Expand Down
7 changes: 5 additions & 2 deletions ui/v2.5/src/patch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ export function after(component: string, fn: Function) {
afterFns[component].push(fn);
}

export function RegisterComponent(component: string, fn: Function) {
export function RegisterComponent<T extends Function>(
component: string,
fn: T
) {
// register with the plugin api
if (components[component]) {
throw new Error("Component " + component + " has already been registered");
Expand All @@ -49,7 +52,7 @@ export function RegisterComponent(component: string, fn: Function) {
}

// patches a function to implement the before/instead/after functionality
export function PatchFunction(name: string, fn: Function) {
export function PatchFunction<T extends Function>(name: string, fn: T) {
return new Proxy(fn, {
apply(target, ctx, args) {
let result;
Expand Down

0 comments on commit 540e80c

Please sign in to comment.