diff --git a/frontend/js/components/list/posters.js b/frontend/js/components/list/posters.js index 4e6fd11..fde81da 100644 --- a/frontend/js/components/list/posters.js +++ b/frontend/js/components/list/posters.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react" +import React, { useState, useEffect, useCallback } from "react" import PropTypes from "prop-types" import { OrderedMap, Map } from "immutable" import fuzzy from "fuzzy"; @@ -81,6 +81,99 @@ ListPosters.propTypes = { export default ListPosters; const Posters = (props) => { + const addMoreCount = 20; + const [size, setSize] = useState(0); + const [postersPerRow, setPostersPerRow] = useState(0); + const [posterHeight, setPosterHeight] = useState(0); + + const loadMore = () => { + if ((size === props.elmts.size)) { return } + + const newSize = (((size + addMoreCount) >= props.elmts.size) + ? props.elmts.size + : size + addMoreCount); + + setSize(newSize); + } + + useEffect(() => { + loadMore() + }, [props.elmts.size]); + + const move = (event) => { + // Only run the function if nothing else if actively focused + if (document.activeElement.tagName.toLowerCase() !== "body") { return } + + let diff = 0; + let moveFocus = 0; + switch (event.key) { + case "Enter": + props.onKeyEnter(props.selectedImdbId); + return; + case "l": + diff = 1; + break; + case "h": + diff = -1; + break; + case "k": + diff = -1*postersPerRow; + moveFocus = -1*posterHeight; + break; + case "j": + diff = postersPerRow; + moveFocus = posterHeight; + break; + default: + return; + } + + // Get the index of the currently selected item + const idx = props.elmts.keySeq().findIndex(k => k === props.selectedImdbId); + + var newIdx = idx + diff; + + // Handle edge cases + if (newIdx > props.elmts.size -1) { + newIdx = props.elmts.size -1; + } else if (newIdx < 0) { + newIdx = 0; + } + + // Get the imdbID of the newly selected item + var selectedImdb = Object.keys(props.elmts.toJS())[newIdx]; + + // Select the movie + props.selectPoster(selectedImdb); + if (moveFocus !== 0) { + window.scrollBy(0, moveFocus); + } + } + + const posterCount = useCallback(node => { + if (node === null) { return } + const parentWidth = node.getBoundingClientRect().width; + const childContainer = node.getElementsByClassName("img-thumbnail"); + let childWidth = 0; + let posterHeight = 0; + if ((childContainer !== null) && (childContainer.item(0) !== null)) { + const child = childContainer.item(0); + childWidth = child.getBoundingClientRect().width + child.getBoundingClientRect().left; + posterHeight = child.getBoundingClientRect().height; + } + + let numberPerRow = (childWidth >= parentWidth) ? 1 : Math.floor(parentWidth/childWidth); + setPostersPerRow(numberPerRow); + setPosterHeight(posterHeight); + }) + + useEffect(() => { + document.onkeypress = move; + return () => { + document.onkeypress = null; + } + }, [move]) + if (props.loading) { return (); } @@ -93,46 +186,31 @@ const Posters = (props) => { ); } - const addMoreCount = 20; - const [size, setSize] = useState(0); - useEffect(() => { - loadMore() - }, [props.elmts.size]); - const hasMore = () => (size !== props.elmts.size); - - const loadMore = () => { - if (!hasMore()) { return } - - const newSize = (((size + addMoreCount) >= props.elmts.size) - ? props.elmts.size - : size + addMoreCount); - - setSize(newSize); - } - return ( - } - > - {props.elmts.slice(0, size).toIndexedSeq().map(function(el, index) { - const imdbId = el.get("imdb_id"); - const selected = (imdbId === props.selectedImdbId) ? true : false; +
+ } + > + {props.elmts.slice(0, size).toIndexedSeq().map(function(el, index) { + const imdbId = el.get("imdb_id"); + const selected = (imdbId === props.selectedImdbId) ? true : false; - return ( - props.selectPoster(imdbId)} - onDoubleClick={() => props.onDoubleClick(imdbId)} - /> - ) - } ,this)} - + return ( + props.selectPoster(imdbId)} + onDoubleClick={() => props.onDoubleClick(imdbId)} + /> + ) + } ,this)} + +
); } Posters.propTypes = {