mirror of
https://github.com/stashapp/stash.git
synced 2025-12-15 04:44:28 +01:00
Recommendations page bug fixes and refactoring (#2578)
* Changed Most Active Studios to Latest Studios * dynamically create view all link and created message for view all * created shared determineSlidesToScroll method * removed added code in Shared/index.ts * renamed getSlickSettings to getSlickSliderSettings * Updated row headers to follow plex naming convention * removed extra s in Sceness * updated row header css to better align header text with view all anchor
This commit is contained in:
parent
31cb8e2cbd
commit
dce4591911
9 changed files with 360 additions and 197 deletions
|
|
@ -0,0 +1,37 @@
|
|||
import React, { FunctionComponent } from "react";
|
||||
import { FindGalleriesQueryResult } from "src/core/generated-graphql";
|
||||
import Slider from "react-slick";
|
||||
import { GalleryCard } from "./GalleryCard";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import { getSlickSliderSettings } from "src/core/recommendations";
|
||||
|
||||
interface IProps {
|
||||
isTouch: boolean;
|
||||
filter: ListFilterModel;
|
||||
result: FindGalleriesQueryResult;
|
||||
header: String;
|
||||
linkText: String;
|
||||
}
|
||||
|
||||
export const GalleryRecommendationRow: FunctionComponent<IProps> = (
|
||||
props: IProps
|
||||
) => {
|
||||
const cardCount = props.result.data?.findGalleries.count;
|
||||
return (
|
||||
<div className="recommendation-row gallery-recommendations">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{props.header}</h2>
|
||||
</div>
|
||||
<a href={`/galleries?${props.filter.makeQueryParameters()}`}>
|
||||
{props.linkText}
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...getSlickSliderSettings(cardCount!, props.isTouch)}>
|
||||
{props.result.data?.findGalleries.galleries.map((gallery) => (
|
||||
<GalleryCard key={gallery.id} gallery={gallery} zoomIndex={1} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
37
ui/v2.5/src/components/Movies/MovieRecommendationRow.tsx
Normal file
37
ui/v2.5/src/components/Movies/MovieRecommendationRow.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import React, { FunctionComponent } from "react";
|
||||
import { FindMoviesQueryResult } from "src/core/generated-graphql";
|
||||
import Slider from "react-slick";
|
||||
import { MovieCard } from "./MovieCard";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import { getSlickSliderSettings } from "src/core/recommendations";
|
||||
|
||||
interface IProps {
|
||||
isTouch: boolean;
|
||||
filter: ListFilterModel;
|
||||
result: FindMoviesQueryResult;
|
||||
header: String;
|
||||
linkText: String;
|
||||
}
|
||||
|
||||
export const MovieRecommendationRow: FunctionComponent<IProps> = (
|
||||
props: IProps
|
||||
) => {
|
||||
const cardCount = props.result.data?.findMovies.count;
|
||||
return (
|
||||
<div className="recommendation-row movie-recommendations">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{props.header}</h2>
|
||||
</div>
|
||||
<a href={`/movies?${props.filter.makeQueryParameters()}`}>
|
||||
{props.linkText}
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...getSlickSliderSettings(cardCount!, props.isTouch)}>
|
||||
{props.result.data?.findMovies.movies.map((p) => (
|
||||
<MovieCard key={p.id} movie={p} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import React, { FunctionComponent } from "react";
|
||||
import { FindPerformersQueryResult } from "src/core/generated-graphql";
|
||||
import Slider from "react-slick";
|
||||
import { PerformerCard } from "./PerformerCard";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import { getSlickSliderSettings } from "src/core/recommendations";
|
||||
|
||||
interface IProps {
|
||||
isTouch: boolean;
|
||||
filter: ListFilterModel;
|
||||
result: FindPerformersQueryResult;
|
||||
header: String;
|
||||
linkText: String;
|
||||
}
|
||||
|
||||
export const PerformerRecommendationRow: FunctionComponent<IProps> = (
|
||||
props: IProps
|
||||
) => {
|
||||
const cardCount = props.result.data?.findPerformers.count;
|
||||
return (
|
||||
<div className="recommendation-row performer-recommendations">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{props.header}</h2>
|
||||
</div>
|
||||
<a href={`/performers?${props.filter.makeQueryParameters()}`}>
|
||||
{props.linkText}
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...getSlickSliderSettings(cardCount!, props.isTouch)}>
|
||||
{props.result.data?.findPerformers.performers.map((p) => (
|
||||
<PerformerCard key={p.id} performer={p} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -8,14 +8,14 @@ import {
|
|||
useFindGalleries,
|
||||
useFindPerformers,
|
||||
} from "src/core/StashService";
|
||||
import { SceneCard } from "src/components/Scenes/SceneCard";
|
||||
import { StudioCard } from "src/components/Studios/StudioCard";
|
||||
import { MovieCard } from "src/components/Movies/MovieCard";
|
||||
import { PerformerCard } from "src/components/Performers/PerformerCard";
|
||||
import { GalleryCard } from "src/components/Galleries/GalleryCard";
|
||||
import { SceneRecommendationRow } from "src/components/Scenes/SceneRecommendationRow";
|
||||
import { StudioRecommendationRow } from "src/components/Studios/StudioRecommendationRow";
|
||||
import { MovieRecommendationRow } from "src/components/Movies/MovieRecommendationRow";
|
||||
import { PerformerRecommendationRow } from "src/components/Performers/PerformerRecommendationRow";
|
||||
import { GalleryRecommendationRow } from "src/components/Galleries/GalleryRecommendationRow";
|
||||
import { SceneQueue } from "src/models/sceneQueue";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import Slider from "react-slick";
|
||||
import { LoadingIndicator } from "src/components/Shared";
|
||||
|
||||
const Recommendations: React.FC = () => {
|
||||
function isTouchEnabled() {
|
||||
|
|
@ -31,50 +31,35 @@ const Recommendations: React.FC = () => {
|
|||
scenefilter.sortDirection = GQL.SortDirectionEnum.Desc;
|
||||
scenefilter.itemsPerPage = itemsPerPage;
|
||||
const sceneResult = useFindScenes(scenefilter);
|
||||
const hasScenes =
|
||||
sceneResult.data &&
|
||||
sceneResult.data.findScenes &&
|
||||
sceneResult.data.findScenes.count > 0;
|
||||
const hasScenes = !!sceneResult?.data?.findScenes?.count;
|
||||
|
||||
const studiofilter = new ListFilterModel(GQL.FilterMode.Studios);
|
||||
studiofilter.sortBy = "scenes_count";
|
||||
studiofilter.sortBy = "created_at";
|
||||
studiofilter.sortDirection = GQL.SortDirectionEnum.Desc;
|
||||
studiofilter.itemsPerPage = itemsPerPage;
|
||||
const studioResult = useFindStudios(studiofilter);
|
||||
const hasStudios =
|
||||
studioResult.data &&
|
||||
studioResult.data.findStudios &&
|
||||
studioResult.data.findStudios.count > 0;
|
||||
const hasStudios = !!studioResult?.data?.findStudios?.count;
|
||||
|
||||
const moviefilter = new ListFilterModel(GQL.FilterMode.Movies);
|
||||
moviefilter.sortBy = "date";
|
||||
moviefilter.sortDirection = GQL.SortDirectionEnum.Desc;
|
||||
moviefilter.itemsPerPage = itemsPerPage;
|
||||
const movieResult = useFindMovies(moviefilter);
|
||||
const hasMovies =
|
||||
movieResult.data &&
|
||||
movieResult.data.findMovies &&
|
||||
movieResult.data.findMovies.count > 0;
|
||||
const hasMovies = !!movieResult?.data?.findMovies?.count;
|
||||
|
||||
const performerfilter = new ListFilterModel(GQL.FilterMode.Performers);
|
||||
performerfilter.sortBy = "created_at";
|
||||
performerfilter.sortDirection = GQL.SortDirectionEnum.Desc;
|
||||
performerfilter.itemsPerPage = itemsPerPage;
|
||||
const performerResult = useFindPerformers(performerfilter);
|
||||
const hasPerformers =
|
||||
performerResult.data &&
|
||||
performerResult.data.findPerformers &&
|
||||
performerResult.data.findPerformers.count > 0;
|
||||
const hasPerformers = !!performerResult?.data?.findPerformers?.count;
|
||||
|
||||
const galleryfilter = new ListFilterModel(GQL.FilterMode.Galleries);
|
||||
galleryfilter.sortBy = "date";
|
||||
galleryfilter.sortDirection = GQL.SortDirectionEnum.Desc;
|
||||
galleryfilter.itemsPerPage = itemsPerPage;
|
||||
const galleryResult = useFindGalleries(galleryfilter);
|
||||
const hasGalleries =
|
||||
galleryResult.data &&
|
||||
galleryResult.data.findGalleries &&
|
||||
galleryResult.data.findGalleries.count > 0;
|
||||
const hasGalleries = !!galleryResult?.data?.findGalleries?.count;
|
||||
|
||||
const messages = defineMessages({
|
||||
emptyServer: {
|
||||
|
|
@ -82,182 +67,108 @@ const Recommendations: React.FC = () => {
|
|||
defaultMessage:
|
||||
"Add some scenes to your server to view recommendations on this page.",
|
||||
},
|
||||
latestScenes: {
|
||||
id: "latest_scenes",
|
||||
defaultMessage: "Latest Scenes",
|
||||
recentlyAddedStudios: {
|
||||
id: "recently_added_studios",
|
||||
defaultMessage: "Recently Added Studios",
|
||||
},
|
||||
mostActiveStudios: {
|
||||
id: "most_active_studios",
|
||||
defaultMessage: "Most Active Studios",
|
||||
recentlyAddedPerformers: {
|
||||
id: "recently_added_performers",
|
||||
defaultMessage: "Recently Added Performers",
|
||||
},
|
||||
latestMovies: {
|
||||
id: "latest_movies",
|
||||
defaultMessage: "Latest Movies",
|
||||
recentlyReleasedGalleries: {
|
||||
id: "recently_released_galleries",
|
||||
defaultMessage: "Recently Released Galleries",
|
||||
},
|
||||
latestPerformers: {
|
||||
id: "latest_performers",
|
||||
defaultMessage: "Latest Performers",
|
||||
recentlyReleasedMovies: {
|
||||
id: "recently_released_movies",
|
||||
defaultMessage: "Recently Released Movies",
|
||||
},
|
||||
latestGalleries: {
|
||||
id: "latest_galleries",
|
||||
defaultMessage: "Latest Galleries",
|
||||
recentlyReleasedScenes: {
|
||||
id: "recently_released_scenes",
|
||||
defaultMessage: "Recently Released Scenes",
|
||||
},
|
||||
viewAll: {
|
||||
id: "view_all",
|
||||
defaultMessage: "View All",
|
||||
},
|
||||
});
|
||||
|
||||
var settings = {
|
||||
dots: !isTouch,
|
||||
arrows: !isTouch,
|
||||
infinite: !isTouch,
|
||||
speed: 300,
|
||||
variableWidth: true,
|
||||
swipeToSlide: true,
|
||||
slidesToShow: 5,
|
||||
slidesToScroll: !isTouch ? 5 : 1,
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1909,
|
||||
settings: {
|
||||
slidesToShow: 4,
|
||||
slidesToScroll: !isTouch ? 4 : 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1542,
|
||||
settings: {
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: !isTouch ? 3 : 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1170,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
slidesToScroll: !isTouch ? 2 : 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 801,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1,
|
||||
dots: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
const queue = SceneQueue.fromListFilterModel(scenefilter);
|
||||
if (
|
||||
sceneResult.loading ||
|
||||
studioResult.loading ||
|
||||
movieResult.loading ||
|
||||
performerResult.loading ||
|
||||
galleryResult.loading
|
||||
) {
|
||||
return <LoadingIndicator />;
|
||||
} else {
|
||||
return (
|
||||
<div className="recommendations-container">
|
||||
{!hasScenes &&
|
||||
!hasStudios &&
|
||||
!hasMovies &&
|
||||
!hasPerformers &&
|
||||
!hasGalleries ? (
|
||||
<div className="no-recommendations">
|
||||
{intl.formatMessage(messages.emptyServer)}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
{hasScenes && (
|
||||
<SceneRecommendationRow
|
||||
isTouch={isTouch}
|
||||
filter={scenefilter}
|
||||
result={sceneResult}
|
||||
queue={SceneQueue.fromListFilterModel(scenefilter)}
|
||||
header={intl.formatMessage(messages.recentlyReleasedScenes)}
|
||||
linkText={intl.formatMessage(messages.viewAll)}
|
||||
/>
|
||||
)}
|
||||
|
||||
return (
|
||||
<div className="recommendations-container">
|
||||
{!hasScenes &&
|
||||
!hasStudios &&
|
||||
!hasMovies &&
|
||||
!hasPerformers &&
|
||||
!hasGalleries ? (
|
||||
<div className="no-recommendations">
|
||||
{intl.formatMessage(messages.emptyServer)}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
{hasScenes && (
|
||||
<div className="recommendation-row">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{intl.formatMessage(messages.latestScenes)}</h2>
|
||||
</div>
|
||||
<a href="/scenes?sortby=date&sortdir=desc">View all</a>
|
||||
</div>
|
||||
<Slider {...settings}>
|
||||
{sceneResult.data?.findScenes.scenes.map((scene, index) => (
|
||||
<SceneCard
|
||||
key={scene.id}
|
||||
scene={scene}
|
||||
queue={queue}
|
||||
index={index}
|
||||
zoomIndex={1}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
)}
|
||||
{hasStudios && (
|
||||
<StudioRecommendationRow
|
||||
isTouch={isTouch}
|
||||
filter={studiofilter}
|
||||
result={studioResult}
|
||||
header={intl.formatMessage(messages.recentlyAddedStudios)}
|
||||
linkText={intl.formatMessage(messages.viewAll)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasStudios && (
|
||||
<div className="recommendation-row">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{intl.formatMessage(messages.mostActiveStudios)}</h2>
|
||||
</div>
|
||||
<a href="/studios?sortby=scenes_count&sortdir=desc">View all</a>
|
||||
</div>
|
||||
<Slider {...settings}>
|
||||
{studioResult.data?.findStudios.studios.map((studio) => (
|
||||
<StudioCard
|
||||
key={studio.id}
|
||||
studio={studio}
|
||||
hideParent={true}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
)}
|
||||
{hasMovies && (
|
||||
<MovieRecommendationRow
|
||||
isTouch={isTouch}
|
||||
filter={moviefilter}
|
||||
result={movieResult}
|
||||
header={intl.formatMessage(messages.recentlyReleasedMovies)}
|
||||
linkText={intl.formatMessage(messages.viewAll)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasMovies && (
|
||||
<div className="recommendation-row">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{intl.formatMessage(messages.latestMovies)}</h2>
|
||||
</div>
|
||||
<a href="/movies?sortby=date&sortdir=desc">View all</a>
|
||||
</div>
|
||||
<Slider {...settings}>
|
||||
{movieResult.data?.findMovies.movies.map((p) => (
|
||||
<MovieCard key={p.id} movie={p} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
)}
|
||||
{hasPerformers && (
|
||||
<PerformerRecommendationRow
|
||||
isTouch={isTouch}
|
||||
filter={performerfilter}
|
||||
result={performerResult}
|
||||
header={intl.formatMessage(messages.recentlyAddedPerformers)}
|
||||
linkText={intl.formatMessage(messages.viewAll)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasPerformers && (
|
||||
<div className="recommendation-row">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{intl.formatMessage(messages.latestPerformers)}</h2>
|
||||
</div>
|
||||
<a href="/performers?sortby=created_at&sortdir=desc">
|
||||
View all
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...settings}>
|
||||
{performerResult.data?.findPerformers.performers.map((p) => (
|
||||
<PerformerCard key={p.id} performer={p} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasGalleries && (
|
||||
<div className="recommendation-row">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{intl.formatMessage(messages.latestGalleries)}</h2>
|
||||
</div>
|
||||
<a href="/galleries?sortby=date&sortdir=desc">View all</a>
|
||||
</div>
|
||||
<Slider {...settings}>
|
||||
{galleryResult.data?.findGalleries.galleries.map((gallery) => (
|
||||
<GalleryCard
|
||||
key={gallery.id}
|
||||
gallery={gallery}
|
||||
zoomIndex={1}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
{hasGalleries && (
|
||||
<GalleryRecommendationRow
|
||||
isTouch={isTouch}
|
||||
filter={galleryfilter}
|
||||
result={galleryResult}
|
||||
header={intl.formatMessage(messages.recentlyReleasedGalleries)}
|
||||
linkText={intl.formatMessage(messages.viewAll)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Recommendations;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
display: inline-flex;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0;
|
||||
text-transform: uppercase;
|
||||
white-space: normal;
|
||||
}
|
||||
|
|
|
|||
45
ui/v2.5/src/components/Scenes/SceneRecommendationRow.tsx
Normal file
45
ui/v2.5/src/components/Scenes/SceneRecommendationRow.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import React, { FunctionComponent } from "react";
|
||||
import { FindScenesQueryResult } from "src/core/generated-graphql";
|
||||
import Slider from "react-slick";
|
||||
import { SceneCard } from "./SceneCard";
|
||||
import { SceneQueue } from "src/models/sceneQueue";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import { getSlickSliderSettings } from "src/core/recommendations";
|
||||
|
||||
interface IProps {
|
||||
isTouch: boolean;
|
||||
filter: ListFilterModel;
|
||||
result: FindScenesQueryResult;
|
||||
queue: SceneQueue;
|
||||
header: String;
|
||||
linkText: String;
|
||||
}
|
||||
|
||||
export const SceneRecommendationRow: FunctionComponent<IProps> = (
|
||||
props: IProps
|
||||
) => {
|
||||
const cardCount = props.result.data?.findScenes.count;
|
||||
return (
|
||||
<div className="recommendation-row scene-recommendations">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{props.header}</h2>
|
||||
</div>
|
||||
<a href={`/scenes?${props.filter.makeQueryParameters()}`}>
|
||||
{props.linkText}
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...getSlickSliderSettings(cardCount!, props.isTouch)}>
|
||||
{props.result.data?.findScenes.scenes.map((scene, index) => (
|
||||
<SceneCard
|
||||
key={scene.id}
|
||||
scene={scene}
|
||||
queue={props.queue}
|
||||
index={index}
|
||||
zoomIndex={1}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
37
ui/v2.5/src/components/Studios/StudioRecommendationRow.tsx
Normal file
37
ui/v2.5/src/components/Studios/StudioRecommendationRow.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import React, { FunctionComponent } from "react";
|
||||
import { FindStudiosQueryResult } from "src/core/generated-graphql";
|
||||
import Slider from "react-slick";
|
||||
import { StudioCard } from "./StudioCard";
|
||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||
import { getSlickSliderSettings } from "src/core/recommendations";
|
||||
|
||||
interface IProps {
|
||||
isTouch: boolean;
|
||||
filter: ListFilterModel;
|
||||
result: FindStudiosQueryResult;
|
||||
header: String;
|
||||
linkText: String;
|
||||
}
|
||||
|
||||
export const StudioRecommendationRow: FunctionComponent<IProps> = (
|
||||
props: IProps
|
||||
) => {
|
||||
const cardCount = props.result.data?.findStudios.count;
|
||||
return (
|
||||
<div className="recommendation-row studio-recommendations">
|
||||
<div className="recommendation-row-head">
|
||||
<div>
|
||||
<h2>{props.header}</h2>
|
||||
</div>
|
||||
<a href={`/studios?${props.filter.makeQueryParameters()}`}>
|
||||
{props.linkText}
|
||||
</a>
|
||||
</div>
|
||||
<Slider {...getSlickSliderSettings(cardCount!, props.isTouch)}>
|
||||
{props.result.data?.findStudios.studios.map((studio) => (
|
||||
<StudioCard key={studio.id} studio={studio} hideParent={true} />
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
57
ui/v2.5/src/core/recommendations.ts
Normal file
57
ui/v2.5/src/core/recommendations.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
function determineSlidesToScroll(
|
||||
cardCount: number,
|
||||
prefered: number,
|
||||
isTouch: boolean
|
||||
) {
|
||||
if (isTouch) {
|
||||
return 1;
|
||||
} else if (cardCount! > prefered) {
|
||||
return prefered;
|
||||
} else {
|
||||
return cardCount;
|
||||
}
|
||||
}
|
||||
|
||||
export function getSlickSliderSettings(cardCount: number, isTouch: boolean) {
|
||||
return {
|
||||
dots: !isTouch,
|
||||
arrows: !isTouch,
|
||||
infinite: !isTouch,
|
||||
speed: 300,
|
||||
variableWidth: true,
|
||||
swipeToSlide: true,
|
||||
slidesToShow: cardCount! > 5 ? 5 : cardCount,
|
||||
slidesToScroll: determineSlidesToScroll(cardCount!, 5, isTouch),
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 1909,
|
||||
settings: {
|
||||
slidesToShow: cardCount! > 4 ? 4 : cardCount,
|
||||
slidesToScroll: determineSlidesToScroll(cardCount!, 4, isTouch),
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1542,
|
||||
settings: {
|
||||
slidesToShow: cardCount! > 3 ? 3 : cardCount,
|
||||
slidesToScroll: determineSlidesToScroll(cardCount!, 3, isTouch),
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 1170,
|
||||
settings: {
|
||||
slidesToShow: cardCount! > 2 ? 2 : cardCount,
|
||||
slidesToScroll: determineSlidesToScroll(cardCount!, 2, isTouch),
|
||||
},
|
||||
},
|
||||
{
|
||||
breakpoint: 801,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1,
|
||||
dots: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
@ -769,10 +769,6 @@
|
|||
"interactive": "Interactive",
|
||||
"interactive_speed": "Interactive speed",
|
||||
"isMissing": "Is Missing",
|
||||
"latest_galleries": "Latest Galleries",
|
||||
"latest_movies": "Latest Movies",
|
||||
"latest_performers": "Latest Performers",
|
||||
"latest_scenes": "Latest Scenes",
|
||||
"library": "Library",
|
||||
"loading": {
|
||||
"generic": "Loading…"
|
||||
|
|
@ -796,7 +792,6 @@
|
|||
},
|
||||
"megabits_per_second": "{value} megabits per second",
|
||||
"metadata": "Metadata",
|
||||
"most_active_studios": "Most Active Studios",
|
||||
"movie": "Movie",
|
||||
"movie_scene_number": "Movie Scene Number",
|
||||
"movies": "Movies",
|
||||
|
|
@ -830,6 +825,11 @@
|
|||
"queue": "Queue",
|
||||
"random": "Random",
|
||||
"rating": "Rating",
|
||||
"recently_added_performers": "Recently Added Performers",
|
||||
"recently_added_studios": "Recently Added Studios",
|
||||
"recently_released_galleries": "Recently Released Galleries",
|
||||
"recently_released_movies": "Recently Released Movies",
|
||||
"recently_released_scenes": "Recently Released Scenes",
|
||||
"resolution": "Resolution",
|
||||
"scene": "Scene",
|
||||
"sceneTagger": "Scene Tagger",
|
||||
|
|
@ -969,6 +969,7 @@
|
|||
"updated_at": "Updated At",
|
||||
"url": "URL",
|
||||
"videos": "Videos",
|
||||
"view_all": "View All",
|
||||
"weight": "Weight",
|
||||
"years_old": "years old",
|
||||
"stashbox": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue