import React from 'react'; import { HashRouter as Router, Switch, Route, useParams } from "react-router-dom"; import Random from './rand'; import './App.css'; type Config = { sleepTimeSeconds: number; showUI: boolean; } let CONFIG: Config; if (process.env.NODE_ENV === 'production') { CONFIG = { sleepTimeSeconds: 5 * 60, showUI: false, } } else { CONFIG = { sleepTimeSeconds: 10, showUI: true, } } const IMAGE_CHUNK = 256; const roundup = (v: number, mod: number) => { let r = v % mod; if (r === 0) { return v; } else { return v + (mod - r); } }; /** * Shuffles array in place. ES6 version * From https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array * @param {Array} a items An array containing the items. */ function shuffle(a: Array) { let rng = new Random(new Date().getDay()); for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(rng.nextFloat() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } type MediaMetadata = { width: number; height: number; }; type MediaItem = { id: string; mediaMetadata: MediaMetadata; filename: string; }; type AlbumProps = { album: string; showUI: boolean; sleepTimeSeconds: number; }; type AlbumState = { error: any; mediaItems: Array | null; idx: number; showUI: boolean; timerID: any | null; }; class Album extends React.Component { state: AlbumState = { error: null, mediaItems: null, idx: 0, showUI: this.props.showUI, timerID: null, }; componentDidMount() { this.loadAlbum() } loadAlbum() { let {album} = this.props; fetch(process.env.PUBLIC_URL + `/api/album/${album}`) .then(res => res.json()) .then( (result) => { this.setState({mediaItems: result}); let {sleepTimeSeconds} = this.props; let timerID = setInterval(()=>{ let {idx} = this.state; this.setState({idx: idx+1}) console.log('timer fired'); }, sleepTimeSeconds*1000); this.setState({timerID}); }, (error) => this.setState({error}), ); } componentWillUnmount() { let {timerID} = this.state; clearInterval(timerID); } nextPhoto() { } render() { // TODO(wathiede): fade transition. // TODO(wathiede): pair-up portrait orientation images. let w = window.innerWidth * window.devicePixelRatio; let h = window.innerHeight * window.devicePixelRatio; let ratio = w/h; if (ratio > 1) { // Landscape image w = roundup(w, IMAGE_CHUNK); h = Math.round(w/ratio); } else { // Portrait image h = roundup(h, IMAGE_CHUNK); w = Math.round(h/ratio); } console.log(`Window size ${window.innerWidth}x${window.innerHeight} with a devicePixelRatio of ${window.devicePixelRatio} for a total size of ${w}x${h}`); //let w = roundup(window.innerWidth*window.devicePixelRatio, IMAGE_CHUNK); //let h = roundup(window.innerHeight*window.devicePixelRatio, IMAGE_CHUNK); let {idx, error, mediaItems, showUI} = this.state; if (error !== null) { return

Error: {JSON.stringify(error)}

; } else if (mediaItems !== null) { let landscapes = mediaItems.filter((mi) => { let md = mi.mediaMetadata; let ratio = md.width/md.height; return ratio > 1; }); let portraits = mediaItems.filter((mi) => { let md = mi.mediaMetadata; let ratio = md.width/md.height; return ratio <= 1; }); console.log(`${landscapes.length} landscape photos`); console.log(`${portraits.length} portraits photos`); let photos; if (ratio > 1) { console.log('display in landscape mode'); photos = landscapes; } else { console.log('display in portrait mode'); photos = portraits; } photos = shuffle(photos); let numImages = photos.length; idx = idx % numImages; let nextIdx = (idx+1)%numImages; let prevIdx = (numImages+idx-1)%numImages; let image = photos[idx]; let nextImage = photos[nextIdx]; let prevImage = photos[prevIdx]; let style: React.CSSProperties = { height: '100%', width: '100%', backgroundColor: 'black', backgroundImage: `url(/api/image/${image.id}?w=${w}&h=${h})`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center center', backgroundSize: 'cover', }; let prefetchStyle: React.CSSProperties = { backgroundColor: 'rgba(127, 127, 127, 0.5)', backgroundPosition: 'center center', backgroundRepeat: 'no-repeat', backgroundSize: 'cover', bottom: 0, height: '25%', position: 'absolute', width: '25%', }; let leftPrefetchStyle: React.CSSProperties = { left: 0, backgroundImage: `url(/api/image/${prevImage.id}?w=${w}&h=${h})`, ...prefetchStyle }; let rightPrefetchStyle: React.CSSProperties = { right: 0, backgroundImage: `url(/api/image/${nextImage.id}?w=${w}&h=${h})`, ...prefetchStyle }; let ui; if (showUI) { ui =
{ e.stopPropagation(); this.setState({idx: prevIdx}) }}>
{image.filename}
{ e.stopPropagation(); this.setState({idx: nextIdx}) }}>
; } return
{ e.stopPropagation(); this.setState({showUI: !showUI}) }}> { ui }
; } else { return

Loading...

; } } } type AlbumIndexProps = { }; type AlbumIndexState = { error: any | null, albums: Array | null, }; class AlbumIndex extends React.Component { state: AlbumIndexState = { error: null, albums: null, } componentDidMount() { fetch(process.env.PUBLIC_URL + "/api/albums") .then(res => res.json()) .then( (result) => this.setState({albums: result}), (error) => this.setState({error}), ); } render() { let {error, albums} = this.state; if (error !== null) { return

Error: {JSON.stringify(error)}

; } else if (albums !== null) { return albums.map((a) => { let img = unset; if (a.coverPhotoMediaItemId !== undefined) { img = { } let figure =
{img}
{ a.title || "No title" } - { a.mediaItemsCount || 0 } photos
; return { figure } }); } else { return

Loading...

; } } } type AlbumRouteProps = { sleepTimeSeconds: number, showUI: boolean }; const AlbumRoute = ({sleepTimeSeconds, showUI}: AlbumRouteProps) => { // We can use the `useParams` hook here to access // the dynamic pieces of the URL. let { albumId } = useParams(); albumId = albumId || ''; return ; } const App = () => { let {showUI, sleepTimeSeconds} = CONFIG; return
} export default App;