Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Movie card visual consistency #1758

Merged
merged 5 commits into from
Sep 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion graphql/documents/data/movie-slim.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ fragment SlimMovieData on Movie {
id
name
front_image_path
}
}
6 changes: 6 additions & 0 deletions graphql/documents/data/movie.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@ fragment MovieData on Movie {
front_image_path
back_image_path
scene_count

scenes {
id
title
path
}
}
3 changes: 2 additions & 1 deletion graphql/schema/types/movie.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Movie {
front_image_path: String # Resolver
back_image_path: String # Resolver
scene_count: Int # Resolver
scenes: [Scene!]!
}

input MovieCreateInput {
Expand Down Expand Up @@ -60,4 +61,4 @@ input MovieDestroyInput {
type FindMoviesResultType {
count: Int!
movies: [Movie!]!
}
}
12 changes: 12 additions & 0 deletions pkg/api/resolver_model_movie.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,18 @@ func (r *movieResolver) SceneCount(ctx context.Context, obj *models.Movie) (ret
return &res, err
}

func (r *movieResolver) Scenes(ctx context.Context, obj *models.Movie) (ret []*models.Scene, err error) {
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
var err error
ret, err = repo.Scene().FindByMovieID(obj.ID)
return err
}); err != nil {
return nil, err
}

return ret, nil
}

func (r *movieResolver) CreatedAt(ctx context.Context, obj *models.Movie) (*time.Time, error) {
return &obj.CreatedAt.Timestamp, nil
}
Expand Down
1 change: 1 addition & 0 deletions ui/v2.5/src/components/Changelog/versions/v0100.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* Support filtering Movies by Performers. ([#1675](https://github.com/stashapp/stash/pull/1675))

### 🎨 Improvements
* Added date and details to Movie card, and move scene count to icon. ([#1758](https://github.com/stashapp/stash/pull/1758))
* Added date and details to Gallery card, and move image count to icon. ([#1763](https://github.com/stashapp/stash/pull/1763))
* Optimised image thumbnail generation (optionally using `libvips`) and made optional. ([#1655](https://github.com/stashapp/stash/pull/1655))
* Added missing image table indexes, resulting in a significant performance improvement. ([#1740](https://github.com/stashapp/stash/pull/1740))
Expand Down
70 changes: 56 additions & 14 deletions ui/v2.5/src/components/Movies/MovieCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React, { FunctionComponent } from "react";
import { FormattedPlural } from "react-intl";
import { Button, ButtonGroup } from "react-bootstrap";
import * as GQL from "src/core/generated-graphql";
import { GridCard } from "src/components/Shared";
import {
GridCard,
HoverPopover,
Icon,
TagLink,
TruncatedText,
} from "src/components/Shared";
import { FormattedMessage } from "react-intl";
import { RatingBanner } from "../Shared/RatingBanner";

interface IProps {
Expand All @@ -14,20 +21,47 @@ interface IProps {

export const MovieCard: FunctionComponent<IProps> = (props: IProps) => {
function maybeRenderSceneNumber() {
if (!props.sceneIndex) {
return (
<span>
{props.movie.scene_count}&nbsp;
<FormattedPlural
value={props.movie.scene_count ?? 0}
one="scene"
other="scenes"
/>
if (!props.sceneIndex) return;

return (
<>
<hr />
<span className="movie-scene-number">
<FormattedMessage id="scene" /> #{props.sceneIndex}
</span>
</>
);
}

function maybeRenderScenesPopoverButton() {
if (props.movie.scenes.length === 0) return;

const popoverContent = props.movie.scenes.map((scene) => (
<TagLink key={scene.id} scene={scene} />
));

return (
<HoverPopover placement="bottom" content={popoverContent}>
<Button className="minimal">
<Icon icon="play-circle" />
<span>{props.movie.scenes.length}</span>
</Button>
</HoverPopover>
);
}

function maybeRenderPopoverButtonGroup() {
if (props.sceneIndex || props.movie.scenes.length > 0) {
return (
<>
{maybeRenderSceneNumber()}
<hr />
<ButtonGroup className="card-popovers">
{maybeRenderScenesPopoverButton()}
</ButtonGroup>
</>
);
}

return <span>Scene number: {props.sceneIndex}</span>;
}

return (
Expand All @@ -46,10 +80,18 @@ export const MovieCard: FunctionComponent<IProps> = (props: IProps) => {
<RatingBanner rating={props.movie.rating} />
</>
}
details={maybeRenderSceneNumber()}
details={
<>
<span>{props.movie.date}</span>
<p>
<TruncatedText text={props.movie.synopsis} lineCount={3} />
</p>
</>
}
selected={props.selected}
selecting={props.selecting}
onSelectedChanged={props.onSelectedChanged}
popovers={maybeRenderPopoverButtonGroup()}
/>
);
};
4 changes: 4 additions & 0 deletions ui/v2.5/src/components/Movies/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
object-fit: contain;
width: 100%;
}

.movie-scene-number {
text-align: center;
}
}

.movie-images {
Expand Down