mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
Show gallery cover on the edit panel (#5935)
This commit is contained in:
parent
724d438721
commit
c9ca40152f
5 changed files with 60 additions and 11 deletions
|
|
@ -9,12 +9,14 @@ import (
|
|||
type GalleryURLBuilder struct {
|
||||
BaseURL string
|
||||
GalleryID string
|
||||
UpdatedAt string
|
||||
}
|
||||
|
||||
func NewGalleryURLBuilder(baseURL string, gallery *models.Gallery) GalleryURLBuilder {
|
||||
return GalleryURLBuilder{
|
||||
BaseURL: baseURL,
|
||||
GalleryID: strconv.Itoa(gallery.ID),
|
||||
UpdatedAt: strconv.FormatInt(gallery.UpdatedAt.Unix(), 10),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -23,5 +25,5 @@ func (b GalleryURLBuilder) GetPreviewURL() string {
|
|||
}
|
||||
|
||||
func (b GalleryURLBuilder) GetCoverURL() string {
|
||||
return b.BaseURL + "/gallery/" + b.GalleryID + "/cover"
|
||||
return b.BaseURL + "/gallery/" + b.GalleryID + "/cover?t=" + b.UpdatedAt
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,6 +162,21 @@ export const GalleryEditPanel: React.FC<IProps> = ({
|
|||
);
|
||||
}, [scrapers]);
|
||||
|
||||
const cover = useMemo(() => {
|
||||
if (gallery?.paths?.cover) {
|
||||
return (
|
||||
<div className="gallery-cover">
|
||||
<img
|
||||
src={gallery.paths.cover}
|
||||
alt={intl.formatMessage({ id: "cover_image" })}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div></div>;
|
||||
}, [gallery?.paths?.cover, intl]);
|
||||
|
||||
async function onSave(input: InputValues) {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
|
|
@ -463,6 +478,12 @@ export const GalleryEditPanel: React.FC<IProps> = ({
|
|||
</Col>
|
||||
<Col lg={5} xl={12}>
|
||||
{renderDetailsField()}
|
||||
<Form.Group controlId="cover_image">
|
||||
<Form.Label>
|
||||
<FormattedMessage id="cover_image" />
|
||||
</Form.Label>
|
||||
{cover}
|
||||
</Form.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -206,6 +206,21 @@ $galleryTabWidth: 450px;
|
|||
}
|
||||
}
|
||||
|
||||
.gallery-cover {
|
||||
aspect-ratio: 4 / 3;
|
||||
display: block;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.gallery-cover img {
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
object-fit: contain;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
div.GalleryWall {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
|
|
@ -1613,17 +1613,30 @@ export const mutateAddGalleryImages = (input: GQL.GalleryAddInput) =>
|
|||
},
|
||||
});
|
||||
|
||||
function evictCover(cache: ApolloCache<GQL.Gallery>, gallery_id: string) {
|
||||
const fields: Pick<Modifiers<GQL.Gallery>, "paths" | "cover"> = {};
|
||||
fields.paths = (paths) => {
|
||||
if (!("cover" in paths)) {
|
||||
return paths;
|
||||
}
|
||||
const coverUrl = new URL(paths.cover);
|
||||
coverUrl.search = "?t=" + Math.floor(Date.now() / 1000);
|
||||
return { ...paths, cover: coverUrl.toString() };
|
||||
};
|
||||
fields.cover = (_value, { DELETE }) => DELETE;
|
||||
cache.modify({
|
||||
id: cache.identify({ __typename: "Gallery", id: gallery_id }),
|
||||
fields,
|
||||
});
|
||||
}
|
||||
|
||||
export const mutateSetGalleryCover = (input: GQL.GallerySetCoverInput) =>
|
||||
client.mutate<GQL.SetGalleryCoverMutation>({
|
||||
mutation: GQL.SetGalleryCoverDocument,
|
||||
variables: input,
|
||||
update(cache, result) {
|
||||
if (!result.data?.setGalleryCover) return;
|
||||
|
||||
cache.evict({
|
||||
id: cache.identify({ __typename: "Gallery", id: input.gallery_id }),
|
||||
fieldName: "cover",
|
||||
});
|
||||
evictCover(cache, input.gallery_id);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -1633,11 +1646,7 @@ export const mutateResetGalleryCover = (input: GQL.GalleryResetCoverInput) =>
|
|||
variables: input,
|
||||
update(cache, result) {
|
||||
if (!result.data?.resetGalleryCover) return;
|
||||
|
||||
cache.evict({
|
||||
id: cache.identify({ __typename: "Gallery", id: input.gallery_id }),
|
||||
fieldName: "cover",
|
||||
});
|
||||
evictCover(cache, input.gallery_id);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ For best results, images in zip file should be stored without compression (copy,
|
|||
|
||||
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.
|
||||
|
||||
You can also manually select any image from a gallery as its cover. On the gallery details page, select the desired cover image, and then select **Set as Cover** in the ⋯ menu.
|
||||
|
||||
## 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:
|
||||
|
|
|
|||
Loading…
Reference in a new issue