Skip to content

Commit

Permalink
Movie card visual consistency (#1758)
Browse files Browse the repository at this point in the history
* Support getting scenes on movies in the API

* Make movie card visually consistent with scene etc

* Add date
* Add synopsis
* Show scene count with hover listing the scenes
* Move scene index to button

* Move scene number to own section

Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
  • Loading branch information
gitgiggety and WithoutPants authored Sep 26, 2021
1 parent 5fdab99 commit 1d04b55
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 16 deletions.
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

0 comments on commit 1d04b55

Please sign in to comment.