);
};
+
+interface IImageWallPanelProps {
+ images: GQL.SlimImageDataFragment[];
+ clickHandler?: (e: MouseEvent, item: GQL.SlimImageDataFragment) => void;
+}
+
+export const ImageWallPanel: React.FC = ({
+ images,
+ clickHandler,
+}) => {
+ return ;
+};
+
+interface IMarkerWallPanelProps {
+ markers: GQL.SceneMarkerDataFragment[];
+ clickHandler?: (e: MouseEvent, item: GQL.SceneMarkerDataFragment) => void;
+}
+
+export const MarkerWallPanel: React.FC = ({
+ markers,
+ clickHandler,
+}) => {
+ return (
+
+ );
+};
+
+interface ISceneWallPanelProps {
+ scenes: GQL.SlimSceneDataFragment[];
+ sceneQueue?: SceneQueue;
+ clickHandler?: (e: MouseEvent, item: GQL.SlimSceneDataFragment) => void;
+}
+
+export const SceneWallPanel: React.FC = ({
+ scenes,
+ sceneQueue,
+ clickHandler,
+}) => {
+ return (
+
+ );
+};
diff --git a/ui/v2.5/src/core/StashService.ts b/ui/v2.5/src/core/StashService.ts
index 87295e0c1..7e79db3b1 100644
--- a/ui/v2.5/src/core/StashService.ts
+++ b/ui/v2.5/src/core/StashService.ts
@@ -6,6 +6,7 @@ import {
getOperationName,
} from "@apollo/client/utilities";
import { stringToGender } from "src/utils/gender";
+import { stringToCircumcised } from "src/utils/circumcised";
import { filterData } from "../utils/data";
import { ListFilterModel } from "../models/list-filter/filter";
import * as GQL from "./generated-graphql";
@@ -221,8 +222,10 @@ export const useFindGallery = (id: string) => {
const skip = id === "new";
return GQL.useFindGalleryQuery({ variables: { id }, skip });
};
-export const useFindScene = (id: string) =>
- GQL.useFindSceneQuery({ variables: { id } });
+export const useFindScene = (id: string) => {
+ const skip = id === "new";
+ return GQL.useFindSceneQuery({ variables: { id }, skip });
+};
export const useSceneStreams = (id: string) =>
GQL.useSceneStreamsQuery({ variables: { id } });
@@ -731,6 +734,7 @@ export const mutateAddGalleryImages = (input: GQL.GalleryAddInput) =>
mutation: GQL.AddGalleryImagesDocument,
variables: input,
update: deleteCache(galleryMutationImpactedQueries),
+ refetchQueries: getQueryNames([GQL.FindGalleryDocument]),
});
export const mutateRemoveGalleryImages = (input: GQL.GalleryRemoveInput) =>
@@ -738,6 +742,7 @@ export const mutateRemoveGalleryImages = (input: GQL.GalleryRemoveInput) =>
mutation: GQL.RemoveGalleryImagesDocument,
variables: input,
update: deleteCache(galleryMutationImpactedQueries),
+ refetchQueries: getQueryNames([GQL.FindGalleryDocument]),
});
export const mutateGallerySetPrimaryFile = (id: string, fileID: string) =>
@@ -1314,6 +1319,10 @@ export const makePerformerCreateInput = (toCreate: GQL.ScrapedPerformer) => {
death_date: toCreate.death_date,
hair_color: toCreate.hair_color,
weight: toCreate.weight ? Number(toCreate.weight) : undefined,
+ penis_length: toCreate.penis_length
+ ? Number(toCreate.penis_length)
+ : undefined,
+ circumcised: stringToCircumcised(toCreate.circumcised),
};
return input;
};
diff --git a/ui/v2.5/src/core/config.ts b/ui/v2.5/src/core/config.ts
index 024914c94..90e11742c 100644
--- a/ui/v2.5/src/core/config.ts
+++ b/ui/v2.5/src/core/config.ts
@@ -25,6 +25,9 @@ export interface ICustomFilter extends ITypename {
direction: SortDirectionEnum;
}
+// NOTE: This value cannot be more defined, because the generated enum it depends upon is UpperCase, which leads to errors on saving
+export type PinnedFilters = Record>;
+
export type FrontPageContent = ISavedFilterRow | ICustomFilter;
export const defaultMaxOptionsShown = 200;
@@ -55,6 +58,9 @@ export interface IUIConfig {
imageWallOptions?: ImageWallOptions;
lastNoteSeen?: number;
+
+ vrTag?: string;
+ pinnedFilters?: PinnedFilters;
}
function recentlyReleased(
diff --git a/ui/v2.5/src/core/createClient.ts b/ui/v2.5/src/core/createClient.ts
index 2fcdaf717..b6601a6cc 100644
--- a/ui/v2.5/src/core/createClient.ts
+++ b/ui/v2.5/src/core/createClient.ts
@@ -88,14 +88,15 @@ const typePolicies: TypePolicies = {
},
};
-export const getBaseURL = () => {
- const baseURL = window.STASH_BASE_URL;
- if (baseURL === "/%BASE_URL%/") return "/";
- return baseURL;
+const possibleTypes = {
+ VisualFile: ["VideoFile", "ImageFile"],
};
+export const baseURL =
+ document.querySelector("base")?.getAttribute("href") ?? "/";
+
export const getPlatformURL = (ws?: boolean) => {
- const platformUrl = new URL(window.location.origin + getBaseURL());
+ const platformUrl = new URL(window.location.origin + baseURL);
if (import.meta.env.DEV) {
platformUrl.port = import.meta.env.VITE_APP_PLATFORM_PORT ?? "9999";
@@ -139,10 +140,7 @@ export const createClient = () => {
// handle unauthorized error by redirecting to the login page
if (networkError && (networkError as ServerError).statusCode === 401) {
// redirect to login page
- const newURL = new URL(
- `${getBaseURL()}login`,
- window.location.toString()
- );
+ const newURL = new URL(`${baseURL}login`, window.location.toString());
newURL.searchParams.append("returnURL", window.location.href);
window.location.href = newURL.toString();
}
@@ -162,7 +160,10 @@ export const createClient = () => {
const link = from([errorLink, splitLink]);
- const cache = new InMemoryCache({ typePolicies });
+ const cache = new InMemoryCache({
+ typePolicies,
+ possibleTypes: possibleTypes,
+ });
const client = new ApolloClient({
link,
cache,
diff --git a/ui/v2.5/src/core/performers.ts b/ui/v2.5/src/core/performers.ts
index e13ac8885..597a0be54 100644
--- a/ui/v2.5/src/core/performers.ts
+++ b/ui/v2.5/src/core/performers.ts
@@ -22,21 +22,21 @@ export const usePerformerFilterHook = (
) {
// add the performer if not present
if (
- !performerCriterion.value.find((p) => {
+ !performerCriterion.value.items.find((p) => {
return p.id === performer.id;
})
) {
- performerCriterion.value.push(performerValue);
+ performerCriterion.value.items.push(performerValue);
}
} else {
// overwrite
- performerCriterion.value = [performerValue];
+ performerCriterion.value.items = [performerValue];
}
performerCriterion.modifier = GQL.CriterionModifier.IncludesAll;
} else {
performerCriterion = new PerformersCriterion();
- performerCriterion.value = [performerValue];
+ performerCriterion.value.items = [performerValue];
performerCriterion.modifier = GQL.CriterionModifier.IncludesAll;
filter.criteria.push(performerCriterion);
}
diff --git a/ui/v2.5/src/core/studios.ts b/ui/v2.5/src/core/studios.ts
index ef93f191c..95649c199 100644
--- a/ui/v2.5/src/core/studios.ts
+++ b/ui/v2.5/src/core/studios.ts
@@ -22,6 +22,7 @@ export const useStudioFilterHook = (studio: GQL.StudioDataFragment) => {
studioCriterion = new StudiosCriterion();
studioCriterion.value = {
items: [studioValue],
+ excluded: [],
depth: (config?.configuration?.ui as IUIConfig)?.showChildStudioContent
? -1
: 0,
diff --git a/ui/v2.5/src/core/tags.ts b/ui/v2.5/src/core/tags.ts
index 3ec042c84..d4f6fc1bf 100644
--- a/ui/v2.5/src/core/tags.ts
+++ b/ui/v2.5/src/core/tags.ts
@@ -42,6 +42,7 @@ export const useTagFilterHook = (tag: GQL.TagDataFragment) => {
tagCriterion = new TagsCriterion(TagsCriterionOption);
tagCriterion.value = {
items: [tagValue],
+ excluded: [],
depth: (config?.configuration?.ui as IUIConfig)?.showChildTagContent
? -1
: 0,
diff --git a/ui/v2.5/src/docs/en/Changelog/v0210.md b/ui/v2.5/src/docs/en/Changelog/v0210.md
new file mode 100644
index 000000000..51f3ba277
--- /dev/null
+++ b/ui/v2.5/src/docs/en/Changelog/v0210.md
@@ -0,0 +1,42 @@
+### ✨ New Features
+* Added VR button to the scene player when the scene tag includes a configurable tag. ([#3636](https://github.com/stashapp/stash/pull/3636))
+* Added ability to include and exclude performers, studios and tags in the same filter. ([#3619](https://github.com/stashapp/stash/pull/3619))
+* Added penis length and circumcision status for Performers. ([#3627](https://github.com/stashapp/stash/pull/3627))
+* Added text field to search criteria in the edit filter dialog. ([#3740](https://github.com/stashapp/stash/pull/3740))
+* Added ability to add (short) video files as images. ([#3583](https://github.com/stashapp/stash/pull/3583))
+* Added ability to force gallery creation by adding `.forcegallery` to directory. ([#3715](https://github.com/stashapp/stash/pull/3715))
+* Added ability to ignore gallery creation by adding `.nogallery` to directory. ([#3715](https://github.com/stashapp/stash/pull/3715))
+* Added Maximum Duration Difference option to the Duplicate Scene Checker. ([#3663](https://github.com/stashapp/stash/pull/3663))
+* Added ability to configure the default sort order for videos served by DLNA. ([#3645](https://github.com/stashapp/stash/pull/3645))
+* Support pinning filter criteria to the top of the edit filter page. ([#3675](https://github.com/stashapp/stash/pull/3675))
+* Added Appears With tab to Performer page showing other performers that appear in the same scenes. ([#3563](https://github.com/stashapp/stash/pull/3563))
+* Added derived Performer O-Counter field. ([#3588](https://github.com/stashapp/stash/pull/3588))
+* Added distance parameter to phash filter. ([#3596](https://github.com/stashapp/stash/pull/3596))
+
+### 🎨 Improvements
+* Gallery Updated At timestamp is now updated when its contents are changed. ([#3771](https://github.com/stashapp/stash/pull/3771))
+* Added male performer images that are consistent with the other performer images. ([#3770](https://github.com/stashapp/stash/pull/3770))
+* Improved the UX when navigating the edit filter dialog using keyboard. ([#3739](https://github.com/stashapp/stash/pull/3739))
+* Changed modifier selector to a set of clickable pills. ([#3598](https://github.com/stashapp/stash/pull/3598))
+* Movie covers can now be shown in the Lightbox when clicking on them. ([#3705](https://github.com/stashapp/stash/pull/3705))
+* Scrapers are now sorted by name in the Scraper UI. ([#3691](https://github.com/stashapp/stash/pull/3691))
+* Changed source selector menu to require click instead of mouseover. ([#3578](https://github.com/stashapp/stash/pull/3578))
+* Updated default studio icon to be consistent with other icons. ([#3577](https://github.com/stashapp/stash/pull/3577))
+* Make cards use up the full width of the screen on mobile. ([#3576](https://github.com/stashapp/stash/pull/3576))
+* Log errors when a graphql request fails. ([#3562](https://github.com/stashapp/stash/pull/3562))
+* Use case insensitive sorting for text based sorting. ([#3560](https://github.com/stashapp/stash/pull/3560))
+* Default date sorting in descending order. ([#3560](https://github.com/stashapp/stash/pull/3560))
+
+### 🐛 Bug fixes
+* Fixed captions not appearing on iOS devices. ([#3729](https://github.com/stashapp/stash/pull/3729))
+* Fixed folder selector appearing for name criterion. ([#3788](https://github.com/stashapp/stash/pull/3788))
+* Fixed generation of interactive heatmaps to match scene duration. ([#3758](https://github.com/stashapp/stash/pull/3758))
+* Fixed incorrect plugin hook being triggered during bulk performer update. ([#3754](https://github.com/stashapp/stash/pull/3754))
+* Fixed error when removing file over network on Windows. ([#3714](https://github.com/stashapp/stash/pull/3714))
+* Fixed scene cards being sized incorrectly on the front page. ([#3724](https://github.com/stashapp/stash/pull/3724))
+* Fixed hair colour not being populated during Batch Update Performers. ([#3718](https://github.com/stashapp/stash/pull/3718))
+* Fixed Create Missing checkbox not appearing in the Identify dialog. ([#3260](https://github.com/stashapp/stash/issues/3260))
+* Fixed override option not being honoured when generating scene covers. ([#3661](https://github.com/stashapp/stash/pull/3661))
+* Fixed error when creating a movie in the scrape scene dialog. ([#3633](https://github.com/stashapp/stash/pull/3633))
+* Fixed issues when scanning a renamed zip file. ([#3610](https://github.com/stashapp/stash/pull/3579))
+* Fixed incorrect Twitter/Instagram URLs sent to stash-box. ([#3579](https://github.com/stashapp/stash/pull/3579))
diff --git a/ui/v2.5/src/docs/en/Manual/AutoTagging.md b/ui/v2.5/src/docs/en/Manual/AutoTagging.md
index 4fba88ad0..ef9035e6c 100644
--- a/ui/v2.5/src/docs/en/Manual/AutoTagging.md
+++ b/ui/v2.5/src/docs/en/Manual/AutoTagging.md
@@ -2,7 +2,7 @@
This task matches your Performers, Studios, and Tags against your media, based on names only. It finds Scenes, Images, and Galleries where the path or filename contains the Performer/Studio/Tag.
-For each scene it finds that matches, it sets the applicable field. It will **only** tag based on performers, studios, and tags that already exist in your database. In order to completely identify and gather information about the scenes in your collection, you will need to use the Tagger view and/or Scraping tools.
+For each scene it finds that matches, it sets the applicable field. It will **only** tag based on performers, studios, and tags that already exist in your database.
When the Performer/Studio/Tag name has multiple words, the search will include paths/filenames where the Performer/Studio/Tag name is separated with `.`, `-` or `_` characters, as well as whitespace.
diff --git a/ui/v2.5/src/docs/en/Manual/Configuration.md b/ui/v2.5/src/docs/en/Manual/Configuration.md
index 99b00f219..ee5cd131a 100644
--- a/ui/v2.5/src/docs/en/Manual/Configuration.md
+++ b/ui/v2.5/src/docs/en/Manual/Configuration.md
@@ -36,6 +36,18 @@ exclude:
_a useful [link](https://regex101.com/) to experiment with regexps_
+## Gallery Creation from Folders
+
+In the Library section you can find an option to create a gallery from each folder containing images. This will be applied on all libraries when activated, including the base folder of a library.
+
+If you wish to apply this on a per folder basis, you can create a file called **.nogallery** or **.forcegallery** in a folder that should act different than this global setting.
+
+This will either exclude the folder from becoming a gallery even if the setting is set, or create a gallery from the folder even if the setting is not set.
+
+The file will only be recognized if written in lower case letters.
+
+Files with a dot in front are handled as hidden in the Linux OS and Mac OS, so you will not see those files after creation on your system without setting your file manager accordingly.
+
## Hashing algorithms
Stash identifies video files by calculating a hash of the file. There are two algorithms available for hashing: `oshash` and `MD5`. `MD5` requires reading the entire file, and can therefore be slow, particularly when reading files over a network. `oshash` (which uses OpenSubtitle's hashing algorithm) only reads 64k from each end of the file.
diff --git a/ui/v2.5/src/docs/en/Manual/Galleries.md b/ui/v2.5/src/docs/en/Manual/Galleries.md
deleted file mode 100644
index c31e2b1c4..000000000
--- a/ui/v2.5/src/docs/en/Manual/Galleries.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Galleries
-
-**Note:** images are now included during the scan process and are loaded independently of galleries. It is _no longer necessary_ to have images in zip files to be scanned into your library.
-
-Galleries are automatically created from zip files found during scanning that contain images. It is also possible to automatically create galleries from folders containing images, by selecting the "Create galleries from folders containing images" checkbox in the Configuration page. It is also possible to manually create galleries.
-
-For best results, images in zip file should be stored without compression (copy, store or no compression options depending on the software you use. Eg on linux: `zip -0 -r gallery.zip foldertozip/`). This impacts **heavily** on the zip read performance.
-
-If a filename of an image in the gallery zip file ends with `cover.jpg`, it will be treated like a cover and presented first in the gallery view page and as a gallery cover in the gallery list view. If more than one images match the name the first one found in natural sort order is selected.
-
-Images can be added to a gallery by navigating to the gallery's page, selecting the "Add" tab, querying for and selecting the images to add, then selecting "Add to Gallery" from the `...` menu button. Likewise, images may be removed from a gallery by selecting the "Images" tab, selecting the images to remove and selecting "Remove from Gallery" from the `...` menu button.
-
diff --git a/ui/v2.5/src/docs/en/Manual/Images.md b/ui/v2.5/src/docs/en/Manual/Images.md
new file mode 100644
index 000000000..7b384596b
--- /dev/null
+++ b/ui/v2.5/src/docs/en/Manual/Images.md
@@ -0,0 +1,27 @@
+# Images and Galleries
+
+Images are the parts which make up galleries, but you can also have them be scanned independently. To declare an image part of a gallery, there are four ways:
+
+1. Group them in a folder together and activate the **Create galleries from folders containing images** option in the library section of your settings. The gallery will get the name of the folder.
+2. Group them in a folder together and create a file in the folder called .forcegallery. The gallery will get the name of the folder.
+3. Group them into a zip archive together. The gallery will get the name of the archive.
+4. You can simply create a gallery in stash itself by clicking on **New** in the Galleries tab.
+
+You can add images to every gallery manually in the gallery detail page. Deleting can be done by selecting the according images in the same view and clicking on the minus next to the edit button.
+
+For best results, images in zip file should be stored without compression (copy, store or no compression options depending on the software you use. Eg on linux: `zip -0 -r gallery.zip foldertozip/`). This impacts **heavily** on the zip read performance.
+
+If a filename of an image in the gallery zip file ends with `cover.jpg`, it will be treated like a cover and presented first in the gallery view page and as a gallery cover in the gallery list view. If more than one images match the name the first one found in natural sort order is selected.
+
+## Image clips/gifs
+
+Images can also be clips/gifs. These are meant to be short video loops. Right now they are not possible in zipfiles. To declare video files to be images, there are two ways:
+
+1. Deactivate video scanning for all libraries that contain clips/gifs, but keep image scanning active. Set the **Scan Video Extensions as Image Clip** option in the library section of your settings.
+2. Make sure none of the file endings used by your clips/gifs are present in the **Video Extensions** and add them to the **Image Extensions** in the library section of your settings.
+
+A clip/gif will be a stillframe in the wall and grid view by default. To view the loop, you can go into the Lightbox Carousel (e.g. by clicking on an image in the wall view) or the image detail page.
+
+If you want the loop to be used as a preview on the wall and grid view, you will have to generate them.
+You can do this as you scan for the new clip file by activating **Generate previews for image clips** on the scan settings, or do it after by going to the **Generated Content** section in the task section of your settings, activating **Image Clip Previews** and clicking generate. This takes a while, as the files are transcoded.
+
diff --git a/ui/v2.5/src/docs/en/Manual/KeyboardShortcuts.md b/ui/v2.5/src/docs/en/Manual/KeyboardShortcuts.md
index 7eee67ef4..98c13cad0 100644
--- a/ui/v2.5/src/docs/en/Manual/KeyboardShortcuts.md
+++ b/ui/v2.5/src/docs/en/Manual/KeyboardShortcuts.md
@@ -24,7 +24,7 @@
| Keyboard sequence | Action |
|-------------------|--------|
-| `/` | Focus search field |
+| `/` | Focus search field / focus query field in filter dialog |
| `f` | Show Add Filter dialog |
| `r` | Reshuffle if sorted by random |
| `v g` | Set view to grid |
diff --git a/ui/v2.5/src/docs/en/Manual/Tasks.md b/ui/v2.5/src/docs/en/Manual/Tasks.md
index 6f30b5fcd..2856306ff 100644
--- a/ui/v2.5/src/docs/en/Manual/Tasks.md
+++ b/ui/v2.5/src/docs/en/Manual/Tasks.md
@@ -14,13 +14,13 @@ The scan task accepts the following options:
| Option | Description |
|--------|-------------|
+| Generate scene covers | Generates scene covers for video files. |
| Generate previews | Generates video previews which play when hovering over a scene. |
| Generate animated image previews | Generates animated webp previews. Only required if the Preview Type is set to Animated Image. Requires Generate previews to be enabled. |
-| Generate sprites | Generates sprites for the scene scrubber. |
+| Generate scrubber sprites | Generates sprites for the scene scrubber. |
| Generate perceptual hashes | Generates perceptual hashes for scene deduplication and identification. |
| Generate thumbnails for images | Generates thumbnails for image files. |
-| Don't include file extension in title | By default, scenes, images and galleries have their title created using the file basename. When the flag is enabled, the file extension is stripped when setting the title. |
-| Set name, date, details from embedded file metadata. | Parse the video file metadata (where supported) and set the scene attributes accordingly. It has previously been noted that this information is frequently incorrect, so only use this option where you are certain that the metadata is correct in the files. |
+| Generate previews for image clips | Generates a gif/looping video as thumbnail for image clips/gifs. |
# Auto Tagging
See the [Auto Tagging](/help/AutoTagging.md) page.
@@ -42,6 +42,7 @@ The generate task accepts the following options:
| Option | Description |
|--------|-------------|
+| Scene covers | Generates scene covers for video files. |
| Previews | Generates video previews which play when hovering over a scene. |
| Animated image previews | Generates animated webp previews. Only required if the Preview Type is set to Animated Image. Requires Generate previews to be enabled. |
| Scene Scrubber Sprites | Generates sprites for the scene scrubber. |
@@ -49,7 +50,9 @@ The generate task accepts the following options:
| Marker Animated Image Previews | Generates animated webp previews for markers. Only required if the Preview Type is set to Animated Image. Requires Markers to be enabled. |
| Marker Screenshots | Generates static JPG images for markers. Only required if Preview Type is set to Static Image. Requires Marker Previews to be enabled. |
| Transcodes | MP4 conversions of unsupported video formats. Allows direct streaming instead of live transcoding. |
-| Perceptual hashes | Generates perceptual hashes for scene deduplication and identification. |
+| Perceptual hashes (for deduplication) | Generates perceptual hashes for scene deduplication and identification. |
+| Generate heatmaps and speeds for interactive scenes | Generates heatmaps and speeds for interactive scenes. |
+| Image Clip Previews | Generates a gif/looping video as thumbnail for image clips/gifs. |
| Overwrite existing generated files | By default, where a generated file exists, it is not regenerated. When this flag is enabled, then the generated files are regenerated. |
## Transcodes
diff --git a/ui/v2.5/src/globals.d.ts b/ui/v2.5/src/globals.d.ts
index 3bd1b67fe..360388e5f 100644
--- a/ui/v2.5/src/globals.d.ts
+++ b/ui/v2.5/src/globals.d.ts
@@ -1,5 +1,3 @@
-// eslint-disable-next-line no-var
-declare var STASH_BASE_URL: string;
declare module "intersection-observer";
declare module "*.md" {
diff --git a/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx b/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx
index ca79805d7..cfe1d5db3 100644
--- a/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx
+++ b/ui/v2.5/src/hooks/Lightbox/Lightbox.tsx
@@ -47,6 +47,7 @@ import {
} from "@fortawesome/free-solid-svg-icons";
import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
import { useDebounce } from "../debounce";
+import { isVideo } from "src/utils/visualFile";
const CLASSNAME = "Lightbox";
const CLASSNAME_HEADER = `${CLASSNAME}-header`;
@@ -425,20 +426,25 @@ export const LightboxComponent: React.FC = ({
}
}
- const navItems = images.map((image, i) => (
-
+ React.createElement(image.paths.preview != "" ? "video" : "img", {
+ loop: image.paths.preview != "",
+ autoPlay: image.paths.preview != "",
+ src:
+ image.paths.preview != ""
+ ? image.paths.preview ?? ""
+ : image.paths.thumbnail ?? "",
+ alt: "",
+ className: cx(CLASSNAME_NAVIMAGE, {
[CLASSNAME_NAVSELECTED]: i === index,
- })}
- onClick={(e: React.MouseEvent) => selectIndex(e, i)}
- role="presentation"
- loading="lazy"
- key={image.paths.thumbnail}
- onLoad={imageLoaded}
- />
- ));
+ }),
+ onClick: (e: React.MouseEvent) => selectIndex(e, i),
+ role: "presentation",
+ loading: "lazy",
+ key: image.paths.thumbnail,
+ onLoad: imageLoaded,
+ })
+ );
const onDelayChange = (e: React.ChangeEvent) => {
let numberValue = Number.parseInt(e.currentTarget.value, 10);
@@ -466,7 +472,7 @@ export const LightboxComponent: React.FC = ({
function gotoPage(imageIndex: number) {
const indexInPage = (imageIndex - 1) % pageSize;
if (pageCallback) {
- let jumppage = Math.floor(imageIndex / pageSize) + 1;
+ let jumppage = Math.floor((imageIndex - 1) / pageSize) + 1;
if (page !== jumppage) {
pageCallback({ page: jumppage });
oldImages.current = images;
@@ -845,6 +851,7 @@ export const LightboxComponent: React.FC = ({
scrollAttemptsBeforeChange={scrollAttemptsBeforeChange}
setZoom={(v) => setZoom(v)}
resetPosition={resetPosition}
+ isVideo={isVideo(image.visual_files?.[0] ?? {})}
/>
) : undefined}