import * as React from "react"; import { graphql } from "gatsby"; import { GatsbyImage, getImage } from "gatsby-plugin-image"; import { Helmet } from "react-helmet"; import { take } from "ramda"; import classnames from "classnames"; import '../styles/index.css'; import { getHelmetSafeBodyStyle, getVibrant, getAspectRatio } from "../utils"; import Nav from "../components/index/Nav"; import ActionButtons from "../components/index/ActionButtons"; import { use100vh } from "react-div-100vh"; const env = process.env.GATSBY_ACTIVE_ENV || process.env.NODE_ENV || "development"; const getDifferentRand = (range, lastNs, iterations = 0) => { const n = Math.floor(Math.random() * range); if (lastNs.findIndex((x) => x === n) > -1 && iterations < 5) { console.log("got dupe, trying again", n); return getDifferentRand(range, lastNs, iterations + 1); } return n; }; const IndexPage = ({ data: { allFile: { nodes: images }, }, }) => { const [isClient, setIsClient] = React.useState(false); const [imageIndex, setImageIndex] = React.useState(0); const image = React.useMemo(() => { return images[imageIndex]; }, [images, imageIndex]); console.log(image); const shuffleImage = React.useCallback( (currentImage) => { const lastThreeImages = JSON.parse(localStorage.getItem("lastHeros")) || []; if (env === "production") { try { window.plausible("Shuffle", { props: { currentImage: currentImage?.base }, }); // eslint-disable-next-line _paq.push(["trackEvent", "Index", "Shuffle", currentImage?.base]); } catch (e) { /* do nothing */ } } const index = getDifferentRand(images.length, lastThreeImages); localStorage.setItem( "lastHeros", JSON.stringify(take(3, [index, ...lastThreeImages])) ); setImageIndex(index); }, [images.length] ); // pick random image on page hydration React.useEffect(() => { if (!isClient) { setIsClient(true); shuffleImage(image); } }, [isClient, imageIndex, image, shuffleImage]); React.useEffect(() => { const keyListener = (e) => { switch (e.code) { case "Space": { shuffleImage(image); return; } case "ArrowRight": { if (imageIndex === images.length - 1) { setImageIndex(0); return; } setImageIndex(imageIndex + 1); return; } case "ArrowLeft": { if (imageIndex === 0) { setImageIndex(images.length - 1); return; } setImageIndex(imageIndex - 1); return; } } }; document.addEventListener("keydown", keyListener); return () => { document.removeEventListener("keydown", keyListener); }; }, [imageIndex, images.length, image, shuffleImage]); const vibrant = getVibrant(image); const ar = getAspectRatio(image); const screenHeight = use100vh(); const imageIsLandscape = isClient ? ar > 1 : true; return ( <> <Helmet> <title>Chuck Dries</title> <body className={classnames(isClient ? "bg-muted-dark" : "bg-gray-800")} style={getHelmetSafeBodyStyle(vibrant, screenHeight)} /> </Helmet> <main className={classnames( "font-serif", imageIsLandscape ? "landscape:grid portrait:h-actual-screen portrait:flex flex-col justify-center" : "portrait:grid landscape:flex flex-row" )} > <div className={classnames( "landscape:flex-auto flex flex-col items-center justify-between", imageIsLandscape ? "portrait:items-center landscape:w-screen" : "landscape:justify-center portrait:w-screen" )} style={{ gridArea: "1/1" }} > <Nav imageIsLandscape={imageIsLandscape} isClient={isClient} /> <div className={classnames( "rounded-[50px] p-3 md:p-5 flex flex-col items-center z-10 border-r-[20px] border-b-[20px] mb-3 mx-2 md:mb-[-90px]", isClient ? "cool-border-big" : "bg-gray-50", !imageIsLandscape && "landscape:mr-4" // text is on left side of image, make some room for drop shadow )} > <h1 className={classnames( "mb-0 mt-0 text-center font-black z-20 text-7xl md:text-8xl lg:text-9xl" )} style={{ lineHeight: "85%" }} > Chuck Dries </h1> <h2 className={classnames( "p-3 text-center z-20 font-bold text-lg md:text-2xl lg:text-3xl" )} style={{ lineHeight: "110%" }} > Full Stack Software Engineer & Photographer </h2> </div> <div className={classnames( "mt-[100px]", imageIsLandscape ? "block portrait:hidden" : "block" )} > <ActionButtons image={image} isClient={isClient} shuffleImage={shuffleImage} /> </div> </div> {isClient ? ( <GatsbyImage alt="" className={classnames( imageIsLandscape ? "landscape:h-actual-screen portrait:h-two-thirds-vw" : "h-actual-screen portrait:w-full landscape:w-1/2" )} image={getImage(image)} loading="eager" style={{ gridArea: "1/1", }} /> ) : ( <div className="landscape:h-actual-screen portrait:h-two-thirds-vw w-full" style={{ gridArea: "1/1" }} ></div> )} {imageIsLandscape && ( <div className="hidden portrait:flex justify-center my-2"> <ActionButtons image={image} isClient={isClient} shuffleImage={shuffleImage} /> </div> )} </main> </> ); }; export const query = graphql` { allFile( filter: { sourceInstanceName: { eq: "gallery" } base: { in: [ "DSC06616.jpg" # B&W abstract ## KEEP ON TOP # "20160530-DSC09108.jpg" # portrait red flowers # # "DSC00201.jpg" # duck # "DSC04905.jpg" # purple layers "DSC05761.jpg" # monument valley "DSC05851.jpg" # utahn highway sunset # "DSC06245.jpg" # snowy milky way # # "DSC08521.jpg" # firepit bloom j&e # "DSC07490.jpg" # house on prairie # "DSC02538.jpg" # portrait pink cactus bloom # "20190624-DSC00771.jpg" # glacier forest fog # # "DSC00237.jpg" # cotton candy clouds "_DSC6062.jpg" # field of wildflowers # "_DSC6060.jpg" # edge of the world "_DSC6219.jpg" # whihte/yellow rosebush # "_DSC6243.jpg" # bright rose in darkness # "_DSC6400-2.jpg" # Horsetail falls # "_DSC6798.jpg" # Japanese zen garden # "_DSC6481.jpg" # Mt Hood from Powell Butte # "_DSC5916.jpg" # blue dart stinger # "_DSC0286.jpg" # god rays # "_DSC8998.jpg" # forest road # "DSC01169.jpg" # ferris wheel reflection "DSC01800.jpg" # cherry blossom landscape sunny sky "DSC01772.jpg" # cherry blossom portrait sunny sky # "DSC06201.jpg" # Wheatland snowy hills "DSC01924.jpg" # cherry blossom sea # "DSC03157.jpg" # constellation of flowers "DSC02610.jpg" # peter iredale portrait "DSC02615.jpg" # rori iredale beach field camera "DSC06490.jpg" # Japanese garden steps "DSC06687.jpg" # Multnomah Falls long exposure "DSC09932.jpg" # milky way "DSC09944.jpg" # milky way rori "DSC03725.jpg" # oregon coast lighthouse ] } } sort: { order: DESC, fields: fields___imageMeta___dateTaken } ) { nodes { relativePath base childImageSharp { fluid { aspectRatio } gatsbyImageData( layout: FULL_WIDTH placeholder: NONE breakpoints: [750, 1080, 1366, 1920, 2560, 3840] ) } fields { imageMeta { vibrant { ...VibrantColors } } } } } } `; export default IndexPage;