diff --git a/src/assets/images/twitter.svg b/src/assets/images/twitter.svg new file mode 100755 index 0000000000000000000000000000000000000000..4f16790673574fb41a23496659eb9659c910f7ba --- /dev/null +++ b/src/assets/images/twitter.svg @@ -0,0 +1,3 @@ +<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M153.6 301.6C247.9 301.6 299.5 223.4 299.5 155.7C299.5 153.5 299.5 151.3 299.4 149.1C309.4 141.9 318.1 132.8 325 122.5C315.8 126.6 305.9 129.3 295.5 130.6C306.1 124.3 314.2 114.2 318.1 102.2C308.2 108.1 297.2 112.3 285.5 114.6C276.1 104.6 262.8 98.4 248.1 98.4C219.8 98.4 196.8 121.4 196.8 149.7C196.8 153.7 197.3 157.6 198.1 161.4C155.5 159.3 117.7 138.8 92.4 107.8C88 115.4 85.5 124.2 85.5 133.6C85.5 151.4 94.6 167.1 108.3 176.3C99.9 176 92 173.7 85.1 169.9C85.1 170.1 85.1 170.3 85.1 170.6C85.1 195.4 102.8 216.2 126.2 220.9C121.9 222.1 117.4 222.7 112.7 222.7C109.4 222.7 106.2 222.4 103.1 221.8C109.6 242.2 128.6 257 151 257.4C133.4 271.2 111.3 279.4 87.3 279.4C83.2 279.4 79.1 279.2 75.1 278.7C97.7 293.1 124.7 301.6 153.6 301.6Z" fill="white"/> +</svg> diff --git a/src/assets/stylesheets/invite-dialog.scss b/src/assets/stylesheets/invite-dialog.scss index 2466630cef1cbec9e3c128abd2b8ad7d647e5894..f28210e2492ad663f31aa1f08874c3f89c5ac755 100644 --- a/src/assets/stylesheets/invite-dialog.scss +++ b/src/assets/stylesheets/invite-dialog.scss @@ -22,8 +22,11 @@ } :local(.link-button) { + @extend %action-button; @extend %action-button-selected; + min-width: auto; margin-top: 4px; + flex: 1; @media (max-height: 370px) { display: none; @@ -115,8 +118,9 @@ :local(.buttons) { display: flex; justify-content: space-between; + width: 100%; - button { + button, a { margin: 0 12px; } } diff --git a/src/assets/stylesheets/scene-ui.scss b/src/assets/stylesheets/scene-ui.scss index 2f48ccee5dae1e9abc7a63258d5955838f1c16c1..55b703e3f55c37e8bdf9966810b31ac1976810f0 100644 --- a/src/assets/stylesheets/scene-ui.scss +++ b/src/assets/stylesheets/scene-ui.scss @@ -52,6 +52,22 @@ margin-bottom: 32px; } +:local(.tweetButton) { + @extend %action-button; + margin-top: 12px; + background-color: #1b95e0; + align-self: center; + padding-right: 32px; + display: flex; + flex-direction: row; + + img { + width: 42px; + height: 42px; + margin-right: 6px; + } +} + :local(.logo) { width: 100%; display: block; diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index 1e4cb312a8f881a13919dcd4f6bfaf517e1e9e46..dc1de2964279d036a8b4e484f762a87af5a8bf09 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -87,12 +87,14 @@ "help.report_issue": "Report an Issue", "scene.logo_tagline": "A new way to get together", "scene.create_button": "Create a room with this scene", + "scene.tweet_button": "Share on Twitter", "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.cancel": "cancel", "invite.enter_via": "Enter via ", + "invite.tweet": "tweet", "invite.and_enter_code": " with code:", "invite.or_visit": "or visit", "spoke.primary_tagline": "make your space", diff --git a/src/components/character-controller.js b/src/components/character-controller.js index 28e48e6c2cb1d37615a84a98c5b793f89efe899d..b0dd84323e3d6eb7027df2d938fbb66a37705789 100644 --- a/src/components/character-controller.js +++ b/src/components/character-controller.js @@ -192,10 +192,10 @@ AFRAME.registerComponent("character-controller", { resetPositionOnNavMesh: function(position, navPosition, object3D) { const { pathfinder } = this.el.sceneEl.systems.nav; if (!(this.navZone in pathfinder.zones)) return; - this.navGroup = pathfinder.getGroup(this.navZone, navPosition, true); + this.navGroup = pathfinder.getGroup(this.navZone, navPosition, true, true); this.navNode = null; this._setNavNode(navPosition); - object3D.position.copy(navPosition); + pathfinder.clampStep(position, navPosition, this.navNode, this.navZone, this.navGroup, object3D.position); }, updateVelocity: function(dt) { diff --git a/src/react-components/invite-dialog.js b/src/react-components/invite-dialog.js index 5a9e4446a6486dfb5fe049bb913885b76a469756..aa5c511bc6da6f8b41c1d08222ea4d0fec7eb512 100644 --- a/src/react-components/invite-dialog.js +++ b/src/react-components/invite-dialog.js @@ -28,7 +28,7 @@ export default class InviteDialog extends Component { this.setState({ shareButtonActive: true }); setTimeout(() => this.setState({ shareButtonActive: false }), 5000); - navigator.share({ title: document.title, url: link }); + navigator.share({ title: "Join me now in #hubs!", url: link }); }; copyClicked = link => { @@ -42,7 +42,13 @@ export default class InviteDialog extends Component { const { entryCode } = this.props; const entryCodeString = pad(entryCode, 6); - const shareLink = `hub.link/${entryCodeString}`; + const shareShortLink = `hub.link/${entryCodeString}`; + const shareFullLink = [location.protocol, "//", location.host, location.pathname].join(""); + + const tweetText = `Join me now in #hubs!`; + const tweetLink = `https://twitter.com/share?url=${encodeURIComponent(shareFullLink)}&text=${encodeURIComponent( + tweetText + )}`; return ( <div className={styles.dialog}> @@ -68,18 +74,24 @@ 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={shareLink} /> + <input type="text" readOnly onFocus={e => e.target.select()} value={shareShortLink} /> </div> <div className={styles.buttons}> - <button className={styles.linkButton} onClick={this.copyClicked.bind(this, "https://" + shareLink)}> + <button className={styles.linkButton} onClick={this.copyClicked.bind(this, "https://" + shareShortLink)}> <span>{this.state.copyButtonActive ? "copied!" : "copy"}</span> </button> {this.props.allowShare && navigator.share && ( - <button className={styles.linkButton} onClick={this.shareClicked.bind(this, "https://" + shareLink)}> + <button className={styles.linkButton} onClick={this.shareClicked.bind(this, shareFullLink)}> <span>{this.state.shareButtonActive ? "sharing..." : "share"}</span> </button> )} + {this.props.allowShare && + !navigator.share && ( + <a href={tweetLink} className={styles.linkButton} target="_blank" rel="noopener noreferrer"> + <FormattedMessage id="invite.tweet" /> + </a> + )} </div> </div> ); diff --git a/src/react-components/scene-ui.js b/src/react-components/scene-ui.js index ec04e095e135bac8bb85beff8c27c7cf2b6b3ae9..b8f8307d3e52e88d8c6c05fd0fd29bca3246ea5f 100644 --- a/src/react-components/scene-ui.js +++ b/src/react-components/scene-ui.js @@ -66,6 +66,12 @@ class SceneUI extends Component { }; render() { + const sceneUrl = [location.protocol, "//", location.host, location.pathname].join(""); + const tweetText = `${this.props.sceneName} in #hubs`; + const tweetLink = `https://twitter.com/share?url=${encodeURIComponent(sceneUrl)}&text=${encodeURIComponent( + tweetText + )}`; + return ( <IntlProvider locale={lang} messages={messages}> <div className={styles.ui}> @@ -89,6 +95,12 @@ class SceneUI extends Component { <button onClick={this.createRoom}> <FormattedMessage id="scene.create_button" /> </button> + <a href={tweetLink} rel="noopener noreferrer" target="_blank" className={styles.tweetButton}> + <img src="../assets/images/twitter.svg" /> + <div> + <FormattedMessage id="scene.tweet_button" /> + </div> + </a> </div> </div> <div className={styles.info}>