matrix-art

An image gallery for Matrix
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-art.git
Log | Files | Refs | README | LICENSE

commit a10d4a0b2a5fa9a7b010d3e1cd01791396c6cd6a
parent 2ef1799777eb6c7a4fe01419fec436daa7e05919
Author: MTRNord <mtrnord1@gmail.com>
Date:   Sun,  2 Jan 2022 00:06:21 +0100

Implement Basic gallery for images

Diffstat:
Mpackage-lock.json | 14++++++++++++++
Mpackage.json | 1+
Mpages/post/[id].tsx | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
3 files changed, 82 insertions(+), 25 deletions(-)

diff --git a/package-lock.json b/package-lock.json @@ -7,6 +7,7 @@ "name": "matrix-art", "dependencies": { "cors": "^2.8.5", + "lightgallery": "^2.3.0", "meilisearch": "^0.23.0", "next": "12.0.7", "node-localstorage": "^2.2.1", @@ -5975,6 +5976,14 @@ "node": ">= 0.8.0" } }, + "node_modules/lightgallery": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lightgallery/-/lightgallery-2.3.0.tgz", + "integrity": "sha512-kdu+uQM2X4LUN2G2tTp72ZOLfwmGwZFjiVQBqYY2E2zL1ADibKwnxZUBEw2zI5zefDe/71IHg+6kBRTbr8CGyg==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/lilconfig": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", @@ -12974,6 +12983,11 @@ "type-check": "~0.4.0" } }, + "lightgallery": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lightgallery/-/lightgallery-2.3.0.tgz", + "integrity": "sha512-kdu+uQM2X4LUN2G2tTp72ZOLfwmGwZFjiVQBqYY2E2zL1ADibKwnxZUBEw2zI5zefDe/71IHg+6kBRTbr8CGyg==" + }, "lilconfig": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", diff --git a/package.json b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "cors": "^2.8.5", + "lightgallery": "^2.3.0", "meilisearch": "^0.23.0", "next": "12.0.7", "node-localstorage": "^2.2.1", diff --git a/pages/post/[id].tsx b/pages/post/[id].tsx @@ -1,3 +1,8 @@ +import LightGallery from 'lightgallery/react'; +import 'lightgallery/css/lightgallery.css'; +import 'lightgallery/css/lg-zoom.css'; +import 'lightgallery/css/lg-thumbnail.css'; +import lgZoom from 'lightgallery/plugins/zoom'; import { GetServerSideProps, InferGetServerSidePropsType } from "next"; import Head from "next/head"; import { NextRouter, withRouter } from "next/router"; @@ -175,57 +180,94 @@ class Post extends Component<Props, State> { } } - renderSingleImageTags(image_event: ImageEvent): ReactNode { - const tags = image_event.content["matrixart.tags"].map((tag) => { - return <div className="mr-2 bg-slate-800 hover:bg-slate-600 p-2 rounded-sm cursor-default" key={(image_event as MatrixEventBase).event_id + "tags" + tag}>{tag}</div>; + renderSingleImageTags(imageEvent: ImageEvent): ReactNode { + const tags = imageEvent.content["matrixart.tags"].map((tag) => { + return <div className="mr-2 bg-slate-800 hover:bg-slate-600 p-2 rounded-sm cursor-default" key={(imageEvent as MatrixEventBase).event_id + "tags" + tag}>{tag}</div>; }); return ( - <div className="flex flex-row items-center text-gray-900 dark:text-gray-200 font-medium" key={(image_event as MatrixEventBase).event_id + "tags"}>{tags}</div> + <div className="flex flex-row items-center text-gray-900 dark:text-gray-200 font-medium" key={(imageEvent as MatrixEventBase).event_id + "tags"}>{tags}</div> ); } - renderImageGalleryTags(image_event: ImageGalleryEvent): ReactNode { - return <></>; + renderImageGalleryTags(imageEvent: ImageGalleryEvent): ReactNode { + const tags = imageEvent.content['m.image_gallery'].flatMap(image => { + return image['matrixart.tags'].map((tag) => { + return <div className="mr-2 bg-slate-800 hover:bg-slate-600 p-2 rounded-sm cursor-default" key={(imageEvent as MatrixEventBase).event_id + "tags" + tag}>{tag}</div>; + }); + }); + return ( + <div className="flex flex-row items-center text-gray-900 dark:text-gray-200 font-medium" key={(imageEvent as MatrixEventBase).event_id + "tags"}>{tags}</div> + ); } renderSingleImageEvent(imageEvent: ImageEvent, caption: string) { const url = this.context.client?.downloadLink(imageEvent.content["m.file"].url); + const thumbnail_url = this.context.client?.downloadLink(imageEvent.content['m.thumbnail'][0].url); - if (!url) { + if (!url || !thumbnail_url) { return <></>; } - return this.renderImage(imageEvent.event_id, - url, - caption, - imageEvent.content["m.file"].mimetype, - imageEvent.content["m.image"].width, - imageEvent.content["m.image"].height + return ( + <> + <Head> + <meta property="og:image" content={url} key="og-image" /> + <meta property="og:image:type" content={imageEvent.content["m.file"].mimetype} key="og-image-type" /> + <meta property="og:image:alt" content={caption} key="og-image-alt" /> + <meta property="og:image:width" content={imageEvent.content["m.image"].width.toString()} key="og-image-width" /> + <meta property="og:image:height" content={imageEvent.content["m.image"].height.toString()} key="og-image-height" /> + <meta name="twitter:image" content={url} key="og-twitter-image" /> + </Head> + <div className="flex justify-center p-10 bg-[#fefefe]/[.95] dark:bg-[#14181E]/[.95]"> + <LightGallery + plugins={[lgZoom]} + elementClassNames="shadow-2xl max-w-full lg:max-w-3xl max-h-[871px] shadow-black cursor-zoom-in" + key={imageEvent.event_id} + > + <a href={url} title={caption} data-src={url}> + <img alt={caption} title={caption} src={thumbnail_url} /> + </a> + </LightGallery> + </div> + </> ); } renderImageGalleryEvent(imageEvent: ImageGalleryEvent, caption: string) { - return <div></div>; - } - - // TODO make full size on click - renderImage(id: string, src: string, caption: string, mime: string, w: number, h: number) { - // TODO proper alt + const images = imageEvent.content['m.image_gallery'].map(image => { + const url = this.context.client?.downloadLink(image["m.file"].url); + const thumbnail_url = this.context.client?.downloadLink(image['m.thumbnail'][0].url); + if (!url || !thumbnail_url) { + return <></>; + } + return ( + <a href={url} title={caption} data-src={url}> + <img alt={caption} title={caption} src={thumbnail_url} /> + </a> + ); + }); return ( <> <Head> - <meta property="og:image" content={src} key="og-image" /> - <meta property="og:image:type" content={mime} key="og-image-type" /> + <meta property="og:image" content={imageEvent.content["m.image_gallery"][0]["m.file"].url} key="og-image" /> + <meta property="og:image:type" content={imageEvent.content["m.image_gallery"][0]["m.file"].mimetype} key="og-image-type" /> <meta property="og:image:alt" content={caption} key="og-image-alt" /> - <meta property="og:image:width" content={w.toString()} key="og-image-width" /> - <meta property="og:image:height" content={h.toString()} key="og-image-height" /> - <meta name="twitter:image" content={src} key="og-twitter-image" /> + <meta property="og:image:width" content={imageEvent.content["m.image_gallery"][0]["m.image"].width.toString()} key="og-image-width" /> + <meta property="og:image:height" content={imageEvent.content["m.image_gallery"][0]["m.image"].height.toString()} key="og-image-height" /> + <meta name="twitter:image" content={imageEvent.content["m.image_gallery"][0]["m.file"].url} key="og-twitter-image" /> </Head> <div className="flex justify-center p-10 bg-[#fefefe]/[.95] dark:bg-[#14181E]/[.95]"> - <img alt={caption} title={caption} className="shadow-2xl max-w-full lg:max-w-3xl max-h-[871px] shadow-black cursor-zoom-in" src={src} key={id}></img> + <LightGallery + plugins={[lgZoom]} + elementClassNames="shadow-2xl max-w-full lg:max-w-3xl max-h-[871px] shadow-black cursor-zoom-in" + key={imageEvent.event_id} + > + {images} + </LightGallery> </div> </> ); } + } Post.contextType = ClientContext;