From 683f306193520e8cdf4534bbce8d8d8f95db8ed2 Mon Sep 17 00:00:00 2001 From: Sander Vocke Date: Fri, 14 Feb 2020 17:39:50 +0100 Subject: [PATCH] Simple image viewing with custom code. --- src/context/modal_gallery_context.js | 3 + src/gallery/gallery.js | 82 ++++++++++++++++++++++++++++ src/gridgallery.js | 64 +++++++++------------- src/lib/modal.js | 37 +++++++++++++ src/main.js | 47 ++++++++++++---- src/queries.js | 8 --- 6 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 src/context/modal_gallery_context.js create mode 100644 src/gallery/gallery.js create mode 100644 src/lib/modal.js diff --git a/src/context/modal_gallery_context.js b/src/context/modal_gallery_context.js new file mode 100644 index 0000000..c1e9ea1 --- /dev/null +++ b/src/context/modal_gallery_context.js @@ -0,0 +1,3 @@ +import { createContext } from 'react'; + +export const g_modal_gallery_context = createContext([{}, () => { }]); \ No newline at end of file diff --git a/src/gallery/gallery.js b/src/gallery/gallery.js new file mode 100644 index 0000000..f1f564a --- /dev/null +++ b/src/gallery/gallery.js @@ -0,0 +1,82 @@ +import React, { useState, useEffect } from 'react'; +import Box from '@material-ui/core/Box'; + +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles(theme => ({ + background: { + width: "100%", + height: "100%", + overflow: "auto", + position: "absolute", + "background-color": "rgba(0,0,0,1)", + 'overflow': 'hidden', + }, + image_container: { + 'width': '100%', + 'height': '100%', + 'overflow': 'hidden', + }, + image: { + 'object-fit': 'contain', + 'width': '100%', + 'height': '100%', + 'overflow': 'hidden', + }, +})); + +export function GalleryImageRender(props) { + const { src } = props; + const classes = useStyles(); + + return ( + + ); +} + +export function GalleryImage(props) { + const { photo } = props; + + // First show the fast (thumbnail) image. + const [src, setSrc] = useState(photo.state.thumbnailpath); + + // Start a fetch of the full image, then show that. + useEffect(() => { + console.log("Fetching..."); + fetch(photo.state.path) + .then(() => { + console.log("Fetch done. setting image."); + setSrc(photo.state.path); + }) + }, []); + + return ( + + ); +} + +export function Gallery(props) { + const { onClose, items, current_item } = props; + const classes = useStyles(); + + var maybe_photo = false; + if (items && items.length > 0 && current_item < items.length) { + maybe_photo = items[current_item]; + } + + return ( + <> + + + { + maybe_photo && + + } + + + + ); +} \ No newline at end of file diff --git a/src/gridgallery.js b/src/gridgallery.js index 265dacb..bc699db 100644 --- a/src/gridgallery.js +++ b/src/gridgallery.js @@ -1,8 +1,10 @@ -import React from 'react'; +import React, { useContext } from 'react'; import Box from '@material-ui/core/Box'; import { makeStyles } from '@material-ui/core/styles'; +import { g_modal_gallery_context } from './context/modal_gallery_context.js'; + const useStyles = makeStyles(theme => ({ gallery: { width: "100%", @@ -12,6 +14,7 @@ const useStyles = makeStyles(theme => ({ }, imgitem: { width: "100%", + cursor: 'pointer', } })); @@ -35,9 +38,8 @@ export function GridGalleryItem(props) { } export function PhotoItem(props) { - const { photo, row_height } = props; + const { photo, row_height, onClick } = props; const classes = useStyles(); - const photo_width = (photo.state.fullsize[0] / photo.state.fullsize[1]) * row_height; return ( @@ -45,7 +47,7 @@ export function PhotoItem(props) { width={photo_width} height={row_height} > - + ); } @@ -66,43 +68,27 @@ export function ItemGridGallery(props) { export function GridGallery(props) { const { photos } = props; - return ( - - {photos.map(photo => { - return - })} - - ); -} - - + const [modalGalleryState, setModalGalleryState] = useContext(g_modal_gallery_context); -/* - -const useStyles = makeStyles(theme => ({ - root: { - width: "100%", - }, -})); + var _ = require('lodash'); -const photo_to_gallery_photo = (photo) => { - if (!photo.state.fullsize) { - throw new Error("Photo for gallery does not have a size."); + const handleClick = (idx) => { + const state = _.cloneDeep(modalGalleryState); + state.active = true; + state.items = photos; + state.current_item = idx; + setModalGalleryState(state); } - return { - src: photo.state.path, - thumbnail: photo.state.thumbnailpath, - thumbnailWidth: photo.state.fullsize[0], - thumbnailHeight: photo.state.fullsize[1], - caption: photo.state.name, - } -} - -export function GridGallery(props) { - const classes = useStyles(); return ( - photo_to_gallery_photo(x))} /> - ) -} -*/ \ No newline at end of file + + {photos.map((photo, idx) => { + return {handleClick(idx);}} + /> + })} + + ); +} \ No newline at end of file diff --git a/src/lib/modal.js b/src/lib/modal.js new file mode 100644 index 0000000..a22ead8 --- /dev/null +++ b/src/lib/modal.js @@ -0,0 +1,37 @@ +import React, { useState, useEffect } from 'react' +import ReactDOM from 'react-dom' + +import { makeStyles } from '@material-ui/core/styles' + +const useStyles = makeStyles(theme => ({ + modal: { + position: "fixed", + top: '0px', + left: '0px', + width: '100%', + height: '100vh', + 'z-index': '1300', //Material UI "modal" value + }, +})); + +export function Modal(props) { + const { children, active } = props; + const [el, setEl] = useState(null); + const classes = useStyles(); + + useEffect(() => { + const new_el = document.createElement('div'); + new_el.className = classes.modal; + setEl(new_el); + document.getElementById('root').appendChild(new_el); + }, []); + + if(!el) { + return <>; + } + if(el) { + el.style.visibility = active ? 'visible' : 'hidden'; + } + return ReactDOM.createPortal(children, el); +} + diff --git a/src/main.js b/src/main.js index d01ebc5..b291b0f 100644 --- a/src/main.js +++ b/src/main.js @@ -12,6 +12,9 @@ import { UserQuery, user_query_from_search_string, maybe_image_query, do_image_q import { Browser } from './browser.js'; import { UserQueryWidget } from './userquerywidget.js'; import { ResultsView } from './resultsview.js'; +import { Modal } from './lib/modal.js'; +import { Gallery } from './gallery/gallery.js'; +import { g_modal_gallery_context } from './context/modal_gallery_context.js'; const useStyles = makeStyles(theme => ({ root: { @@ -46,6 +49,11 @@ export function LoadedMainPage(props) { const [allTags, setAllTags] = React.useState([]); const [albums, setAlbums] = React.useState([]); const [tags, setTags] = React.useState([]); + const [modalGalleryState, setModalGalleryState] = React.useState({ + active: false, + items: [], + current_item: 0, + }); const { database, photos_dir, thumbs_dir } = props; var _ = require('lodash'); @@ -110,7 +118,7 @@ export function LoadedMainPage(props) { function onNewQuery(q) { var do_update = !_.isEqual(q.filter, gallery_user_query.filter); setGalleryUserQuery(q); - if (do_update) { + if (do_update) { updatePhotos(q); updateAlbums(q); updateTags(q); @@ -122,18 +130,35 @@ export function LoadedMainPage(props) { onNewQuery(query); } + function handleGalleryClose() { + var state = _.cloneDeep(modalGalleryState); + state.active = false; + state.items = []; + state.current_item = 0; + setModalGalleryState(state); + } + return ( <> - - - {albums && } + + + + {albums && } + + + + + {photos && } + - - - - {photos && } - - + + + + ); } @@ -147,8 +172,8 @@ const theme = createMuiTheme({ }, }); - export function MainPage() { + // TODO: ProvideDB should be put in a context like the modal gallery is. return (