diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index c61b991c4bf080b0044701f4e853f1c8712a1936..0281dcd9f8d798366a072898e13230e3dc120faf 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -10,17 +10,17 @@ "entry.desktop-screen": "Screen", "entry.mobile-screen": "Phone", "entry.mobile-safari": "Safari", - "entry.generic-prefix": "Enter with ", - "entry.generic-medium": "PC VR", + "entry.generic-prefix": " ", + "entry.generic-medium": "Connected Headset", "entry.generic-subtitle-desktop": "Oculus or SteamVR", "entry.gearvr-prefix": "Enter on ", "entry.gearvr-medium": "Gear VR", "entry.choose-device": "Choose Device", - "entry.device-prefix-desktop": "Use a ", - "entry.device-prefix-mobile": "Use a ", + "entry.device-prefix-desktop": " ", + "entry.device-prefix-mobile": " ", "entry.device-medium": "Mobile Headset", - "entry.device-subtitle-desktop": "Standalone or Phone Clip-in", - "entry.device-subtitle-mobile": "Standalone or Phone Clip-in", + "entry.device-subtitle-desktop": "Standalone or Mobile VR", + "entry.device-subtitle-mobile": "Standalone or Mobile VR", "entry.device-subtitle-vr": "Phone or PC", "entry.cardboard": "Enter on Google Cardboard", "entry.daydream-prefix": "Enter on ", @@ -84,12 +84,12 @@ "link.in_your_browser": "In your headset's browser, go to:", "link.enter_code": "Then, enter this one-time link code:", "link.do_not_close": "Keep this open to use this code.", - "link.connect_headset": "Connect Mobile Headset", + "link.connect_headset": "Link VR Headset", "link.cancel": "cancel", "invite.enter_via": "Enter via ", "invite.tweet": "tweet", "invite.and_enter_code": " with code:", - "invite.or_visit": "or visit", + "invite.or_visit": "or share permalink", "spoke.primary_tagline": "make your space", "spoke.secondary_tagline": "Create 3D social scenes for ", "spoke.thank_you": "Thank you for downloading Spoke!", diff --git a/src/hub.js b/src/hub.js index ec589e2da5eb2acb8b7e31df4c63c9d29a1723df..9685b24749ceb07f42b8afa778469b048a0a85b8 100644 --- a/src/hub.js +++ b/src/hub.js @@ -257,7 +257,7 @@ async function handleHubChannelJoined(entryManager, hubChannel, data) { document .querySelector("#hud-hub-entry-link") - .setAttribute("text", { value: `hub.link/${hub.entry_code}`, width: 1.1, align: "center" }); + .setAttribute("text", { value: `hub.link/${hub.hub_id}`, width: 1.1, align: "center" }); scene.setAttribute("networked-scene", { room: hub.hub_id, diff --git a/src/link.js b/src/link.js index 401fe54d9b8b9bd91df1c2140257710502a23add..7f803b75a780d22bd85e51f6902806efebea1b5e 100644 --- a/src/link.js +++ b/src/link.js @@ -6,6 +6,7 @@ import LinkRoot from "./react-components/link-root"; import LinkChannel from "./utils/link-channel"; import { connectToReticulum } from "./utils/phoenix-utils"; import Store from "./storage/store"; +import { detectInHMD } from "./utils/vr-caps-detect.js"; registerTelemetry(); @@ -17,4 +18,7 @@ const linkChannel = new LinkChannel(store); linkChannel.setSocket(socket); -ReactDOM.render(<LinkRoot store={store} linkChannel={linkChannel} />, document.getElementById("link-root")); +ReactDOM.render( + <LinkRoot store={store} linkChannel={linkChannel} showHeadsetLinkOption={detectInHMD()} />, + document.getElementById("link-root") +); diff --git a/src/react-components/invite-dialog.js b/src/react-components/invite-dialog.js index aa5c511bc6da6f8b41c1d08222ea4d0fec7eb512..414194081d417d6185cd1041bdb1ed1a7be355ab 100644 --- a/src/react-components/invite-dialog.js +++ b/src/react-components/invite-dialog.js @@ -15,6 +15,7 @@ function pad(num, size) { export default class InviteDialog extends Component { static propTypes = { entryCode: PropTypes.number, + hubId: PropTypes.string, allowShare: PropTypes.bool, onClose: PropTypes.func }; @@ -42,11 +43,11 @@ export default class InviteDialog extends Component { const { entryCode } = this.props; const entryCodeString = pad(entryCode, 6); - const shareShortLink = `hub.link/${entryCodeString}`; - const shareFullLink = [location.protocol, "//", location.host, location.pathname].join(""); + const shortLinkText = `hub.link/${this.props.hubId}`; + const shortLink = "https://" + shortLinkText; const tweetText = `Join me now in #hubs!`; - const tweetLink = `https://twitter.com/share?url=${encodeURIComponent(shareFullLink)}&text=${encodeURIComponent( + const tweetLink = `https://twitter.com/share?url=${encodeURIComponent(shortLink)}&text=${encodeURIComponent( tweetText )}`; @@ -74,15 +75,15 @@ export default class InviteDialog extends Component { <FormattedMessage id="invite.or_visit" /> </div> <div className={styles.domain}> - <input type="text" readOnly onFocus={e => e.target.select()} value={shareShortLink} /> + <input type="text" readOnly onFocus={e => e.target.select()} value={shortLinkText} /> </div> <div className={styles.buttons}> - <button className={styles.linkButton} onClick={this.copyClicked.bind(this, "https://" + shareShortLink)}> + <button className={styles.linkButton} onClick={this.copyClicked.bind(this, shortLink)}> <span>{this.state.copyButtonActive ? "copied!" : "copy"}</span> </button> {this.props.allowShare && navigator.share && ( - <button className={styles.linkButton} onClick={this.shareClicked.bind(this, shareFullLink)}> + <button className={styles.linkButton} onClick={this.shareClicked.bind(this, shortLink)}> <span>{this.state.shareButtonActive ? "sharing..." : "share"}</span> </button> )} diff --git a/src/react-components/link-root.js b/src/react-components/link-root.js index 5253de0130b73f10d7e71ada313fa01057e0aaf1..be652f7b18d42a88f9cd9594cecdf46074c7e7b0 100644 --- a/src/react-components/link-root.js +++ b/src/react-components/link-root.js @@ -20,7 +20,8 @@ class LinkRoot extends Component { static propTypes = { intl: PropTypes.object, store: PropTypes.object, - linkChannel: PropTypes.object + linkChannel: PropTypes.object, + showHeadsetLinkOption: PropTypes.bool }; state = { @@ -178,16 +179,18 @@ class LinkRoot extends Component { </div> <div className={styles.enteredFooter}> - {!this.state.isAlphaMode && ( - <img onClick={() => this.toggleMode()} src={HeadsetIcon} className={styles.headsetIcon} /> - )} - {!this.state.isAlphaMode && ( - <span> - <a href="#" onClick={() => this.toggleMode()}> - <FormattedMessage id="link.linking_a_headset" /> - </a> - </span> - )} + {!this.state.isAlphaMode && + this.props.showHeadsetLinkOption && ( + <img onClick={() => this.toggleMode()} src={HeadsetIcon} className={styles.headsetIcon} /> + )} + {!this.state.isAlphaMode && + this.props.showHeadsetLinkOption && ( + <span> + <a href="#" onClick={() => this.toggleMode()}> + <FormattedMessage id="link.linking_a_headset" /> + </a> + </span> + )} </div> </div> @@ -208,15 +211,19 @@ class LinkRoot extends Component { {d} </button> ))} - <button - className={classNames(styles.keypadButton, styles.keypadToggleMode)} - onTouchStart={() => this.toggleMode()} - onClick={() => { - if (!hasTouchEvents) this.toggleMode(); - }} - > - {this.state.isAlphaMode ? "123" : "ABC"} - </button> + {this.props.showHeadsetLinkOption ? ( + <button + className={classNames(styles.keypadButton, styles.keypadToggleMode)} + onTouchStart={() => this.toggleMode()} + onClick={() => { + if (!hasTouchEvents) this.toggleMode(); + }} + > + {this.state.isAlphaMode ? "123" : "ABC"} + </button> + ) : ( + <div /> + )} {!this.state.isAlphaMode && ( <button disabled={this.state.entered.length === this.maxAllowedChars()} diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index 73c2a1e871da4c1f4185daf1a85efaaaac80eb62..153bd64b309abddc14cea0165aeab6cad3f5f3c6 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -553,7 +553,7 @@ class UIRoot extends Component { }; onMiniInviteClicked = () => { - const link = "https://hub.link/" + this.props.hubEntryCode; + const link = "https://hub.link/" + this.props.hubId; this.setState({ miniInviteActivated: true }); setTimeout(() => { @@ -977,7 +977,7 @@ class UIRoot extends Component { ? navigator.share ? "sharing..." : "copied!" - : "hub.link/" + this.props.hubEntryCode} + : "hub.link/" + this.props.hubId} </span> </button> )} @@ -990,6 +990,7 @@ class UIRoot extends Component { <InviteDialog allowShare={!this.props.availableVREntryTypes.isInHMD} entryCode={this.props.hubEntryCode} + hubId={this.props.hubId} onClose={() => this.setState({ showInviteDialog: false })} /> )} diff --git a/src/utils/vr-caps-detect.js b/src/utils/vr-caps-detect.js index d5ad87eff808d1cb528c76b068de0c855d0bb3a0..fc2737ad41519798326d1f2ce6cec57e5a8e5b23 100644 --- a/src/utils/vr-caps-detect.js +++ b/src/utils/vr-caps-detect.js @@ -22,6 +22,11 @@ function isMaybeDaydreamCompatibleDevice(ua) { // that can be entered into as a "generic" entry flow. const GENERIC_ENTRY_TYPE_DEVICE_BLACKLIST = [/cardboard/i]; +export function detectInHMD() { + const isOculusBrowser = /Oculus/.test(navigator.userAgent); + return isOculusBrowser; +} + // Tries to determine VR entry compatibility regardless of the current browser. // // For each VR "entry type", returns VR_DEVICE_AVAILABILITY.yes if that type can be launched into directly from this browser @@ -45,7 +50,6 @@ const GENERIC_ENTRY_TYPE_DEVICE_BLACKLIST = [/cardboard/i]; export async function getAvailableVREntryTypes() { const ua = navigator.userAgent; const isSamsungBrowser = browser.name === "chrome" && /SamsungBrowser/.test(ua); - const isOculusBrowser = /Oculus/.test(ua); // This needs to be kept up-to-date with the latest browsers that can support VR and Hubs. // Checking for navigator.getVRDisplays always passes b/c of polyfill. @@ -63,7 +67,9 @@ export async function getAvailableVREntryTypes() { : VR_DEVICE_AVAILABILITY.no; const displays = isWebVRCapableBrowser ? await navigator.getVRDisplays() : []; - const isInHMD = isOculusBrowser; + + const isOculusBrowser = /Oculus/.test(ua); + const isInHMD = detectInHMD(); const screen = isInHMD ? VR_DEVICE_AVAILABILITY.no