diff --git a/src/hub.js b/src/hub.js index 6c6d9fc89c51675a67d67f6113506d1c1e692c56..f73dbb8b41ce5d2a8427a944a33bf0f5771995f1 100644 --- a/src/hub.js +++ b/src/hub.js @@ -102,6 +102,7 @@ AFRAME.registerInputMappings(inputConfig, true); const store = new Store(); const concurrentLoadDetector = new ConcurrentLoadDetector(); +const uiRootProps = {}; concurrentLoadDetector.start(); @@ -212,9 +213,7 @@ function mountUI(scene) { const htmlPrefix = document.body.dataset.htmlPrefix || ""; const showProfileEntry = !store.state.profile.has_saved_profile; - // TODO: Refactor to avoid using return value - /* eslint-disable react/no-render-return-value */ - const uiRoot = ReactDOM.render( + ReactDOM.render( <UIRoot {...{ scene, @@ -226,14 +225,12 @@ function mountUI(scene) { enableScreenSharing, store, htmlPrefix, - showProfileEntry + showProfileEntry, + ...uiRootProps }} />, document.getElementById("ui-root") ); - /* eslint-enable react/no-render-return-value */ - - return uiRoot; } const onReady = async () => { @@ -243,18 +240,24 @@ const onReady = async () => { registerNetworkSchemas(); - const uiRoot = mountUI(scene); + mountUI(scene); + + const remountUI = () => { + mountUI(scene); + }; getAvailableVREntryTypes().then(availableVREntryTypes => { - uiRoot.setState({ availableVREntryTypes }); - uiRoot.handleForcedVREntryType(); + console.log('BPDEBUG availableVREntryTypes', availableVREntryTypes); + uiRootProps.availableVREntryTypes = availableVREntryTypes; + remountUI(); }); const environmentRoot = document.querySelector("#environment-root"); const initialEnvironmentEl = document.createElement("a-entity"); initialEnvironmentEl.addEventListener("bundleloaded", () => { - uiRoot.setState({ initialEnvironmentLoaded: true }); + uiRootProps.initialEnvironmentLoaded = true; + remountUI(); // Wait a tick plus some margin so that the environments actually render. setTimeout(() => scene.renderer.animate(null), 100); }); @@ -262,7 +265,8 @@ const onReady = async () => { if (qs.room) { // If ?room is set, this is `yarn start`, so just use a default environment and query string room. - uiRoot.setState({ janusRoomId: qs.room && !isNaN(parseInt(qs.room)) ? parseInt(qs.room) : 1 }); + uiRootProps.janusRoomId = qs.room && !isNaN(parseInt(qs.room)) ? parseInt(qs.room) : 1; + remountUI(); initialEnvironmentEl.setAttribute("gltf-bundle", { src: "https://asset-bundles-prod.reticulum.io/rooms/meetingroom/MeetingRoom.bundle.json" // src: "https://asset-bundles-prod.reticulum.io/rooms/theater/TheaterMeshes.bundle.json" @@ -279,7 +283,8 @@ const onReady = async () => { const hub = data.hubs[0]; const defaultSpaceTopic = hub.topics[0]; const gltfBundleUrl = defaultSpaceTopic.assets.find(a => a.asset_type === "gltf_bundle").src; - uiRoot.setState({ janusRoomId: defaultSpaceTopic.janus_room_id }); + uiRootProps.janusRoomId = defaultSpaceTopic.janus_room_id; + remountUI(); initialEnvironmentEl.setAttribute("gltf-bundle", `src: ${gltfBundleUrl}`); }; diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index 07488ced3d668b051c21cd1274416b647654c69a..e89cc82a343652784c011ad4097ed9ce7357da02 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -61,11 +61,13 @@ class UIRoot extends Component { store: PropTypes.object, scene: PropTypes.object, htmlPrefix: PropTypes.string, - showProfileEntry: PropTypes.bool + showProfileEntry: PropTypes.bool, + availableVREntryTypes: PropTypes.object, + initialEnvironmentLoaded: PropTypes.bool, + janusRoomId: PropTypes.number }; state = { - availableVREntryTypes: null, entryStep: ENTRY_STEPS.start, enterInVR: false, @@ -88,12 +90,9 @@ class UIRoot extends Component { autoExitTimerInterval: null, secondsRemainingBeforeAutoExit: Infinity, - initialEnvironmentLoaded: false, exited: false, - showProfileEntry: false, - - janusRoomId: null + showProfileEntry: false }; constructor(props) { @@ -110,8 +109,10 @@ class UIRoot extends Component { this.props.scene.addEventListener("stateremoved", this.onAframeStateChanged); } - componentWillUnmount() { - this.props.scene.removeEventListener("loaded", this.onSceneLoaded); + componentDidUpdate(prevProps) { + if (this.props.availableVREntryTypes && prevProps.availableVREntryTypes !== this.props.availableVREntryTypes) { + this.handleForcedVREntryType(); + } } onSceneLoaded = () => { @@ -256,7 +257,7 @@ class UIRoot extends Component { }; enterGearVR = async () => { - if (this.state.availableVREntryTypes.gearvr === VR_DEVICE_AVAILABILITY.yes) { + if (this.props.availableVREntryTypes.gearvr === VR_DEVICE_AVAILABILITY.yes) { await this.performDirectEntryFlow(true); } else { this.exit(); @@ -275,7 +276,7 @@ class UIRoot extends Component { }; enterDaydream = async () => { - if (this.state.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe) { + if (this.props.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe) { this.exit(); // We are not in mobile chrome, so launch into chrome via an Intent URL @@ -473,7 +474,7 @@ class UIRoot extends Component { }; onAudioReadyButton = () => { - this.props.enterScene(this.state.mediaStream, this.state.enterInVR, this.state.janusRoomId); + this.props.enterScene(this.state.mediaStream, this.state.enterInVR, this.props.janusRoomId); const mediaStream = this.state.mediaStream; @@ -498,7 +499,7 @@ class UIRoot extends Component { }; render() { - if (!this.state.initialEnvironmentLoaded || !this.state.availableVREntryTypes || !this.state.janusRoomId) { + if (!this.props.initialEnvironmentLoaded || !this.props.availableVREntryTypes || !this.props.janusRoomId) { return ( <IntlProvider locale={lang} messages={messages}> <div className="loading-panel"> @@ -552,21 +553,21 @@ class UIRoot extends Component { this.state.entryStep === ENTRY_STEPS.start ? ( <div className="entry-panel"> <TwoDEntryButton onClick={this.enter2D} /> - {this.state.availableVREntryTypes.generic !== VR_DEVICE_AVAILABILITY.no && ( + {this.props.availableVREntryTypes.generic !== VR_DEVICE_AVAILABILITY.no && ( <GenericEntryButton onClick={this.enterVR} /> )} - {this.state.availableVREntryTypes.gearvr !== VR_DEVICE_AVAILABILITY.no && ( + {this.props.availableVREntryTypes.gearvr !== VR_DEVICE_AVAILABILITY.no && ( <GearVREntryButton onClick={this.enterGearVR} /> )} - {this.state.availableVREntryTypes.daydream !== VR_DEVICE_AVAILABILITY.no && ( + {this.props.availableVREntryTypes.daydream !== VR_DEVICE_AVAILABILITY.no && ( <DaydreamEntryButton onClick={this.enterDaydream} subtitle={ - this.state.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe ? daydreamMaybeSubtitle : "" + this.props.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe ? daydreamMaybeSubtitle : "" } /> )} - {this.state.availableVREntryTypes.cardboard !== VR_DEVICE_AVAILABILITY.no && ( + {this.props.availableVREntryTypes.cardboard !== VR_DEVICE_AVAILABILITY.no && ( <div className="entry-panel__secondary" onClick={this.enterVR}> <FormattedMessage id="entry.cardboard" /> </div>