From 9b59df4dee32f151fa07c5b829f3e51577463fbb Mon Sep 17 00:00:00 2001 From: Brian Peiris <brianpeiris@gmail.com> Date: Thu, 15 Mar 2018 12:00:14 -0700 Subject: [PATCH] storage based name entry with validation --- src/react-components/ui-root.js | 36 +++++++++++++++++++++++++++++---- src/room.js | 5 ++++- src/storage/store.js | 2 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index 7239f2289..a9f97fa58 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -1,12 +1,14 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { VR_DEVICE_AVAILABILITY } from "../utils/vr-caps-detect.js"; +import Store, { SCHEMA } from "../storage/store"; const ENTRY_STEPS = { start: "start", mic_grant: "mic_grant", mic_granted: "mic_granted", audio_setup: "audio_setup", + name_entry: "name_entry", finished: "finished" } @@ -58,7 +60,9 @@ class UIRoot extends Component { static propTypes = { enterScene: PropTypes.func, availableVREntryTypes: PropTypes.object - }; + } + + store = new Store() state = { entryStep: ENTRY_STEPS.start, @@ -76,7 +80,7 @@ class UIRoot extends Component { this.setupTestTone(); } - setupTestTone = () => { + setupTestTone = () => { const toneClip = document.querySelector("#test-tone"); const toneLength = 1800; const toneDelay = 5000; @@ -228,13 +232,19 @@ class UIRoot extends Component { } } - this.props.enterScene(mediaStream); this.stopTestTone(); + this.setState({ entryStep: ENTRY_STEPS.name_entry }); + } + + saveName = (e) => { + e.preventDefault(); + this.store.update({ profile: { display_name: this.nameInput.value } }); + this.props.enterScene(this.state.mediaStream); this.setState({ entryStep: ENTRY_STEPS.finished }); } render() { - const entryPanel = this.state.entryStep === ENTRY_STEPS.start + const entryPanel = this.state.entryStep === ENTRY_STEPS.start ? ( <div> <TwoDEntryButton onClick={this.enter2D}/> @@ -274,12 +284,30 @@ class UIRoot extends Component { </div> ) : null; + const nameEntryPanel = this.state.entryStep === ENTRY_STEPS.name_entry + ? ( + <div> + Name Entry + <form onSubmit={this.saveName}> + <label>Name: + <input + defaultValue={this.store.state.profile.display_name} + required pattern={SCHEMA.definitions.profile.properties.display_name.pattern} + title="Alphanumerics and hyphens. At least 3 characters, no more than 32" + ref={inp => this.nameInput = inp}/> + </label> + <input type="submit" value="Save" /> + </form> + </div> + ) : null; + return ( <div> UI Here {entryPanel} {micPanel} {audioSetupPanel} + {nameEntryPanel} </div> ); } diff --git a/src/room.js b/src/room.js index afe163d27..2f01a1382 100644 --- a/src/room.js +++ b/src/room.js @@ -186,7 +186,10 @@ function onConnect() { function mountUI() { getAvailableVREntryTypes().then(availableVREntryTypes => { - ReactDOM.render(<UIRoot {...{ availableVREntryTypes, enterScene }} />, document.getElementById("ui-root")); + ReactDOM.render( + <UIRoot {...{ availableVREntryTypes, enterScene }} />, + document.getElementById("ui-root") + ); document.getElementById("loader").style.display = "none"; }); } diff --git a/src/storage/store.js b/src/storage/store.js index 34caa9edb..b1b362d53 100644 --- a/src/storage/store.js +++ b/src/storage/store.js @@ -7,7 +7,7 @@ const validator = new Validator(); // Durable (via local-storage) schema-enforced state that is meant to be consumed via forward data flow. // (Think flux but with way less incidental complexity, at least for now :)) -const SCHEMA = { +export const SCHEMA = { id: "/MozillaDuckStore", definitions: { -- GitLab