import { Layout } from '@components/common' import commerce from '@lib/api/commerce' import { GetStaticPathsContext, GetStaticPropsContext, InferGetStaticPropsType, } from 'next' import { Viewer } from 'photo-sphere-viewer' import { GyroscopePlugin } from 'photo-sphere-viewer/dist/plugins/gyroscope' import { MarkersPlugin } from 'photo-sphere-viewer/dist/plugins/markers' import { GalleryPlugin } from 'photo-sphere-viewer/dist/plugins/gallery' import 'photo-sphere-viewer/dist/plugins/markers.css' import 'photo-sphere-viewer/dist/plugins/gallery.css' import { StereoPlugin } from 'photo-sphere-viewer/dist/plugins/stereo' import { VirtualTourPlugin } from 'photo-sphere-viewer/dist/plugins/virtual-tour' import { VisibleRangePlugin } from 'photo-sphere-viewer/dist/plugins/visible-range' import { RefObject, useEffect, useRef, useState } from 'react' import { useRouter } from 'next/router' import RegionsDataJson from '../../../static_data/navBarMenuData.json' import MarkerCardModal from '@components/common/Room/MarkerCardModal/MarkerCardModal' import { useDisclosure } from '@chakra-ui/react' import decadesManifest from '../../../static_data/decadesManifest.json' import productDetailsMetafields from '../../../static_data/productDetailsMetafields.json' import { MarkerData, MarkerJson, } from '@components/common/Room/RoomTypes/RoomTypes' import { getNodes, getRecursiveMarkers } from 'workers/DecadeWorker' import screenfull from 'screenfull' import { Stream } from 'stream' export async function getStaticPaths({ locales }: GetStaticPathsContext) { const decadesPaths = RegionsDataJson.regions .filter((region) => region.enabled) .flatMap((region) => { let regionDecadesPath = new Array() for (let key in decadesManifest) { if (decadesManifest[key as keyof typeof decadesManifest].enabled) { Array.from(Array(7).keys()).forEach((nodeId: number) => regionDecadesPath.push(region.href + '/' + key + '/' + nodeId) ) } } return regionDecadesPath }) return { paths: locales ? locales.reduce((arr, locale) => { // Add a decade path for every locale decadesPaths.forEach((path: any) => { arr.push(`/${locale}${path}`) }) return arr }, []) : decadesPaths, fallback: 'blocking', } } export async function getStaticProps({ params, locale, locales, preview, }: GetStaticPropsContext<{ region: string; decade: string; start: string }>) { const config = { locale, locales } let products = new Array() let decadeManifest = ( await import( `../../../static_data/regions/${params?.region}/${params?.decade}/manifest.json` ) ).rooms let region = params?.region let decade = params?.decade let startNode = params?.start //sunrise sunset api to retreive Rome rise/set times const sunriseSunsetAPI = 'https://api.sunrise-sunset.org/json?lat=41.9027835&lng=12.4963655' const [sunriseTime, sunsetTime] = await fetch(sunriseSunsetAPI) .then((response) => { if (!response.ok) { throw Error(response.statusText) } return response.json() }) .then((data) => data.results) .then((data) => [ parseInt(data.sunrise.split(':')[0]), parseInt(data.sunset.split(':')[0]), ]) .catch((error) => [7, 7]) const time = new Date().getUTCHours() >= sunsetTime + 12 || new Date().getUTCHours() <= sunriseTime ? 'night' : 'day' for (const roomMeta of decadeManifest) { let roomMarkers try { roomMarkers = await import( `../../../static_data/regions/abruzzo/${decade}/${time}/${ roomMeta.filename.split('.')[0] }.json` ) } catch (e) { continue } for (const productMarker of roomMarkers.markers.filter( (marker: MarkerJson) => marker.markerType == 'product' )) { if ( products.find(({ product }) => product.slug?.includes(productMarker.markerSource) ) ) continue const productPromise = commerce.getProduct({ variables: { slug: productMarker.markerSource, withMetafields: [ { namespace: 'custom', key: 'nazionalit_' }, { namespace: 'custom', key: 'descrizione_tecnica' }, { namespace: 'custom', key: 'descrizione_storica' }, ], }, config, preview, }) products.push(await productPromise) } } if (!products) { throw new Error(`Products associated with markers not found`) } return { props: { products, decadeManifest, region, decade, startNode, time, }, revalidate: 200, } } export default function RoomPage({ products, decadeManifest, region, decade, startNode, time, }: InferGetStaticPropsType) { const { isOpen: isOpenModal, onOpen: onOpenModal, onClose: onCloseModal, } = useDisclosure() const [currentMarkerInModal, setCurrentMarkerInModal] = useState() const [recursiveMarkers] = useState( getRecursiveMarkers(decade!, decadeManifest, time) ) const [virtualTourNodes] = useState>( getNodes(products, decadeManifest, region!, decade!, time) ) const [audioPlayer, setAudioPlayer] = useState() const [isAudioInBackground, setIsAudioInBackground] = useState(false) const [isNodeChanged, setIsNodeChanged] = useState(false) const router = useRouter() const audioPlayerRef = useRef(audioPlayer) let navbarArray = new Array( 'autorotate', 'zoom', 'move', 'markers', 'markersList', 'gallery', 'stereo', 'gyroscope', 'fullscreen' ) navbarArray = navbarArray.concat( recursiveMarkers.map((recursiveMarker: any) => { return { id: recursiveMarker.name, content: recursiveMarker.name, title: recursiveMarker.name, className: 'custom-button', visible: false, onClick: (viewer: any) => { changeToRecursiveRoom(recursiveMarker, viewer) }, } }) ) const changeToRecursiveRoom = (recursiveMarker: any, viewer: any) => { const virtualTour = viewer.getPlugin(VirtualTourPlugin) const destNode = virtualTourNodes.find( (node: any) => node.name === recursiveMarker.name ) virtualTour.setCurrentNode(destNode.id) } useEffect(() => { const shperePlayerInstance = new Viewer({ container: 'roomViewer', plugins: [ [ VisibleRangePlugin, { longitudeRange: [null], latitudeRange: [-Math.PI / 2, Math.PI / 4], //Restrict range so you can't see the top of the pano }, ], [GyroscopePlugin, StereoPlugin], MarkersPlugin, [ GalleryPlugin, { thumbnailSize: { width: 100, height: 100 }, }, ], [ VirtualTourPlugin, { positionMode: VirtualTourPlugin.MODE_3D, renderMode: VirtualTourPlugin.MODE_MARKERS, nodes: virtualTourNodes, startNodeId: startNode, }, ], ], touchmoveTwoFingers: true, mousewheelCtrlKey: true, navbar: navbarArray, }) const markersPlugin = shperePlayerInstance.getPlugin(MarkersPlugin) const virtualTourPlugin = shperePlayerInstance.getPlugin(VirtualTourPlugin) markersPlugin?.on('select-marker', (e, marker) => { if (marker.id.includes('tour-link')) { return } if (screenfull.isEnabled) { screenfull.exit() } if (marker.data.markerType === 'room') { virtualTourPlugin?.setCurrentNode( decadeManifest.find( (room: any) => room.name === marker.data.markerPayload.resourceSource ).id ) return } setCurrentMarkerInModal(marker.data) onOpenModal() }) virtualTourPlugin?.on('node-changed', (e, nodeId, data) => { setIsNodeChanged(true) recursiveMarkers.forEach((recursive: any) => shperePlayerInstance.navbar.getButton(recursive.name).hide() ) const originNode = virtualTourNodes.find( (node: any) => node.id === nodeId ) const originRoom = recursiveMarkers.find((recursive: any) => originNode.panorama.includes(recursive.panorama) ) if (originRoom != undefined) { shperePlayerInstance.navbar.getButton(originRoom.name).show() } }) router.events.on('routeChangeStart', () => { if (audioPlayerRef.current && !audioPlayerRef.current?.paused) { audioPlayerRef.current!.pause() audioPlayerRef.current!.src = '' } }) // unmount component instructions return () => { shperePlayerInstance.destroy() router.events.off('routeChangeStart', () => { if (audioPlayerRef.current && !audioPlayerRef.current?.paused) { audioPlayerRef.current!.pause() audioPlayerRef.current!.src = '' } }) } }, []) useEffect(() => { if (isAudioInBackground === true) { setTimeout(() => { audioPlayer!.play() }, 500) setTimeout(() => { audioPlayer?.pause() setIsAudioInBackground(false) }, audioPlayer!.duration - audioPlayer!.currentTime) } }, [isAudioInBackground]) useEffect(() => { if ( currentMarkerInModal != undefined && currentMarkerInModal.markerType === 'video' && !audioPlayer?.paused ) { audioPlayer?.pause() } }, [currentMarkerInModal]) const onAudioPlay = (player: HTMLAudioElement) => { if (!audioPlayer?.paused) { audioPlayer?.pause() } setAudioPlayer(player) } useEffect(() => { audioPlayerRef.current = audioPlayer }, [audioPlayer]) useEffect(() => { if (isNodeChanged && !audioPlayer?.paused) { audioPlayer?.pause() setIsNodeChanged(false) } }, [isNodeChanged]) return ( <> {currentMarkerInModal != undefined ? ( currentMarkerInModal.markerType === 'audio' ? ( setIsAudioInBackground(true)} onAudioPlayerPlay={onAudioPlay} /> ) : ( ) ) : ( <> )}
) } RoomPage.Layout = Layout