Grégoire Delattre 4b26080193
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Update redux state management
Use immer with native javascript objects instead of immutablejs.
2020-04-07 18:22:26 +02:00

107 lines
2.6 KiB
JavaScript

import React, { useEffect, useCallback, useRef } from "react";
import PropTypes from "prop-types";
export const KeyboardNavigation = ({
onKeyEnter,
selectPoster,
children,
list,
selected,
}) => {
const containerRef = useRef(null);
useEffect(() => {
document.onkeypress = move;
return () => {
document.onkeypress = null;
};
}, [move, list, selected]);
const move = useCallback(
(event) => {
// Only run the function if nothing else if actively focused
if (document.activeElement.tagName.toLowerCase() !== "body") {
return;
}
// Compute the grid dimentions
if (containerRef === null) {
return;
}
const containerWidth = containerRef.current.getBoundingClientRect().width;
const posterContainer = containerRef.current.getElementsByClassName(
"img-thumbnail"
);
let posterWidth = 0;
if (posterContainer !== null && posterContainer.item(0) !== null) {
const poster = posterContainer.item(0);
posterWidth =
poster.getBoundingClientRect().width +
poster.getBoundingClientRect().left;
}
let postersPerRow =
posterWidth >= containerWidth
? 1
: Math.floor(containerWidth / posterWidth);
let diff = 0;
switch (event.key) {
case "Enter":
onKeyEnter(selected);
return;
case "l":
diff = 1;
break;
case "h":
diff = -1;
break;
case "k":
diff = -1 * postersPerRow;
break;
case "j":
diff = postersPerRow;
break;
default:
return;
}
// Get the index of the currently selected item
const idx = list.findIndex((e) => e.imdbId === selected);
var newIdx = idx + diff;
// Handle edge cases
if (newIdx > list.length - 1) {
newIdx = list.length - 1;
} else if (newIdx < 0) {
newIdx = 0;
}
// Get the imdbID of the newly selected item
var selectedImdb = list[newIdx].imdbId;
// Select the movie
selectPoster(selectedImdb);
containerRef.current
.getElementsByClassName("img-thumbnail")
.item(newIdx)
.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "nearest",
});
},
[list, onKeyEnter, selectPoster, selected]
);
return <div ref={containerRef}>{children}</div>;
};
KeyboardNavigation.propTypes = {
list: PropTypes.array,
selected: PropTypes.string,
onKeyEnter: PropTypes.func,
selectPoster: PropTypes.func,
children: PropTypes.object,
};