diff --git a/.eslintrc.json b/.eslintrc.json index d39862227e78dc98b5d902fd0a1bf84a23fa76b4..8ab63d8cc0f6d8854b53e96c03a7889080ecb650 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,8 +1,5 @@ { - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module" - }, + "parser": "babel-eslint", "plugins": [ "prettier", "react" diff --git a/.prettierrc.json b/.prettierrc.json index 963354f23168f2e9f79b42c261c612cc662e849c..25fc98b8834374d036ee851ffe5a75fa92ffff4a 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,3 +1,4 @@ { - "printWidth": 120 + "printWidth": 120, + "parser": "babylon" } diff --git a/package.json b/package.json index 123aaec21dbee756dbaa10b5229c8be8f0816315..5baab2abb42b937e578c0b379d96fcc81f9f9e39 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,10 @@ "aframe-physics-system": "https://github.com/donmccurdy/aframe-physics-system", "aframe-teleport-controls": "https://github.com/netpro2k/aframe-teleport-controls#feature/pauseable", "aframe-xr": "github:brianpeiris/aframe-xr#3162aed", - "babel-plugin-react-intl": "^2.4.0", - "babel-plugin-transform-react-jsx-img-import": "^0.1.4", "classnames": "^2.2.5", "detect-browser": "^2.1.0", "event-target-shim": "^3.0.1", "jsonschema": "^1.2.2", - "material-design-lite": "^1.3.0", "minijanus": "^0.5.0", "mobile-detect": "^1.4.1", "moving-average": "^1.0.0", @@ -49,9 +46,11 @@ }, "devDependencies": { "babel-core": "^6.26.0", - "babel-eslint": "^8.2.2", + "babel-eslint": "8", "babel-loader": "^7.1.3", + "babel-plugin-react-intl": "^2.4.0", "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-react-jsx-img-import": "^0.1.4", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.24.1", "cross-env": "^5.1.3", diff --git a/scripts/build_local_reticulum.sh b/scripts/build_local_reticulum.sh new file mode 100755 index 0000000000000000000000000000000000000000..118a801e24fba4fdbed51c5b23f793db46cc498f --- /dev/null +++ b/scripts/build_local_reticulum.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +if [ ! -e ../reticulum ]; then + echo "This script assumes reticulum is checked out in a sibling to this folder." +fi + +rm -rf ../reticulum/priv/static ; BASE_ASSETS_PATH=http://localhost:4000/ yarn build -- --output-path ../reticulum/priv/static diff --git a/src/assets/environments/CliffVista_mesh.glb b/src/assets/environments/cliff_meeting_space/CliffVista_mesh.glb similarity index 100% rename from src/assets/environments/CliffVista_mesh.glb rename to src/assets/environments/cliff_meeting_space/CliffVista_mesh.glb diff --git a/src/assets/environments/FloorNav_mesh.glb b/src/assets/environments/cliff_meeting_space/FloorNav_mesh.glb similarity index 100% rename from src/assets/environments/FloorNav_mesh.glb rename to src/assets/environments/cliff_meeting_space/FloorNav_mesh.glb diff --git a/src/assets/environments/MeetingSpace1_mesh.glb b/src/assets/environments/cliff_meeting_space/MeetingSpace1_mesh.glb similarity index 100% rename from src/assets/environments/MeetingSpace1_mesh.glb rename to src/assets/environments/cliff_meeting_space/MeetingSpace1_mesh.glb diff --git a/src/assets/environments/OutdoorFacade_mesh.glb b/src/assets/environments/cliff_meeting_space/OutdoorFacade_mesh.glb similarity index 100% rename from src/assets/environments/OutdoorFacade_mesh.glb rename to src/assets/environments/cliff_meeting_space/OutdoorFacade_mesh.glb diff --git a/src/assets/environments/cliff_meeting_space/bundle.json.tpl b/src/assets/environments/cliff_meeting_space/bundle.json.tpl new file mode 100644 index 0000000000000000000000000000000000000000..cb321614109330cfb9d010a899c215bd740c27b2 --- /dev/null +++ b/src/assets/environments/cliff_meeting_space/bundle.json.tpl @@ -0,0 +1,28 @@ +{ + "name": "cliff_meeting_space", + "version": "0.1.0", + "meta": { + "title": "Cliffside Meeting Space", + "description": "Enjoy a beautiful vista view while collaborating in Mixed Reality", + "authors": [ + { "name": "Jim Conrad", "github": "j-conrad" } + ], + "images": [ + { "type": "preview-thumbnail", "srcset": "<%= require("./preview-thumbnail.png") %>" } + ] + }, + "assets": [ + { + "name": "space-geometry", "src": "<%= require("./MeetingSpace1_mesh.glb") %>" + }, + { + "name": "outdoor-geometry", "src": "<%= require("./OutdoorFacade_mesh.glb") %>" + }, + { + "name": "collision", "src": "<%= require("./FloorNav_mesh.glb") %>" + }, + { + "name": "cliff-geometry", "src": "<%= require("./CliffVista_mesh.glb") %>" + } + ] +} diff --git a/src/assets/environments/cliff_meeting_space/preview-thumbnail.png b/src/assets/environments/cliff_meeting_space/preview-thumbnail.png new file mode 100755 index 0000000000000000000000000000000000000000..050f0e62619b45bb16fdd1bf648a0ba2696a6d46 Binary files /dev/null and b/src/assets/environments/cliff_meeting_space/preview-thumbnail.png differ diff --git a/src/assets/fonts/zilla-slab_latin-ext.woff2 b/src/assets/fonts/zilla-slab_latin-ext.woff2 deleted file mode 100644 index 60259781df0d9a85f8e9f88ef7ed3dcf8b69b12b..0000000000000000000000000000000000000000 Binary files a/src/assets/fonts/zilla-slab_latin-ext.woff2 and /dev/null differ diff --git a/src/assets/fonts/zilla-slab_latin.woff2 b/src/assets/fonts/zilla-slab_latin.woff2 deleted file mode 100644 index 18b5d6e8f5f3bd37ffe7effde8414b7ff3ed0409..0000000000000000000000000000000000000000 Binary files a/src/assets/fonts/zilla-slab_latin.woff2 and /dev/null differ diff --git a/src/assets/images/dice_icon.svg b/src/assets/images/dice_icon.svg new file mode 100755 index 0000000000000000000000000000000000000000..7625794485f657ff84d4323f113e34063f78905f --- /dev/null +++ b/src/assets/images/dice_icon.svg @@ -0,0 +1,22 @@ +<svg width="32" height="34" viewBox="0 0 32 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>dice_icon</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="translate(448 -293)"> +<g id="dice_icon"> +<g id="Group"> +<g id="Group"> +<g id="Vector"> +<use xlink:href="#path0_fill" transform="translate(-448 310.389)" fill="#FFFFFF"/> +</g> +<g id="Vector"> +<use xlink:href="#path1_fill" transform="translate(-436.032 293)" fill="#FFFFFF"/> +</g> +</g> +</g> +</g> +</g> +<defs> +<path id="path0_fill" d="M 12.7277 0L 3.47119 0C 1.55509 0 0 1.59463 0 3.55943L 0 13.0513C 0 15.0161 1.55509 16.6107 3.47119 16.6107L 12.7277 16.6107C 14.6449 16.6107 16.1989 15.0161 16.1989 13.0513L 16.1989 3.55943C 16.1989 1.59463 14.6449 0 12.7277 0ZM 4.04972 14.2377C 3.09167 14.2377 2.31412 13.4404 2.31412 12.458C 2.31412 11.4756 3.09167 10.6783 4.04972 10.6783C 5.00777 10.6783 5.78531 11.4756 5.78531 12.458C 5.78531 13.4404 5.00777 14.2377 4.04972 14.2377ZM 4.04972 5.93239C 3.09167 5.93239 2.31412 5.13508 2.31412 4.15267C 2.31412 3.17027 3.09167 2.37296 4.04972 2.37296C 5.00777 2.37296 5.78531 3.17027 5.78531 4.15267C 5.78531 5.13508 5.00777 5.93239 4.04972 5.93239ZM 8.09943 10.0851C 7.14139 10.0851 6.36384 9.28775 6.36384 8.30534C 6.36384 7.32294 7.14139 6.52563 8.09943 6.52563C 9.05748 6.52563 9.83503 7.32294 9.83503 8.30534C 9.83503 9.28775 9.05748 10.0851 8.09943 10.0851ZM 12.1492 14.2377C 11.1911 14.2377 10.4136 13.4404 10.4136 12.458C 10.4136 11.4756 11.1911 10.6783 12.1492 10.6783C 13.1072 10.6783 13.8847 11.4756 13.8847 12.458C 13.8847 13.4404 13.1072 14.2377 12.1492 14.2377ZM 12.1492 5.93239C 11.1911 5.93239 10.4136 5.13508 10.4136 4.15267C 10.4136 3.17027 11.1911 2.37296 12.1492 2.37296C 13.1072 2.37296 13.8847 3.17027 13.8847 4.15267C 13.8847 5.13508 13.1072 5.93239 12.1492 5.93239Z"/> +<path id="path1_fill" d="M 19.0155 7.75393L 12.47 1.04201C 11.115 -0.347359 8.91661 -0.347359 7.56169 1.04201L 1.01617 7.75393C -0.338747 9.14329 -0.338747 11.3976 1.01617 12.787L 7.56169 19.4989C 8.91661 20.8883 11.115 20.8883 12.47 19.4989L 19.0155 12.787C 20.3704 11.3976 20.3704 9.14329 19.0155 7.75393ZM 11.2423 17.4023C 10.5643 18.0964 9.46621 18.0964 8.78817 17.4023C 8.11013 16.7071 8.11013 15.5799 8.78817 14.8847C 9.46621 14.1906 10.5643 14.1906 11.2423 14.8847C 11.9203 15.5799 11.9203 16.7071 11.2423 17.4023ZM 11.2423 11.5281C 10.5643 12.2234 9.46621 12.2234 8.78817 11.5281C 8.11013 10.8328 8.11013 9.70687 8.78817 9.01159C 9.46621 8.31631 10.5643 8.31631 11.2423 9.01159C 11.9203 9.70687 11.9203 10.834 11.2423 11.5281ZM 11.2423 5.65623C 10.5643 6.35032 9.46621 6.35032 8.78817 5.65623C 8.11013 4.96095 8.11013 3.83382 8.78817 3.13855C 9.46621 2.44446 10.5643 2.44446 11.2423 3.13855C 11.9203 3.83382 11.9203 4.96095 11.2423 5.65623Z"/> +</defs> +</svg> diff --git a/src/assets/images/expand_dots_icon.svg b/src/assets/images/expand_dots_icon.svg new file mode 100755 index 0000000000000000000000000000000000000000..8d765ad21b0d4de41fa4c09771ebf83761cafd06 --- /dev/null +++ b/src/assets/images/expand_dots_icon.svg @@ -0,0 +1,20 @@ +<svg width="26" height="6" viewBox="0 0 26 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>expand_dots_icon</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="translate(455 -258)"> +<g id="expand_dots_icon"> +<g id="Ellipse"> +<use xlink:href="#path0_fill" transform="translate(-455 258)" fill="#FFFFFF"/> +</g> +<g id="Ellipse"> +<use xlink:href="#path0_fill" transform="translate(-435 258)" fill="#FFFFFF"/> +</g> +<g id="Ellipse"> +<use xlink:href="#path0_fill" transform="translate(-445 258)" fill="#FFFFFF"/> +</g> +</g> +</g> +<defs> +<path id="path0_fill" d="M 6 3C 6 4.65685 4.65685 6 3 6C 1.34315 6 0 4.65685 0 3C 0 1.34315 1.34315 0 3 0C 4.65685 0 6 1.34315 6 3Z"/> +</defs> +</svg> diff --git a/src/assets/images/hub_create_button_disabled.svg b/src/assets/images/hub_create_button_disabled.svg new file mode 100755 index 0000000000000000000000000000000000000000..168e43e80b55792126e69e85cd75ae5da2ec51e8 --- /dev/null +++ b/src/assets/images/hub_create_button_disabled.svg @@ -0,0 +1,20 @@ +<svg width="55" height="55" viewBox="0 0 55 55" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>hub_create_button_disabled</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="translate(-92 -236)"> +<g id="hub_create_button_disabled"> +<g id="Oval Copy"> +<use xlink:href="#path0_stroke" transform="translate(94 238)" fill="#C0C0C0"/> +</g> +<g id="Group 7"> +<g id="Union"> +<use xlink:href="#path1_fill" transform="translate(112.7 255.567)" fill="#C0C0C0"/> +</g> +</g> +</g> +</g> +<defs> +<path id="path0_stroke" d="M 25.5 52.5C 40.4117 52.5 52.5 40.4117 52.5 25.5L 49.5 25.5C 49.5 38.7548 38.7548 49.5 25.5 49.5L 25.5 52.5ZM 52.5 25.5C 52.5 10.5883 40.4117 -1.5 25.5 -1.5L 25.5 1.5C 38.7548 1.5 49.5 12.2452 49.5 25.5L 52.5 25.5ZM 25.5 -1.5C 10.5883 -1.5 -1.5 10.5883 -1.5 25.5L 1.5 25.5C 1.5 12.2452 12.2452 1.5 25.5 1.5L 25.5 -1.5ZM -1.5 25.5C -1.5 40.4117 10.5883 52.5 25.5 52.5L 25.5 49.5C 12.2452 49.5 1.5 38.7548 1.5 25.5L -1.5 25.5Z"/> +<path id="path1_fill" fill-rule="evenodd" d="M 6.8 1.52588e-05L 15.3 7.65001L 6.8 15.3L 6.80001 10.2L 7.62939e-06 10.2L 7.62939e-06 5.10002L 6.80001 5.10002L 6.8 1.52588e-05Z"/> +</defs> +</svg> diff --git a/src/assets/images/hub_create_button_enabled.svg b/src/assets/images/hub_create_button_enabled.svg new file mode 100755 index 0000000000000000000000000000000000000000..f696984717b06cf6448829a45f80fcdab17b1800 --- /dev/null +++ b/src/assets/images/hub_create_button_enabled.svg @@ -0,0 +1,20 @@ +<svg width="55" height="55" viewBox="0 0 55 55" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>hub_create_button_enabled</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="translate(-92 -236)"> +<g id="hub_create_button_enabled"> +<g id="Oval Copy"> +<use xlink:href="#path0_fill" transform="translate(94 238)" fill="#2F80ED"/> +<use xlink:href="#path1_stroke" transform="translate(94 238)" fill="#FFFFFF"/> +</g> +<g id="Union"> +<use xlink:href="#path2_fill" transform="translate(112.7 255.567)" fill="#FFFFFF"/> +</g> +</g> +</g> +<defs> +<path id="path0_fill" fill-rule="evenodd" d="M 25.5 51C 39.5833 51 51 39.5833 51 25.5C 51 11.4167 39.5833 0 25.5 0C 11.4167 0 0 11.4167 0 25.5C 0 39.5833 11.4167 51 25.5 51Z"/> +<path id="path1_stroke" d="M 25.5 52.5C 40.4117 52.5 52.5 40.4117 52.5 25.5L 49.5 25.5C 49.5 38.7548 38.7548 49.5 25.5 49.5L 25.5 52.5ZM 52.5 25.5C 52.5 10.5883 40.4117 -1.5 25.5 -1.5L 25.5 1.5C 38.7548 1.5 49.5 12.2452 49.5 25.5L 52.5 25.5ZM 25.5 -1.5C 10.5883 -1.5 -1.5 10.5883 -1.5 25.5L 1.5 25.5C 1.5 12.2452 12.2452 1.5 25.5 1.5L 25.5 -1.5ZM -1.5 25.5C -1.5 40.4117 10.5883 52.5 25.5 52.5L 25.5 49.5C 12.2452 49.5 1.5 38.7548 1.5 25.5L -1.5 25.5Z"/> +<path id="path2_fill" fill-rule="evenodd" d="M 6.8 0L 15.3 7.64999L 6.8 15.3L 6.8 10.2L 0 10.2L 0 5.10001L 6.8 5.10001L 6.8 0Z"/> +</defs> +</svg> diff --git a/src/assets/images/logo.svg b/src/assets/images/logo.svg new file mode 100755 index 0000000000000000000000000000000000000000..43d6250ba602598561cd23813f5b63b9898f2df7 --- /dev/null +++ b/src/assets/images/logo.svg @@ -0,0 +1,73 @@ +<svg width="1101" height="150" viewBox="0 0 1101 150" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>logo</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="matrix(3 0 0 3 1473 588)"> +<g id="logo"> +<g id="Rectangle 2.1"> +<use xlink:href="#path0_fill" transform="translate(-491 -196)" fill="#FFFFFF"/> +</g> +<g id="moz://a"> +<use xlink:href="#path1_fill" transform="translate(-481 -202)"/> +</g> +<g id="Group 5.1"> +<g id="duck"> +<use xlink:href="#path2_fill" transform="translate(-311 -199)" fill="#FFFFFF"/> +</g> +<g id="Group 4"> +<g id="Group 2"> +<g id="noun_12039_cc"> +<g id="Subtract"> +<use xlink:href="#path3_fill" transform="translate(-191.254 -196)" fill="url(#paint3_linear)"/> +</g> +</g> +<g id="Ellipse"> +<use xlink:href="#path4_fill" transform="matrix(0.998739 0.0501978 -0.0492734 0.998785 -178.487 -187.814)"/> +</g> +<g id="Mask Group"> +<mask id="mask0_alpha" mask-type="alpha"> +<g id="Vector"> +<use xlink:href="#path5_fill" transform="translate(-198.5 -190.014)" fill="#C4C4C4"/> +</g> +</mask> +<g id="Vector" mask="url(#mask0_alpha)"> +<use xlink:href="#path6_fill" transform="translate(-191.254 -196)" fill="#FF8A00"/> +</g> +</g> +<g id="Ellipse"> +<use xlink:href="#path7_fill" transform="translate(-175 -186)" fill="#FFFFFF"/> +</g> +</g> +<g id="Group 4.1"> +<g id="Group 3"> +<g id="Subtract"> +<use xlink:href="#path8_fill" transform="translate(-203 -157.13)" fill="url(#paint8_radial)"/> +</g> +</g> +</g> +</g> +</g> +</g> +</g> +<defs> +<linearGradient id="paint3_linear" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(3.54163e-15 56.5272 -57.8393 3.46129e-15 57.8393 1.67757e-22)"> +<stop offset="0" stop-color="#FFC000"/> +<stop offset="1" stop-color="#FFD600"/> +</linearGradient> +<radialGradient id="paint8_radial" cx="0.5" cy="0.5" r="0.5" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-5 -160 111.805 -3.49389 -13.4023 140.377)"> +<stop offset="0" stop-color="#2F80ED" stop-opacity="0"/> +<stop offset="0.154696" stop-color="#2F80ED"/> +<stop offset="0.508287" stop-color="#2F80ED"/> +<stop offset="0.883978" stop-color="#2F80ED"/> +<stop offset="0.983425" stop-color="#2F80ED" stop-opacity="0.51"/> +</radialGradient> +<path id="path0_fill" d="M 0 0L 172 0L 172 49L 0 49L 0 0Z"/> +<path id="path1_fill" d="M 41.472 45L 32.4 45L 32.4 32.808C 32.4 30.952 32.08 29.624 31.44 28.824C 30.832 28.024 29.92 27.624 28.704 27.624C 27.232 27.624 26.16 28.104 25.488 29.064C 24.848 30.024 24.528 31.256 24.528 32.76L 24.528 40.344L 27.408 40.344L 27.408 45L 18.336 45L 18.336 32.808C 18.336 30.952 18.016 29.624 17.376 28.824C 16.768 28.024 15.856 27.624 14.64 27.624C 13.136 27.624 12.064 28.104 11.424 29.064C 10.784 30.024 10.464 31.256 10.464 32.76L 10.464 40.344L 14.592 40.344L 14.592 45L 1.392 45L 1.392 40.344L 4.272 40.344L 4.272 28.056L 1.44 28.056L 1.44 23.352L 10.464 23.352L 10.464 26.616C 11.84 24.152 14.032 22.92 17.04 22.92C 18.608 22.92 20.048 23.304 21.36 24.072C 22.672 24.84 23.584 26.008 24.096 27.576C 25.376 24.472 27.728 22.92 31.152 22.92C 33.104 22.92 34.832 23.528 36.336 24.744C 37.84 25.96 38.592 27.848 38.592 30.408L 38.592 40.344L 41.472 40.344L 41.472 45ZM 66.1909 34.2C 66.1909 37.624 65.0709 40.36 62.8309 42.408C 60.5909 44.456 57.7429 45.48 54.2869 45.48C 50.9589 45.48 48.2389 44.52 46.1269 42.6C 44.0469 40.648 43.0069 37.928 43.0069 34.44C 43.0069 31.272 43.9669 28.552 45.8869 26.28C 47.8069 24.008 50.7189 22.872 54.6229 22.872C 58.5269 22.872 61.4229 24.008 63.3109 26.28C 65.2309 28.52 66.1909 31.16 66.1909 34.2ZM 59.8069 34.008C 59.8069 31.8 59.2949 30.184 58.2709 29.16C 57.2469 28.136 55.9989 27.624 54.5269 27.624C 52.9269 27.624 51.6629 28.2 50.7349 29.352C 49.8389 30.472 49.3909 32.056 49.3909 34.104C 49.3909 35.96 49.8069 37.528 50.6389 38.808C 51.5029 40.088 52.7829 40.728 54.4789 40.728C 56.0789 40.728 57.3589 40.136 58.3189 38.952C 59.3109 37.736 59.8069 36.088 59.8069 34.008ZM 87.8119 45L 68.8999 45L 68.2759 41.736L 79.8919 28.008L 73.4119 28.008L 72.4519 31.32L 67.9879 30.936L 68.7559 23.352L 87.7639 23.352L 88.2439 26.616L 76.2919 40.344L 83.2519 40.344L 84.2599 36.936L 89.1559 37.416L 87.8119 45ZM 92.8789 31.128L 92.8789 23.352L 99.3109 23.352L 99.3109 31.128L 92.8789 31.128ZM 92.8789 45L 92.8789 37.224L 99.3109 37.224L 99.3109 45L 92.8789 45ZM 119.281 11.976L 109.921 45L 103.825 45L 113.185 11.976L 119.281 11.976ZM 131.562 11.976L 122.202 45L 116.106 45L 125.466 11.976L 131.562 11.976ZM 133.858 24.888C 135.746 24.12 137.314 23.608 138.562 23.352C 139.842 23.064 141.362 22.92 143.122 22.92C 145.458 22.92 147.474 23.528 149.17 24.744C 150.866 25.96 151.714 27.8 151.714 30.264L 151.714 39.672C 151.714 40.792 152.21 41.352 153.202 41.352C 153.49 41.352 153.794 41.304 154.114 41.208L 154.162 44.472C 152.914 45.144 151.618 45.48 150.274 45.48C 147.426 45.48 145.842 44.056 145.522 41.208L 145.522 41.16C 144.914 42.248 144.034 43.24 142.882 44.136C 141.762 45.032 140.322 45.48 138.562 45.48C 136.994 45.48 135.49 45.016 134.05 44.088C 132.61 43.16 131.89 41.56 131.89 39.288C 131.89 36.632 132.946 34.872 135.058 34.008C 137.202 33.144 139.506 32.712 141.97 32.712C 143.346 32.712 144.53 32.776 145.522 32.904L 145.522 32.184C 145.522 31.064 145.362 29.976 145.042 28.92C 144.754 27.864 143.73 27.336 141.97 27.336C 141.33 27.336 140.738 27.384 140.194 27.48C 139.682 27.544 139.17 27.704 138.658 27.96L 137.842 31.032L 132.898 30.504L 133.858 24.888ZM 145.522 36.168L 145.522 35.88C 145.01 35.816 144.482 35.752 143.938 35.688C 143.426 35.624 142.914 35.592 142.402 35.592C 141.314 35.592 140.354 35.8 139.522 36.216C 138.69 36.6 138.274 37.384 138.274 38.568C 138.274 39.272 138.466 39.864 138.85 40.344C 139.234 40.824 139.89 41.064 140.818 41.064C 141.906 41.064 142.914 40.68 143.842 39.912C 144.802 39.112 145.362 37.864 145.522 36.168Z"/> +<path id="path2_fill" d="M 23.32 42L 17.292 42L 17.292 37.952C 16.6467 39.1253 15.752 40.1667 14.608 41.076C 13.4933 41.9853 12.0413 42.44 10.252 42.44C 7.75867 42.44 5.73467 41.5893 4.18 39.888C 2.62533 38.1867 1.848 35.8253 1.848 32.804C 1.848 31.1027 2.12667 29.4307 2.684 27.788C 3.27067 26.1453 4.20933 24.7813 5.5 23.696C 6.79067 22.6107 8.52133 22.068 10.692 22.068C 12.0707 22.068 13.3467 22.376 14.52 22.992C 15.6933 23.608 16.6173 24.5027 17.292 25.676L 17.292 13.752L 12.364 13.752L 12.364 11.728L 19.712 11.728L 19.712 39.976L 23.32 39.976L 23.32 42ZM 17.292 33.684L 17.292 29.856C 17.2333 28.2427 16.588 26.908 15.356 25.852C 14.1533 24.7667 12.7307 24.224 11.088 24.224C 8.68267 24.224 6.96667 25.104 5.94 26.864C 4.91333 28.624 4.4 30.5453 4.4 32.628C 4.4 35.1213 5.00133 37.028 6.204 38.348C 7.40667 39.6387 8.91733 40.284 10.736 40.284C 12.5547 40.284 14.08 39.5507 15.312 38.084C 16.5733 36.6173 17.2333 35.1507 17.292 33.684ZM 47.6496 42L 41.5776 42L 41.5776 38.128C 40.9616 39.4187 40.0523 40.46 38.8496 41.252C 37.6469 42.044 36.2536 42.44 34.6696 42.44C 32.7336 42.44 31.1203 41.8387 29.8296 40.636C 28.5389 39.4333 27.8936 37.4973 27.8936 34.828L 27.8936 24.532L 24.2856 24.532L 24.2856 22.464L 30.3136 22.464L 30.3136 34.256C 30.3136 36.4853 30.7829 38.0547 31.7216 38.964C 32.6896 39.844 33.9069 40.284 35.3736 40.284C 37.1336 40.284 38.5856 39.5947 39.7296 38.216C 40.9029 36.8373 41.5189 35.444 41.5776 34.036L 41.5776 24.532L 37.2656 24.532L 37.2656 22.464L 43.9976 22.464L 43.9976 39.976L 47.6496 39.976L 47.6496 42ZM 66.8638 35.62C 66.5705 37.3213 65.7932 38.8907 64.5318 40.328C 63.2998 41.736 61.4078 42.44 58.8558 42.44C 56.1865 42.44 54.0745 41.56 52.5198 39.8C 50.9652 38.04 50.1878 35.62 50.1878 32.54C 50.1878 30.868 50.4958 29.2253 51.1118 27.612C 51.7278 25.9987 52.6812 24.6787 53.9718 23.652C 55.2918 22.596 56.9785 22.068 59.0318 22.068C 61.7012 22.068 63.8865 22.772 65.5878 24.18L 66.2918 28.536L 64.2678 28.8L 63.5198 25.5C 62.3172 24.6493 60.8212 24.224 59.0318 24.224C 56.7145 24.224 55.0865 25.06 54.1478 26.732C 53.2385 28.3747 52.7838 30.252 52.7838 32.364C 52.7838 34.8573 53.3265 36.808 54.4118 38.216C 55.4972 39.5947 57.0665 40.284 59.1198 40.284C 62.2292 40.284 64.1212 38.568 64.7958 35.136L 66.8638 35.62ZM 90.5792 42L 81.5592 42L 81.5592 39.976L 84.8152 39.976L 78.9632 32.584L 75.3112 32.584L 75.3112 39.976L 78.4352 39.976L 78.4352 42L 69.2832 42L 69.2832 39.976L 72.8912 39.976L 72.8912 13.752L 69.2392 13.752L 69.2392 11.728L 75.3112 11.728L 75.3112 30.648L 78.9192 30.648L 83.8032 24.532L 80.5912 24.532L 80.5912 22.464L 89.5232 22.464L 89.5232 24.532L 86.3552 24.532L 80.8112 31.396L 87.5432 39.976L 90.5792 39.976L 90.5792 42Z"/> +<path id="path3_fill" fill-rule="evenodd" d="M 50.1196 19.2305C 50.7549 18.1952 51.125 17.5921 51.7513 18.064C 57.8821 22.6814 59.8811 33.9351 55.4308 42.8152C 54.4341 44.8042 53.1743 46.5352 51.704 48.0339C 49.7701 47.0253 48.2661 45.5184 47.5038 43.7364C 46.093 47.0338 42.143 49.3891 37.6288 49.3891C 33.1145 49.3891 29.1645 47.0338 27.7538 43.7364C 26.343 47.0338 22.393 49.3891 17.8788 49.3891C 13.3645 49.3891 9.41447 47.0338 8.00375 43.7364C 7.26579 45.4613 5.83299 46.9284 3.98805 47.9354C 2.12418 45.2647 1.03558 42.0543 1.03558 38.4553C 1.03558 31.2486 5.3735 25.052 11.5934 22.2921C 5.61858 20.0395 0 16.3055 0 12.5564C 0 8.60062 3.68587 9.3717 8.2905 10.335C 8.38057 10.3539 8.47099 10.3728 8.56175 10.3917C 9.80632 4.4583 15.096 0 21.4376 0C 28.703 0 34.5916 5.85301 34.5916 13.0724C 34.5916 17.64 32.2312 21.6552 28.6587 23.9928C 31.9238 25.0827 35.7856 25.9041 40.3394 25.3748C 46.8108 24.6225 48.9302 21.1689 50.1196 19.2305Z"/> +<path id="path4_fill" d="M 7.05374 3.53287C 7.05374 5.48402 5.4747 7.06574 3.52687 7.06574C 1.57903 7.06574 0 5.48402 0 3.53287C 0 1.58172 1.57903 0 3.52687 0C 5.4747 0 7.05374 1.58172 7.05374 3.53287Z"/> +<path id="path5_fill" d="M 5.26992 15.2297C 4.44439 16.8291 3.88077 18.4665 3.52634 20.1083L 8.37531 42.9269C 8.79147 43.7115 8.912 43.9574 8.5 43.5137L 8.37531 42.9269C 6.85509 40.0607 1.3898 30.005 3.52634 20.1083L 0 3.5137L 12.7169 0C 19.3717 5.11528 19.4225 7.50551 18.8281 16.3028C 11.1147 18.292 8.0235 9.89461 5.26992 15.2297Z"/> +<path id="path6_fill" d="M 51.7513 18.064C 49.9525 16.7087 50.2674 24.2207 40.3395 25.3748C 35.7856 25.9041 31.9238 25.0827 28.6587 23.9928C 32.2312 21.6552 34.5916 17.64 34.5916 13.0724C 34.5916 5.85301 28.703 1.8757e-08 21.4376 1.8757e-08C 15.096 1.8757e-08 9.80632 4.4583 8.56176 10.3917C 3.83149 9.40368 -4.16361e-09 8.52324 -4.16361e-09 12.5564C -4.16361e-09 16.3055 5.61858 20.0395 11.5934 22.2921C 5.37351 25.052 1.03558 31.2486 1.03558 38.4553C 1.03558 48.2286 9.06296 55.1362 18.8443 56.152C 32.7329 57.5947 49.2091 55.231 55.4308 42.8152C 59.8811 33.9351 57.8821 22.6814 51.7513 18.064Z"/> +<path id="path7_fill" d="M 2 1C 2 1.55228 1.55228 2 1 2C 0.447715 2 0 1.55228 0 1C 0 0.447715 0.447715 0 1 0C 1.55228 0 2 0.447715 2 1Z"/> +<path id="path8_fill" fill-rule="evenodd" d="M 0 1.52588e-05L 0 4.86665C 1.41072 8.16408 5.36072 10.5194 9.875 10.5194C 14.3893 10.5194 18.3393 8.16408 19.75 4.86665C 21.1607 8.16408 25.1107 10.5194 29.625 10.5194C 34.1393 10.5194 38.0893 8.16408 39.5 4.86665C 40.9107 8.16408 44.8607 10.5194 49.375 10.5194C 53.8893 10.5194 57.8393 8.16408 59.25 4.86665C 60.6607 8.16408 64.6107 10.5194 69.125 10.5194C 73.6393 10.5194 77.5893 8.16408 79 4.86665L 79 0C 77.5893 3.29741 73.6393 5.65273 69.125 5.65273C 64.6107 5.65273 60.6607 3.29741 59.25 0C 57.8393 3.29741 53.8893 5.65273 49.375 5.65273C 44.8607 5.65273 40.9107 3.29741 39.5 0C 38.0893 3.29741 34.1393 5.65273 29.625 5.65273C 25.1107 5.65273 21.1607 3.29741 19.75 0C 18.3393 3.29742 14.3893 5.65273 9.875 5.65273C 5.36072 5.65273 1.41072 3.29742 0 1.52588e-05Z"/> +</defs> +</svg> diff --git a/src/assets/images/package.json b/src/assets/images/package.json deleted file mode 100644 index 0a5693e4ee3946b74a1a1e9632f9abb5ddbd5d35..0000000000000000000000000000000000000000 --- a/src/assets/images/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "moving-average": "^1.0.0" - } -} diff --git a/src/assets/images/webvr_cube.svg b/src/assets/images/webvr_cube.svg new file mode 100755 index 0000000000000000000000000000000000000000..4ccbc7fee2c47d58d80ff9b8c11b6007786508e6 --- /dev/null +++ b/src/assets/images/webvr_cube.svg @@ -0,0 +1,22 @@ +<svg width="30" height="35" viewBox="0 0 30 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<title>webvr_cube</title> +<desc>Created using Figma</desc> +<g id="Canvas" transform="translate(-269 391)"> +<g id="webvr_cube"> +<g id="Vector"> +<use xlink:href="#path0_fill" transform="translate(269.099 -382.765)" fill="#2F80ED"/> +</g> +<g id="Vector 4"> +<use xlink:href="#path1_fill" transform="translate(269 -391)" fill="#B8D5FC"/> +</g> +<g id="Vector 3"> +<use xlink:href="#path2_fill" transform="translate(283.882 -382.5)" fill="#6DA4ED"/> +</g> +</g> +</g> +<defs> +<path id="path0_fill" d="M 14.7831 8.69853L 0 0L 0 17.9118L 14.8325 26.7647L 14.7831 8.69853Z"/> +<path id="path1_fill" d="M 14.882 0L 30 8.5L 14.882 16.9338L 0 8.33823L 14.882 0Z"/> +<path id="path2_fill" d="M 15.1181 17.5L 0.0494418 26.5L 0.0494418 25.9338L 0 8.43381L 15.1181 0L 15.1181 17.5Z"/> +</defs> +</svg> diff --git a/src/assets/stylesheets/audio.scss b/src/assets/stylesheets/audio.scss index 93e819f7a356f8b946c1292ff0ccddb5c0c03d5a..67aac69962d861e993fb0e58e5dec9441536d2a9 100644 --- a/src/assets/stylesheets/audio.scss +++ b/src/assets/stylesheets/audio.scss @@ -4,103 +4,103 @@ flex: 10 1 auto; justify-content: flex-start; align-items: center; -} - -.audio-setup-panel__title { - @extend %top-title; -} - -.audio-setup-panel__subtitle { - @extend %top-subtitle; -} - -.audio-setup-panel__device-chooser { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - position: relative; -} - -.audio-setup-panel__enter-button { - @extend %bottom-button; -} - -.audio-setup-panel__device-chooser__dropdown { - @extend %rounded-border; - @extend %default-font; - - background-color: black; - padding: 6px; - color: white; - font-size: 1.1em; - width: 90%; -} - -.audio-setup-panel__device-chooser__mic-icon { - position: absolute; - left: 7.5%; - top: 10px; -} - -.audio-setup-panel__levels { - margin-top: 20px; - margin-bottom: 20px; - display: flex; - justify-content: space-evenly; - align-items: center; - width: 100%; -} - -.audio-setup-panel__levels__mic { - position:relative; - width: 111px; - height: 111px; -} - -.audio-setup-panel__levels__mic_icon { - position: absolute; - top: 0; - left: 0; - z-index: 2; - min-width: 111px; - min-height: 111px; -} - -.audio-setup-panel__levels__speaker { - position:relative; - width: 111px; - height: 111px; -} - -.audio-setup-panel__levels__speaker_icon { - position: absolute; - top: 0; - left: 0; - z-index: 2; - min-width: 111px; - min-height: 111px; -} - -.audio-setup-panel__levels__level { - position: absolute; - top: 0; - left: 0; - opacity: 1.0; - z-index: 1; -} - -.audio-setup-panel__hmd-mic-warning { - margin: 20px; -} - -.audio-setup-panel__hmd-mic-warning__label { - vertical-align: middle; - margin-left: 5px; -} - -.audio-setup-panel__hmd-mic-warning__icon { - vertical-align: middle; + + &__enter-button { + @extend %bottom-button; + } + + &__title { + @extend %top-title; + } + + &__subtitle { + @extend %top-subtitle; + } + + &__device-chooser { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; + + &__dropdown { + @extend %rounded-border; + @extend %default-font; + + background-color: black; + padding: 6px; + color: white; + font-size: 1.1em; + width: 90%; + } + + &__mic-icon { + position: absolute; + left: 7.5%; + top: 10px; + } + } + + &__levels { + margin-top: 20px; + margin-bottom: 20px; + display: flex; + justify-content: space-evenly; + align-items: center; + width: 100%; + + &__mic { + position:relative; + width: 111px; + height: 111px; + } + + &__mic_icon { + position: absolute; + top: 0; + left: 0; + z-index: 2; + min-width: 111px; + min-height: 111px; + } + + &__speaker { + position:relative; + width: 111px; + height: 111px; + } + + &__speaker_icon { + position: absolute; + top: 0; + left: 0; + z-index: 2; + min-width: 111px; + min-height: 111px; + } + + &__level { + position: absolute; + top: 0; + left: 0; + opacity: 1.0; + z-index: 1; + } + } + + &__hmd-mic-warning { + margin: 20px; + + &__label { + vertical-align: middle; + margin-left: 5px; + } + + &__icon { + vertical-align: middle; + } + } } .mic-grant-panel { @@ -109,26 +109,26 @@ flex: 10 1 auto; justify-content: flex-start; align-items: center; -} - -.mic-grant-panel__title { - @extend %top-title; -} - -.mic-grant-panel__subtitle { - @extend %top-subtitle; -} - -.mic-grant-panel__icon { - flex: 10; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; -} -.mic-grant-panel__next { - @extend %bottom-button; - margin: auto; - flex: 1 1 20px; + &__title { + @extend %top-title; + } + + &__subtitle { + @extend %top-subtitle; + } + + &__icon { + flex: 10; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + } + + &__next { + @extend %bottom-button; + margin: auto; + flex: 1 1 20px; + } } diff --git a/src/assets/stylesheets/avatar-selector.scss b/src/assets/stylesheets/avatar-selector.scss index 1663ec5b6ba92ef81c1b7fc9955f98dd0788272b..b3d20bea02eb7e17cebbbf220794aa5b3c305338 100644 --- a/src/assets/stylesheets/avatar-selector.scss +++ b/src/assets/stylesheets/avatar-selector.scss @@ -1,4 +1,3 @@ -@import 'fonts'; @import 'shared'; #selector-root { @@ -17,16 +16,10 @@ color: grey; } &__previous-button, &__next-button { + @extend %big-icon-button; position: absolute; top: 50%; margin-top: -0.5em; - appearance: none; - -moz-appearance: none; - -webkit-appearance: none; - background: transparent; - color: white; - border: none; - font-size: 64pt; } &__previous-button { left: 0.2em; diff --git a/src/assets/stylesheets/entry.scss b/src/assets/stylesheets/entry.scss index 2915f56da8f98f3fc79bda2b147d3750179c5dbc..bdd20d1ee7af717ac0b2808b696c85fe49c8d775 100644 --- a/src/assets/stylesheets/entry.scss +++ b/src/assets/stylesheets/entry.scss @@ -36,19 +36,20 @@ vertical-align: sub; margin: 0 0.6em } + &__screen-sharing-checkbox:checked { border: 9px double white; outline: 9px solid white; outline-offset: -18px; } -} -.entry-panel__secondary { - width: 100%; - text-align: center; - margin-top: 10px; - cursor: pointer; - color: $grey-text; + &__secondary { + width: 100%; + text-align: center; + margin-top: 10px; + cursor: pointer; + color: $grey-text; + } } .entry-button { @@ -57,20 +58,19 @@ margin-top: 10px; margin-bottom: 10px; cursor: pointer; -} -.entry-button__icon { - flex: 1 1 90px; - min-width: 90px; - min-height: 90px; -} + &__icon { + flex: 1 1 90px; + min-width: 90px; + min-height: 90px; + } -.entry-button__label { - flex: 10 1 auto; - margin-left: 20px; - font-size: 1.5em; - display: flex; - flex-direction: column; - justify-content: center; + &__label { + flex: 10 1 auto; + margin-left: 20px; + font-size: 1.5em; + display: flex; + flex-direction: column; + justify-content: center; + } } - diff --git a/src/assets/stylesheets/exited.scss b/src/assets/stylesheets/exited.scss index 341d382fecbe94680d7ffe8a4709c484074028f3..72959090e6cf5ed18d29c2750beb7bbb4280fcae 100644 --- a/src/assets/stylesheets/exited.scss +++ b/src/assets/stylesheets/exited.scss @@ -6,14 +6,14 @@ justify-content: center; align-items: center; flex-direction: column; -} -.exited-panel__title { - font-size: 1.2em; -} + &__title { + font-size: 1.2em; + } -.exited-panel__subtitle { - font-size: 0.8em; + &__subtitle { + font-size: 0.8em; + } } .autoexit-panel { @@ -23,19 +23,19 @@ justify-content: flex-start; align-items: center; padding: 15px; -} -.autoexit-panel__title { - @extend %top-title; -} - -.autoexit-panel__subtitle { - @extend %top-subtitle; -} + &__title { + @extend %top-title; + } + + &__subtitle { + @extend %top-subtitle; + } -.autoexit-panel__cancel-button { - @extend %bottom-button; - margin-top: 20px; - cursor: pointer; + &__cancel-button { + @extend %bottom-button; + margin-top: 20px; + cursor: pointer; + } } diff --git a/src/assets/stylesheets/fonts.scss b/src/assets/stylesheets/fonts.scss deleted file mode 100644 index 1ec1b6c12a0854b202b74f2a2f3d60ce9a3d517b..0000000000000000000000000000000000000000 --- a/src/assets/stylesheets/fonts.scss +++ /dev/null @@ -1,17 +0,0 @@ -/* latin-ext */ -@font-face { - font-family: 'Zilla Slab'; - font-style: normal; - font-weight: 400; - src: local('Zilla Slab'), local('ZillaSlab-Regular'), url('../fonts/zilla-slab_latin-ext.woff2') format('woff2'); - unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; -} - -/* latin */ -@font-face { - font-family: 'Zilla Slab'; - font-style: normal; - font-weight: 400; - src: local('Zilla Slab'), local('ZillaSlab-Regular'), url('../fonts/zilla-slab_latin.woff2') format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; -} diff --git a/src/assets/stylesheets/hub-create.scss b/src/assets/stylesheets/hub-create.scss new file mode 100644 index 0000000000000000000000000000000000000000..137483494fb0b2a99838b4ac20347432095b1792 --- /dev/null +++ b/src/assets/stylesheets/hub-create.scss @@ -0,0 +1,229 @@ +.create-panel { + display: flex; + flex-direction: column; + + @media (max-width: 768px) { + align-items: center; + } + + &__header { + color: $grey-text; + font-size: 1.2em; + margin-bottom: 14px; + margin-left: 12px; + text-shadow: 0px 0px 2px rgba(32, 32, 32, 1.0); + + @media (max-width: 768px) { + text-align: center; + } + } + + &__form { + position: relative; + width: 700px; + + @media (max-width: 768px) , (max-height: 715px) { + width: auto; + width: 500px; + } + + @media (max-width: 520px) { + width: 300px; + } + + &__name { + @extend %rounded-border; + @extend %default-font; + + color: white; + font-size: 2em; + background: black; + padding: 25px; + padding-left: 90px; + padding-right: 90px; + width: 100%; + line-height: 40px; + + &::selection { + background-color: #2F80ED; + color: white; + } + + &::-moz-selection { + background-color: #2F80ED; + color: white; + } + + @media (max-width: 768px) , (max-height: 715px) { + min-width: auto; + font-size: 1.5em; + width: 100%; + text-align: center; + } + + @media (max-width: 520px) { + padding-left: 15px; + font-size: 1.2em; + } + + &--expanded { + margin-top: 340px; + border-radius: 0px 0px 14px 14px; + + @media (max-width: 768px) , (max-height: 715px) { + margin-top: 275px; + } + + @media (max-width: 520px) { + margin-top: 165px; + } + } + } + + &__submit-button , &__rotate-button { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + background: transparent; + border: none; + cursor: pointer; + } + + &__left-container { + position: absolute; + height: 100%; + width: 90px; + height: 95px; + left: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + bottom: 0; + + @media (max-width: 520px) { + display: none; + } + } + + &__right-container { + position: absolute; + height: 95px; + width: 90px; + right: 4px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + bottom: 0; + } + + &__environment { + position: absolute; + top: 0px; + left: 0px; + width: 700px; + height: 100%; + box-sizing: border-box; + border-radius: 14px; + border: 3px solid white; + border-radius: 14px; + overflow: hidden; + pointer-events: none; + + @media (max-width: 768px) , (max-height: 715px) { + width: 100%; + } + + &__picker { + width: 100%; + height: 340px; + border-bottom: 3px solid white; + overflow: hidden; + position: relative; + + @media (max-width: 768px) , (max-height: 715px) { + height: 280px; + } + + @media (max-width: 520px) { + height: 165px; + } + + &__image { + width: 112%; + position: absolute; + top: -3%; + left: -3%; + } + + &__labels { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + + &__footer { + position: absolute; + bottom: 14px; + left: 12px; + font-size: 1.2em; + text-shadow: 0px 0px 6px #202020; + color: $light-text; + } + + &__header { + position: absolute; + top: 14px; + left: 18px; + display: flex; + flex-direction: column; + text-shadow: 0px 0px 3px #404040; + + &__title { + font-size: 1.6em; + font-weight: bold; + color: white; + } + + &__author { + color: $light-text; + font-size: 1.4em; + + @media (max-width: 520px) { + display: none; + } + } + } + } + + &__controls { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + + &__next, &__prev { + @extend %big-icon-button; + + position: absolute; + top: 50%; + margin-top: -0.5em; + pointer-events: auto; + cursor: pointer; + } + + &__prev { + left: 0.2em; + } + + &__next { + right: 0.2em; + } + } + } + } + } +} diff --git a/src/assets/stylesheets/room.scss b/src/assets/stylesheets/hub.scss similarity index 94% rename from src/assets/stylesheets/room.scss rename to src/assets/stylesheets/hub.scss index d042519b31409aa888dde3bbe83e69758fb1cb54..c10db8dd196ca6b3dce999605e002893cacd05e6 100644 --- a/src/assets/stylesheets/room.scss +++ b/src/assets/stylesheets/hub.scss @@ -1,4 +1,3 @@ -@import 'fonts'; @import 'shared'; @import 'loader'; diff --git a/src/assets/stylesheets/index.scss b/src/assets/stylesheets/index.scss new file mode 100644 index 0000000000000000000000000000000000000000..77615e9d341f4ca5688ebe6f0e209163f2c884cf --- /dev/null +++ b/src/assets/stylesheets/index.scss @@ -0,0 +1,219 @@ +@import 'shared'; +@import 'hub-create'; + +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + background-color: black; + color: white; +} + +.home-root { + @extend %default-font; + + width: 100%; + height: 100%; + margin: 0; + padding: 0; +} + +.home { + position: absolute; + display: flex; + width: 100%; + height: 100%; +} + +.main-content { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + z-index: 2; +} + +.background-video { + position: fixed; + top: 0; + left: 0; + opacity: 0.66; + min-width: 100%; + min-height: 100%; + z-index: 1; +} + +.header-content { + padding: 1.5em 2.5em 1.5em 2.5em; + background-color: rgba(0, 0, 0, 0.85); + min-height: 90px; + display: flex; + border-bottom: 2px solid #242424; + + &__title { + flex: 10; + display: flex; + + @media (max-width: 768px) { + justify-content: center; + } + + &__name { + width: 300px; + } + + &__preview { + color: $grey-text; + margin-left: 10px; + } + } + + &__experiment { + text-align: right; + flex: 1 1 350px; + color: $grey-text; + font-size: 1.0em; + font-weight: lighter; + + @media (max-width: 768px) { + display: none; + } + + &__container { + display: flex; + justify-content: flex-end; + } + + &__icon { + margin-left: 12px; + margin-right: 12px; + } + + &__info { + display: flex; + flex-direction: column; + justify-content: center; + + &__header { + a { + color: $grey-text; + } + } + + &__link { + color: $dark-grey; + font-size: 0.8em; + } + } + } +} + +.hero-content { + flex: 10; + min-height: 740px; + display: flex; + flex-direction: column; + + @media (max-width: 768px) { + padding: 1em 1.5em 1em 1.5em; + justify-content: space-around; + min-height: 490px; + } + + &__container { + padding-top: 2vw; + padding-left: 2.1em; + padding-right: 2.1em; + flex: 10; + text-shadow: 0px 0px 2px rgba(32, 32, 32, 1.0); + + @media (max-height: 812px) , (max-width: 768px) { + flex: 0 0 auto; + } + + @media (max-height: 720px) { + padding-bottom: 0px; + } + + &__title { + font-size: 4vw; + font-weight: bold; + + @media (max-width: 768px) , (max-height: 715px) { + font-size: 1.9em; + } + + @media (max-width: 768px) { + text-align: center; + } + + @media (min-width: 1824px) { + font-size: 4.5em; + } + } + + &__subtitle { + font-size: 2.5vw; + font-weight: lighter; + color: $light-text; + + @media (max-width: 768px) , (max-height: 715px) { + font-size: 1.1em; + margin-top: 0.2em; + } + + @media (max-width: 768px) { + text-align: center; + } + + @media (min-width: 1824px) { + font-size: 2.8em; + } + } + } + + &__create { + padding: 2.1em; + padding-bottom: 3.5vw; + + @media (max-width: 768px) { + padding: 0.5em; + align-self: center; + } + } +} + +.footer-content { + padding: 1em 2.25em 1em 2.25em; + background-color: rgba(0, 0, 0, 0.85); + min-height: 75px; + display: flex; + border-top: 2px solid #242424; + align-items: center; + justify-content: center; + + &__links { + text-align: center; + color: $dark-grey; + display: flex; + flex-direction: column; + + &__top { + display: flex; + justify-content: space-between; + } + + &__link { + color: $grey-text; + margin-left: 8px; + margin-right: 8px; + } + + &__bottom { + margin-top: 4px; + } + } +} diff --git a/src/assets/stylesheets/loader.scss b/src/assets/stylesheets/loader.scss index 400636ca8f4b7fb541ed62359b8f0b30238bb63e..a770b54d46a7a4126c69017b89257e343d66c4ce 100644 --- a/src/assets/stylesheets/loader.scss +++ b/src/assets/stylesheets/loader.scss @@ -5,6 +5,12 @@ } .loading-panel { + @extend %default-font; + pointer-events: none; + color: white; + position: absolute; + top: 0; + left: 0; background-color: black; width: 100%; height: 100%; diff --git a/src/assets/stylesheets/profile.scss b/src/assets/stylesheets/profile.scss index 9b45afd389dd5006d1596ee11d94f41a1ee59650..000e974bbad3aec3760eb51e9863c78755a590fc 100644 --- a/src/assets/stylesheets/profile.scss +++ b/src/assets/stylesheets/profile.scss @@ -15,83 +15,84 @@ height: 100%; margin: 1em 0; } -} -.profile-entry__box { - border-radius: 8px; - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; - padding: 15px; - flex: 1 1 100%; - width: 60vw; - min-width: 300px; - max-width: 700px; - height: 500px -} + &__box { + border-radius: 8px; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + padding: 15px; + flex: 1 1 100%; + width: 60vw; + min-width: 300px; + max-width: 700px; + height: 500px; -.profile-entry__box--darkened { - background-color: $darkest-transparent; -} + &--darkened { + background-color: $darkest-transparent; + } + } -.profile-entry__subtitle { - width: 100%; - text-align: center; - font-size: 1.2em; - color: $grey-text; -} + &__subtitle { + width: 100%; + text-align: center; + font-size: 1.2em; + color: $grey-text; + } -.profile-entry__form-field-text { - @extend %rounded-border; - @extend %default-font; + &__form-field-text { + @extend %rounded-border; + @extend %default-font; - color: $light-text; - font-size: 1.2em; - background-color: transparent; - line-height: 2.0em; - padding-left: 1.25em; - padding-right: 1.25em; - margin: 0.5em 0; -} + color: $light-text; + font-size: 1.2em; + background-color: transparent; + line-height: 2.0em; + padding-left: 1.25em; + padding-right: 1.25em; + margin: 0.5em 0; + } -.profile-entry__form-submit { - @extend %default-font; - border: none; + &__form-submit { + @extend %default-font; + border: none; - margin: 8px; - width: 100px; - line-height: 1.5em; - font-size: 1.0em; + margin: 8px; + width: 100px; + line-height: 1.5em; + font-size: 1.0em; - background-color: transparent; - font-weight: bold; - color: white; - cursor: pointer; + background-color: transparent; + font-weight: bold; + color: white; + cursor: pointer; + } } .profile-info-header { display: flex; flex: 1 1 40px; width: 100%; -} -.profile-info-header__icon { - cursor: pointer; - width: 20px; - height: 20px; - padding: 15px; -} + &__icon { + cursor: pointer; + width: 20px; + height: 20px; + padding: 15px; + } -.profile-info-header__profile_display_name { - cursor: pointer; - flex: 6 1 auto; - font-size: 1.2em; - line-height: 50px; -} + &__profile_display_name { + cursor: pointer; + flex: 6 1 auto; + font-size: 1.2em; + line-height: 50px; + } -.profile-info-header__app_name { - font-size: 1.8em; - padding-right: 18px; - line-height: 50px; + &__app_name { + font-size: 1.8em; + padding-right: 18px; + line-height: 50px; + } } + diff --git a/src/assets/stylesheets/shared.scss b/src/assets/stylesheets/shared.scss index a353915f5e8ec2e09a5c9ff79cadbd5aecd1732d..c2d4f013de5b853664b751400969602b356a53f9 100644 --- a/src/assets/stylesheets/shared.scss +++ b/src/assets/stylesheets/shared.scss @@ -33,3 +33,12 @@ $darker-grey: rgba(64, 64, 64, 1.0); padding-top: 4px; } +%big-icon-button { + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + background: transparent; + color: white; + border: none; + font-size: 64pt; +} diff --git a/src/assets/stylesheets/ui-root.scss b/src/assets/stylesheets/ui-root.scss index 74f4ad4a37f344162f1ee029a51fd5e0525e2728..debc2b188557353ab7ec2e081347e826d5a192c0 100644 --- a/src/assets/stylesheets/ui-root.scss +++ b/src/assets/stylesheets/ui-root.scss @@ -20,10 +20,10 @@ grid-template-rows: 1fr 20px minmax(400px, 600px) 20px 1fr; width: 100%; height: 100%; -} -.ui-dialog--darkened { - background-color: $dark-transparent; + &--darkened { + background-color: $dark-transparent; + } } .ui-dialog-box { @@ -37,17 +37,14 @@ border-radius: 8px; width: 100%; height: 100%; + + &--backgrounded { + filter: blur(1px); + opacity: 0.7; + pointer-events: none; + } } .ui-interactive { pointer-events: auto; } - -.ui-dialog-box--backgrounded { -} - -.ui-dialog-box-contents--backgrounded { - filter: blur(1px); - opacity: 0.7; - pointer-events: none; -} diff --git a/src/assets/translations.data.json b/src/assets/translations.data.json index 4c9af592fa7b15592af0961f4df84aaf3b1fe2d5..1757ec61cce5b97855750537a7812efe5349a57e 100644 --- a/src/assets/translations.data.json +++ b/src/assets/translations.data.json @@ -32,6 +32,20 @@ "autoexit.title": "Auto-ending session in ", "autoexit.title_units": " seconds", "autoexit.subtitle": "You have started another session.", - "autoexit.cancel": "CANCEL" + "autoexit.cancel": "CANCEL", + "home.create_header": "Name your room:", + "home.environment_picker_footer": "Choose a scene", + "home.create_name.validation_warning": "Invalid name, limited to 4 to 64 characters and limited symbols.", + "home.webvr_disclaimer_pre": "A ", + "home.webvr_disclaimer_post": " experiment by ", + "home.webvr_disclaimer_mr_team": "Mozilla Mixed Reality", + "home.view_source": "View Source", + "home.join_on_slack": "Join us on Slack", + "home.report_issue": "Report an Issue", + "home.get_updates": "Get Updates", + "home.hero_title": "A new way to get together online.", + "home.hero_subtitle": "Laugh, play, get stuff done, or just hang out.", + "home.made_with_love": "made with â¤ï¸ by ", + "home.environment_author_by": " by " } } diff --git a/src/assets/video/home.webm b/src/assets/video/home.webm new file mode 100644 index 0000000000000000000000000000000000000000..d7156cad9530c12a8b0b3f31332cfebda0f4cea9 Binary files /dev/null and b/src/assets/video/home.webm differ diff --git a/src/components/gltf-bundle.js b/src/components/gltf-bundle.js new file mode 100644 index 0000000000000000000000000000000000000000..791fa7eef9076b44eda996192181dc488e755846 --- /dev/null +++ b/src/components/gltf-bundle.js @@ -0,0 +1,29 @@ +AFRAME.registerComponent("gltf-bundle", { + schema: { + src: { default: "" } + }, + + init: async function() { + this._addGltfEntitiesForBundleJson = this._addGltfEntitiesForBundleJson.bind(this); + + const res = await fetch(this.data.src); + const data = await res.json(); + this._addGltfEntitiesForBundleJson(data); + }, + + _addGltfEntitiesForBundleJson: function(bundleJson) { + const loaded = []; + + for (let i = 0; i < bundleJson.assets.length; i++) { + const asset = bundleJson.assets[i]; + const src = asset.src; + const gltfEl = document.createElement("a-gltf-entity"); + gltfEl.setAttribute("src", src); + gltfEl.setAttribute("position", "0 0 0"); + loaded.push(new Promise(resolve => gltfEl.addEventListener("model-loaded", resolve))); + this.el.appendChild(gltfEl); + } + + Promise.all(loaded).then(() => this.el.emit("bundleloaded")); + } +}); diff --git a/src/room.html b/src/hub.html similarity index 91% rename from src/room.html rename to src/hub.html index 5fc6c309b438a3e7788abb92ff346bdb0ee42754..fd276abaec43666e9f57842b8e96a0da8c6b1ead 100644 --- a/src/room.html +++ b/src/hub.html @@ -3,8 +3,9 @@ <head> <meta charset="utf-8"> - <title>Mozilla Mixed Reality Social Client</title> + <title>moz://a duck</title> + <meta name="viewport" content="width=device-width, initial-scale=1"> <meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="<%= ORIGIN_TRIAL_EXPIRES %>" content="<%= ORIGIN_TRIAL_TOKEN %>"> <% if(NODE_ENV === "production") { %> <script src="https://cdn.rawgit.com/brianpeiris/aframe/845825ae694449524c185c44a314d361eead4680/dist/aframe-master.min.js"></script> @@ -93,11 +94,6 @@ ></a-progressive-asset> <a-asset-item id="watch-model" response-type="arraybuffer" src="./assets/hud/watch.glb"></a-asset-item> - - <a-asset-item id="meeting-space1-mesh" response-type="arraybuffer" src="./assets/environments/MeetingSpace1_mesh.glb"></a-asset-item> - <a-asset-item id="outdoor-facade-mesh" response-type="arraybuffer" src="./assets/environments/OutdoorFacade_mesh.glb"></a-asset-item> - <a-asset-item id="floor-nav-mesh" response-type="arraybuffer" src="./assets/environments/FloorNav_mesh.glb"></a-asset-item> - <a-asset-item id="cliff-vista-mesh" response-type="arraybuffer" src="./assets/environments/CliffVista_mesh.glb"></a-asset-item> <a-asset-item id="interactable-duck" response-type="arraybuffer" src="./assets/interactables/duck/DuckyMesh.glb"></a-asset-item> <img id="water-normal-map" src="./assets/waternormals.jpg"></a-asset-item> @@ -328,34 +324,7 @@ ></a-entity> <!-- Environment --> - <a-gltf-entity - id="meeting-space" - src="#meeting-space1-mesh" - position="0 0 0" - ></a-gltf-entity> - - <a-gltf-entity - id="outdoor-facade" - src="#outdoor-facade-mesh" - position="0 0 0" - xr="ar: false" - ></a-gltf-entity> - - <a-gltf-entity - id="floor-nav" - src="#floor-nav-mesh" - visible="false" - position="0 0 0" - xr="ar: false" - ></a-gltf-entity> - - <a-gltf-entity - id="cliff-vista" - src="#cliff-vista-mesh" - layers="reflection:true" - position="0 0 0" - xr="ar: false" - ></a-gltf-entity> + <a-entity id="environment-root" position="0 0 0"/> <a-entity id="skybox" id="skybox" diff --git a/src/room.js b/src/hub.js similarity index 82% rename from src/room.js rename to src/hub.js index 232bc18accb2d4150f3213e09f1cbaac5d0c4d47..887e470250fd224c616ec66e8f53e2ceaea703fe 100644 --- a/src/room.js +++ b/src/hub.js @@ -1,4 +1,4 @@ -import "./assets/stylesheets/room.scss"; +import "./assets/stylesheets/hub.scss"; import queryString from "query-string"; import { patchWebGLRenderingContext } from "./utils/webgl"; @@ -41,6 +41,7 @@ import "./components/player-info"; import "./components/debug"; import "./components/animation-mixer"; import "./components/loop-animation"; +import "./components/gltf-bundle"; import ReactDOM from "react-dom"; import React from "react"; @@ -102,6 +103,7 @@ AFRAME.registerInputMappings(inputConfig, true); const store = new Store(); const concurrentLoadDetector = new ConcurrentLoadDetector(); + concurrentLoadDetector.start(); // Always layer in any new default profile bits @@ -117,12 +119,12 @@ function applyProfileFromStore(playerRig) { const displayName = store.state.profile.display_name; playerRig.setAttribute("player-info", { displayName, - avatarSrc: '#' + (store.state.profile.avatar_id || "botdefault") + avatarSrc: "#" + (store.state.profile.avatar_id || "botdefault") }); document.querySelector("a-scene").emit("username-changed", { username: displayName }); } -async function enterScene(mediaStream, enterInVR) { +async function enterScene(mediaStream, enterInVR, janusRoomId) { const scene = document.querySelector("a-scene"); const playerRig = document.querySelector("#player-rig"); document.querySelector("a-scene canvas").classList.remove("blurred"); @@ -134,12 +136,14 @@ async function enterScene(mediaStream, enterInVR) { AFRAME.registerInputActions(inGameActions, "default"); + document.querySelector("#player-camera").setAttribute("look-controls"); + scene.setAttribute("networked-scene", { adapter: "janus", audio: true, debug: true, connectOnLoad: false, - room: qs.room && !isNaN(parseInt(qs.room, 10)) ? parseInt(qs.room, 10) : 1, + room: janusRoomId, serverURL: process.env.JANUS_SERVER }); @@ -173,8 +177,7 @@ async function enterScene(mediaStream, enterInVR) { for (const track of videoTracks) { mediaStream.addTrack(track); } - } - else { + } else { for (const track of mediaStream.getVideoTracks()) { mediaStream.removeTrack(track); } @@ -214,7 +217,6 @@ async function enterScene(mediaStream, enterInVR) { function onConnect() {} function mountUI(scene) { - const qs = queryString.parse(location.search); const disableAutoExitOnConcurrentLoad = qsTruthy("allow_multi"); const forcedVREntryType = qs.vr_entry_type || null; const enableScreenSharing = qsTruthy("enable_screen_sharing"); @@ -235,17 +237,43 @@ function mountUI(scene) { document.getElementById("ui-root") ); - getAvailableVREntryTypes().then(availableVREntryTypes => { - uiRoot.setState({ availableVREntryTypes }); - uiRoot.handleForcedVREntryType(); - }); + return uiRoot; } -const onReady = () => { +const onReady = async () => { const scene = document.querySelector("a-scene"); document.querySelector("a-scene canvas").classList.add("blurred"); window.APP.scene = scene; - mountUI(scene); + + const uiRoot = mountUI(scene); + + getAvailableVREntryTypes().then(availableVREntryTypes => { + uiRoot.setState({ availableVREntryTypes }); + uiRoot.handleForcedVREntryType(); + }); + + const environmentRoot = document.querySelector("#environment-root"); + + const initialEnvironmentEl = document.createElement("a-entity"); + initialEnvironmentEl.addEventListener("bundleloaded", () => uiRoot.setState({ initialEnvironmentLoaded: true })); + environmentRoot.appendChild(initialEnvironmentEl); + + 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 }); + initialEnvironmentEl.setAttribute("gltf-bundle", "src: /assets/environments/cliff_meeting_space/bundle.json"); + return; + } + + const hubId = document.location.pathname.substring(1).split("/")[0]; + console.log(`Hub ID: ${hubId}`); + const res = await fetch(`/api/v1/hubs/${hubId}`); + const data = await res.json(); + 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 }); + initialEnvironmentEl.setAttribute("gltf-bundle", `src: ${gltfBundleUrl}`); }; document.addEventListener("DOMContentLoaded", onReady); diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000000000000000000000000000000000000..6e0d03c001627862dcba3b8e3db3e991afc29a4e --- /dev/null +++ b/src/index.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> + +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>moz://a duck</title> + <link href="https://fonts.googleapis.com/css?family=Zilla+Slab:300,300i,400,400i,700" rel="stylesheet"> +</head> + +<body> + <div id="home-root" class="home-root"></div> +</body> + +</html> diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000000000000000000000000000000000000..2518b42dd56390078e56b04220ed780ab6abe707 --- /dev/null +++ b/src/index.js @@ -0,0 +1,7 @@ +import "./assets/stylesheets/index.scss"; +import React from "react"; +import ReactDOM from "react-dom"; +import HomeRoot from "./react-components/home-root"; +import registerTelemetry from "./telemetry"; + +ReactDOM.render(<HomeRoot />, document.getElementById("home-root")); diff --git a/src/lobby.css b/src/lobby.css deleted file mode 100644 index 539c8ab7976b745447203a281529e1aa6c80ef00..0000000000000000000000000000000000000000 --- a/src/lobby.css +++ /dev/null @@ -1,58 +0,0 @@ -* { - box-sizing: border-box; -} - -body { - margin: 0; - padding: 0; - background: black url(./assets/background.jpg) no-repeat left center; - background-size: cover; -} - -.overlay { - display: flex; - background: rgba(0, 0, 0, 0.4); - width: 100vw; - height: 100vh; - align-items: center; - padding: 100px 50px; -} - -.panel { - height: 100%; - display: flex; -} - -.scroll { - flex: 1; - overflow-y: auto; -} - -.mdl-list { - margin: 0; -} - -.room-item { - padding: 0; -} - -.room-item a { - width: 100%; - height: 100%; - padding: 16px; - color: inherit; - text-decoration: none; -} - -.room-item a:hover { - background: #eaeaea; -} - -@media only screen and (max-width: 320px) { - .overlay { - padding: 0; - } - .panel { - width: 100%; - } -} diff --git a/src/lobby.html b/src/lobby.html deleted file mode 100644 index 3fd52acf4da53f06c6fb91a19a62b3f89339f01c..0000000000000000000000000000000000000000 --- a/src/lobby.html +++ /dev/null @@ -1,14 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Mozilla Mixed Reality Social Client Lobby</title> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - - <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> - </head> - <body> - <div id="root"></div> - </body> -</html> diff --git a/src/lobby.js b/src/lobby.js deleted file mode 100644 index c3c9a6baed6d3da99508d08a8dd3b37b148cfd58..0000000000000000000000000000000000000000 --- a/src/lobby.js +++ /dev/null @@ -1,116 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import { JanusSession, JanusPluginHandle } from "minijanus"; - -import "material-design-lite"; -import "material-design-lite/material.css"; -import "./lobby.css"; -import "webrtc-adapter"; - -import registerTelemetry from "./telemetry"; - -const publicRooms = [1, 2, 3, 4, 5]; - -registerTelemetry(); - -class Lobby extends React.Component { - constructor() { - super(); - this.state = { rooms: [] }; - - this.onWebsocketOpen = this.onWebsocketOpen.bind(this); - this.onWebsocketMessage = this.onWebsocketMessage.bind(this); - this.updateRooms = this.updateRooms.bind(this); - } - - componentDidMount() { - this.ws = new WebSocket(process.env.JANUS_SERVER, "janus-protocol"); - this.session = new JanusSession(this.ws.send.bind(this.ws)); - this.ws.addEventListener("open", this.onWebsocketOpen); - this.ws.addEventListener("message", this.onWebsocketMessage); - } - - componentWillUnmount() { - clearInterval(this.pollRoomsIntervalHandle); - this.ws.removeEventListener("open", this.onWebsocketOpen); - this.ws.removeEventListener("message", this.onWebsocketMessage); - } - - onWebsocketOpen() { - this.session - .create() - .then(() => { - this.handle = new JanusPluginHandle(this.session); - return this.handle.attach("janus.plugin.sfu").then(this.updateRooms); - }) - .then(() => { - this.pollRoomsIntervalHandle = setInterval(this.updateRooms, 10000); - }); - } - - updateRooms() { - return this.fetchRooms().then(rooms => this.setState({ rooms })); - } - - fetchRooms() { - return this.handle.sendMessage({ kind: "listusers" }).then(signal => { - const usersByRoom = signal.plugindata.data.response.users; - return publicRooms.map(id => ({ - id, - limit: 12, - users: usersByRoom[id] || [] - })); - }); - } - - onWebsocketMessage(event) { - this.session.receive(JSON.parse(event.data)); - } - - render() { - return ( - <div className="overlay"> - <RoomList rooms={this.state.rooms} /> - </div> - ); - } -} - -const RoomListItem = ({ room }) => { - return ( - <li className="room-item mdl-list__item mdl-list__item--two-line"> - <a href={`room.html?room=${room.id}`}> - <span className="mdl-list__item-primary-content"> - <i className="material-icons mdl-list__item-icon">room</i> - <span>Meeting room {room.id}</span> - <span className="mdl-list__item-sub-title"> - {room.users.length}/{room.limit} - </span> - </span> - </a> - </li> - ); -}; - -const RoomList = ({ rooms }) => { - const roomId = - publicRooms.length + 1 + Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - publicRooms.length + 1)); - - return ( - <div className="mdl-card mdl-shadow--2dp panel"> - <ul className="mdl-list scroll">{rooms.map(room => <RoomListItem key={room.id} room={room} />)}</ul> - <ul className="mdl-list"> - <li className="mdl-list__item room-item"> - <a href={`room.html?room=${roomId}`}> - <span className="mdl-list__item-primary-content"> - <i className="material-icons mdl-list__item-icon">add</i> - New Meeting Room - </span> - </a> - </li> - </ul> - </div> - ); -}; - -ReactDOM.render(<Lobby />, document.getElementById("root")); diff --git a/src/onboarding.css b/src/onboarding.css deleted file mode 100644 index c3332df4090424929d76fa27159646a43972ee3e..0000000000000000000000000000000000000000 --- a/src/onboarding.css +++ /dev/null @@ -1,15 +0,0 @@ -* { - box-sizing: border-box; -} - -body { - margin: 0; - padding: 0; -} - -:local(.onboarding) { - display: flex; - flex: 1; - margin: 20px; - flex-direction: column; -} diff --git a/src/onboarding.html b/src/onboarding.html deleted file mode 100644 index cda90ad3c0623819574f4827d25af2447ac2b5d1..0000000000000000000000000000000000000000 --- a/src/onboarding.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Mozilla Mixed Reality Social Client Lobby</title> - <meta charset="utf-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - </head> - <body> - <div id="root"></div> - </body> -</html> diff --git a/src/onboarding.js b/src/onboarding.js deleted file mode 100644 index a3d25c27b1e1b6fbbfdcd0cc432b345ca2e79a75..0000000000000000000000000000000000000000 --- a/src/onboarding.js +++ /dev/null @@ -1,51 +0,0 @@ -import ReactDOM from "react-dom"; -import React from "react"; -import { HashRouter as Router, Route, Link } from "react-router-dom"; -import styles from "./onboarding.css"; - -const Onboarding = () => ( - <Router basename=""> - <div className={styles.onboarding}> - <Link to="/">Start Over</Link> - - <hr /> - - <Route exact path="/" component={Landing} /> - <Route path="/step1" component={Step1} /> - <Route path="/step2" component={Step2} /> - <Route path="/step3" component={Step3} /> - </div> - </Router> -); - -const Landing = () => ( - <div> - <h2>Landing</h2> - <Link to="/step1">Get Started</Link> - </div> -); - -const Step1 = () => ( - <div> - <h2>Step 1</h2> - <Link to="/step2">Next</Link> - </div> -); - -const Step2 = () => ( - <div> - <h2>Step 2</h2> - <Link to="/step1">Back</Link> - <Link to="/step3">Next</Link> - </div> -); - -const Step3 = () => ( - <div> - <h2>Step 3</h2> - <Link to="/step2">Back</Link> - <a href="/room.html?room=1">Create Room</a> - </div> -); - -ReactDOM.render(<Onboarding />, document.getElementById("root")); diff --git a/src/react-components/avatar-selector.js b/src/react-components/avatar-selector.js index 7cf71b7c5e130c2bbd16a54e5b247f3a1cea74d5..6ce9a8a172726bb1b6d6194e13d5f88aa29185b5 100644 --- a/src/react-components/avatar-selector.js +++ b/src/react-components/avatar-selector.js @@ -1,49 +1,49 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { injectIntl, FormattedMessage } from 'react-intl'; -import FontAwesomeIcon from '@fortawesome/react-fontawesome'; -import faAngleLeft from '@fortawesome/fontawesome-free-solid/faAngleLeft'; -import faAngleRight from '@fortawesome/fontawesome-free-solid/faAngleRight'; -import meetingSpace from '../assets/environments/MeetingSpace1_mesh.glb'; +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { injectIntl, FormattedMessage } from "react-intl"; +import FontAwesomeIcon from "@fortawesome/react-fontawesome"; +import faAngleLeft from "@fortawesome/fontawesome-free-solid/faAngleLeft"; +import faAngleRight from "@fortawesome/fontawesome-free-solid/faAngleRight"; +import meetingSpace from "../assets/environments/cliff_meeting_space/MeetingSpace1_mesh.glb"; class AvatarSelector extends Component { static propTypes = { avatars: PropTypes.array, avatarId: PropTypes.string, - onChange: PropTypes.func, - } + onChange: PropTypes.func + }; - getAvatarIndex = (direction=0) => { + getAvatarIndex = (direction = 0) => { const currAvatarIndex = this.props.avatars.findIndex(avatar => avatar.id === this.props.avatarId); const numAvatars = this.props.avatars.length; return ((currAvatarIndex + direction) % numAvatars + numAvatars) % numAvatars; - } - nextAvatarIndex = () => this.getAvatarIndex(1) - previousAvatarIndex = () => this.getAvatarIndex(-1) + }; + nextAvatarIndex = () => this.getAvatarIndex(1); + previousAvatarIndex = () => this.getAvatarIndex(-1); emitChangeToNext = () => { const nextAvatarId = this.props.avatars[this.nextAvatarIndex()].id; this.props.onChange(nextAvatarId); - } + }; emitChangeToPrevious = () => { const previousAvatarId = this.props.avatars[this.previousAvatarIndex()].id; this.props.onChange(previousAvatarId); - } + }; componentDidUpdate(prevProps) { - if (this.props.avatarId !== prevProps.avatarId) { + if (this.props.avatarId !== prevProps.avatarId) { // HACK - a-animation ought to restart the animation when the `to` attribute changes, but it doesn't // so we need to force it here. - const currRot = this.animation.parentNode.getAttribute('rotation'); - this.animation.setAttribute('from', `${currRot.x} ${currRot.y} ${currRot.z}`); + const currRot = this.animation.parentNode.getAttribute("rotation"); + this.animation.setAttribute("from", `${currRot.x} ${currRot.y} ${currRot.z}`); this.animation.stop(); this.animation.handleMixinUpdate(); this.animation.start(); } } - render () { + render() { const avatarAssets = this.props.avatars.map(avatar => ( <a-progressive-asset id={avatar.id} @@ -51,74 +51,63 @@ class AvatarSelector extends Component { response-type="arraybuffer" high-src={`${avatar.models.high}`} low-src={`${avatar.models.low}`} - ></a-progressive-asset> + /> )); const avatarEntities = this.props.avatars.map((avatar, i) => ( <a-entity key={avatar.id} position="0 0 0" rotation={`0 ${360 * -i / this.props.avatars.length} 0`}> - <a-gltf-entity position="0 0 5" rotation="0 0 0" src={'#' + avatar.id} inflate="true"> + <a-gltf-entity position="0 0 5" rotation="0 0 0" src={"#" + avatar.id} inflate="true"> <template data-selector=".RootScene"> - <a-entity animation-mixer></a-entity> + <a-entity animation-mixer /> </template> <a-animation attribute="rotation" dur="2000" to={`0 ${this.getAvatarIndex() === i ? 360 : 0} 0`} - repeat="indefinite"> - </a-animation> + repeat="indefinite" + /> </a-gltf-entity> </a-entity> )); return ( <div className="avatar-selector"> - <span className="avatar-selector__loading"> - <FormattedMessage id="profile.avatar-selector.loading"/> - </span> - <a-scene vr-mode-ui="enabled: false" ref={sce => this.scene = sce}> - <a-assets> - {avatarAssets} - <a-asset-item - id="meeting-space1-mesh" - response-type="arraybuffer" - src={meetingSpace} - ></a-asset-item> - </a-assets> + <span className="avatar-selector__loading"> + <FormattedMessage id="profile.avatar-selector.loading" /> + </span> + <a-scene vr-mode-ui="enabled: false" ref={sce => (this.scene = sce)}> + <a-assets> + {avatarAssets} + <a-asset-item id="meeting-space1-mesh" response-type="arraybuffer" src={meetingSpace} /> + </a-assets> - <a-entity> - <a-animation - ref={anm => this.animation = anm} - attribute="rotation" - dur="1000" - easing="ease-out" - to={`0 ${360 * this.getAvatarIndex() / this.props.avatars.length + 180} 0`}> - </a-animation> - {avatarEntities} - </a-entity> + <a-entity> + <a-animation + ref={anm => (this.animation = anm)} + attribute="rotation" + dur="1000" + easing="ease-out" + to={`0 ${360 * this.getAvatarIndex() / this.props.avatars.length + 180} 0`} + /> + {avatarEntities} + </a-entity> - <a-entity position="0 1.5 -5.6" rotation="-10 180 0" camera></a-entity> + <a-entity position="0 1.5 -5.6" rotation="-10 180 0" camera /> - <a-entity - hide-when-quality="low" - light="type: directional; color: #F9FFCE; intensity: 0.6" - position="0 5 -15" - ></a-entity> - <a-entity - hide-when-quality="low" - light="type: ambient; color: #FFF" - ></a-entity> - <a-gltf-entity - id="meeting-space" - src="#meeting-space1-mesh" - position="0 0 0" - ></a-gltf-entity> - </a-scene> - <button className="avatar-selector__previous-button" onClick={this.emitChangeToPrevious}> - <FontAwesomeIcon icon={faAngleLeft} /> - </button> - <button className="avatar-selector__next-button" onClick={this.emitChangeToNext}> - <FontAwesomeIcon icon={faAngleRight} /> - </button> + <a-entity + hide-when-quality="low" + light="type: directional; color: #F9FFCE; intensity: 0.6" + position="0 5 -15" + /> + <a-entity hide-when-quality="low" light="type: ambient; color: #FFF" /> + <a-gltf-entity id="meeting-space" src="#meeting-space1-mesh" position="0 0 0" /> + </a-scene> + <button className="avatar-selector__previous-button" onClick={this.emitChangeToPrevious}> + <FontAwesomeIcon icon={faAngleLeft} /> + </button> + <button className="avatar-selector__next-button" onClick={this.emitChangeToNext}> + <FontAwesomeIcon icon={faAngleRight} /> + </button> </div> ); } diff --git a/src/react-components/home-root.js b/src/react-components/home-root.js new file mode 100644 index 0000000000000000000000000000000000000000..332904b9db9fd29ecb8b57f6e929cf07127d78f3 --- /dev/null +++ b/src/react-components/home-root.js @@ -0,0 +1,138 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import classNames from "classnames"; +import queryString from "query-string"; +import { IntlProvider, injectIntl, FormattedMessage, addLocaleData } from "react-intl"; +import en from "react-intl/locale-data/en"; +import homeVideo from "../assets/video/home.webm"; + +import HubCreatePanel from "./hub-create-panel.js"; + +const navigatorLang = (navigator.languages && navigator.languages[0]) || navigator.language || navigator.userLanguage; + +const lang = navigatorLang.toLowerCase().split(/[_-]+/)[0]; + +import localeData from "../assets/translations.data.json"; +addLocaleData([...en]); + +const messages = localeData[lang] || localeData.en; + +const ENVIRONMENT_URLS = [ + `${document.location.protocol}//${document.location.host}/assets/environments/cliff_meeting_space/bundle.json` +]; + +class HomeRoot extends Component { + static propTypes = { + intl: PropTypes.object + }; + + state = { + environments: [] + }; + + componentDidMount() { + this.loadEnvironments(); + document.querySelector("#background-video").playbackRate = 0.5; + } + + loadEnvironments = () => { + const environments = []; + + const environmentLoads = ENVIRONMENT_URLS.map(src => + (async () => { + const res = await fetch(src); + const data = await res.json(); + data.bundle_url = src; + environments.push(data); + })() + ); + + Promise.all(environmentLoads).then(() => this.setState({ environments })); + }; + + render() { + return ( + <IntlProvider locale={lang} messages={messages}> + <div className="home"> + <div className="main-content"> + <div className="header-content"> + <div className="header-content__title"> + <img className="header-content__title__name" src="../assets/images/logo.svg" /> + <div className="header-content__title__preview">preview</div> + </div> + <div className="header-content__experiment"> + <div className="header-content__experiment__container"> + <img src="../assets/images/webvr_cube.svg" className="header-content__experiment__icon" /> + <div className="header-content__experiment__info"> + <div className="header-content__experiment__info__header"> + <span> + <FormattedMessage id="home.webvr_disclaimer_pre" /> + </span> + <span style={{ fontWeight: "bold" }}>WebVR</span> + <span> + <FormattedMessage id="home.webvr_disclaimer_post" /> + </span> + <span> + <a rel="noopener noreferrer" target="_blank" href="https://blog.mozvr.com"> + <FormattedMessage id="home.webvr_disclaimer_mr_team" /> + </a> + </span> + </div> + + <div> + <a + className="header-content__experiment__info__link" + rel="noopener noreferrer" + target="_blank" + href="https://github.com/mozilla/mr-social-client" + > + <FormattedMessage id="home.view_source" /> + </a> + </div> + </div> + </div> + </div> + </div> + <div className="hero-content"> + <div className="hero-content__container"> + <div className="hero-content__container__title"> + <FormattedMessage id="home.hero_title" /> + </div> + <div className="hero-content__container__subtitle"> + <FormattedMessage id="home.hero_subtitle" /> + </div> + </div> + <div className="hero-content__create"> + {this.state.environments.length > 0 && <HubCreatePanel environments={this.state.environments} />} + </div> + </div> + <div className="footer-content"> + <div className="footer-content__links"> + <div className="footer-content__links__top"> + <a className="footer-content__links__link" rel="noopener noreferrer" target="_blank" href="#"> + <FormattedMessage id="home.join_on_slack" /> + </a> + <a className="footer-content__links__link" rel="noopener noreferrer" target="_blank" href="#"> + <FormattedMessage id="home.get_updates" /> + </a> + <a className="footer-content__links__link" rel="noopener noreferrer" target="_blank" href="#"> + <FormattedMessage id="home.report_issue" /> + </a> + </div> + <div className="footer-content__links__bottom"> + <FormattedMessage id="home.made_with_love" /> + <span style={{ fontWeight: "bold", color: "white" }}>moz://a</span> + </div> + </div> + </div> + </div> + <video playsInline autoPlay muted loop className="background-video" id="background-video"> + <source src={homeVideo} type="video/webm" /> + </video> + </div> + </IntlProvider> + ); + } +} + +export default HomeRoot; diff --git a/src/react-components/hub-create-panel.js b/src/react-components/hub-create-panel.js new file mode 100644 index 0000000000000000000000000000000000000000..f117ead03f85bc0116619e14c2c3f3d7505b8ba5 --- /dev/null +++ b/src/react-components/hub-create-panel.js @@ -0,0 +1,189 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { injectIntl, FormattedMessage } from "react-intl"; +import { generateHubName } from "../utils/name-generation"; +import classNames from "classnames"; +import faAngleLeft from "@fortawesome/fontawesome-free-solid/faAngleLeft"; +import faAngleRight from "@fortawesome/fontawesome-free-solid/faAngleRight"; +import FontAwesomeIcon from "@fortawesome/react-fontawesome"; + +const HUB_NAME_PATTERN = "^[A-Za-z0-9-'\":!@#$%^&*(),.?~ ]{4,64}$"; + +class HubCreatePanel extends Component { + static propTypes = { + intl: PropTypes.object, + environments: PropTypes.array + }; + + constructor(props) { + super(props); + + this.state = { + name: generateHubName(), + environmentIndex: Math.floor(Math.random() * props.environments.length), + + // HACK: expand on small screens by default to ensure scene selection possible. + // Eventually this could/should be done via media queries. + expanded: window.innerWidth < 420 + }; + } + + createHub = async e => { + e.preventDefault(); + const environment = this.props.environments[this.state.environmentIndex]; + + const payload = { + hub: { name: this.state.name, default_environment_gltf_bundle_url: environment.bundle_url } + }; + + const res = await fetch("/api/v1/hubs", { + body: JSON.stringify(payload), + headers: { "content-type": "application/json" }, + method: "POST" + }); + + const hub = await res.json(); + document.location = hub.url; + }; + + isHubNameValid = () => { + const hubAlphaPattern = "[A-Za-z0-9]{4}"; + return new RegExp(HUB_NAME_PATTERN).test(this.state.name) && new RegExp(hubAlphaPattern).test(this.state.name); + }; + + setToEnvironmentOffset = offset => { + const numEnvs = this.props.environments.length; + + this.setState(state => ({ + environmentIndex: ((state.environmentIndex + offset) % this.props.environments.length + numEnvs) % numEnvs + })); + }; + + setToNextEnvironment = e => { + e.preventDefault(); + this.setToEnvironmentOffset(1); + }; + + setToPreviousEnvironment = e => { + e.preventDefault(); + this.setToEnvironmentOffset(-1); + }; + + shuffle = () => { + this.setState({ + name: generateHubName(), + environmentIndex: Math.floor(Math.random() * this.props.environments.length) + }); + }; + + render() { + const { formatMessage } = this.props.intl; + + if (this.props.environments.length == 0) { + return <div />; + } + + const environment = this.props.environments[this.state.environmentIndex]; + const environmentImageSrcSet = environment.meta.images.find(i => i.type === "preview-thumbnail").srcset; + + const environmentTitle = environment.meta.title; + const environmentAuthor = (environment.meta.authors || [])[0]; + + const formNameClassNames = classNames("create-panel__form__name", { + "create-panel__form__name--expanded": this.state.expanded + }); + + return ( + <form onSubmit={this.createHub}> + <div className="create-panel"> + {!this.state.expanded && ( + <div className="create-panel__header"> + <FormattedMessage id="home.create_header" /> + </div> + )} + <div className="create-panel__form"> + <div + className="create-panel__form__left-container" + onClick={e => { + e.preventDefault(); + + if (this.state.expanded) { + this.shuffle(); + } else { + this.setState({ expanded: true }); + } + }} + > + <button className="create-panel__form__rotate-button"> + {this.state.expanded ? ( + <img src="../assets/images/dice_icon.svg" /> + ) : ( + <img src="../assets/images/expand_dots_icon.svg" /> + )} + </button> + </div> + <div className="create-panel__form__right-container" onClick={this.createHub}> + <button className="create-panel__form__submit-button"> + {this.isHubNameValid() ? ( + <img src="../assets/images/hub_create_button_enabled.svg" /> + ) : ( + <img src="../assets/images/hub_create_button_disabled.svg" /> + )} + </button> + </div> + {this.state.expanded && ( + <div className="create-panel__form__environment"> + <div className="create-panel__form__environment__picker"> + <img className="create-panel__form__environment__picker__image" srcSet={environmentImageSrcSet} /> + <div className="create-panel__form__environment__picker__labels"> + <div className="create-panel__form__environment__picker__labels__header"> + <span className="create-panel__form__environment__picker__labels__header__title"> + {environmentTitle} + </span> + {environmentAuthor && + environmentAuthor.name && ( + <span className="create-panel__form__environment__picker__labels__header__author"> + <FormattedMessage id="home.environment_author_by" /> + <span>{environmentAuthor.name}</span> + </span> + )} + </div> + <div className="create-panel__form__environment__picker__labels__footer"> + <FormattedMessage id="home.environment_picker_footer" /> + </div> + </div> + <div className="create-panel__form__environment__picker__controls"> + <button + className="create-panel__form__environment__picker__controls__prev" + onClick={this.setToPreviousEnvironment} + > + <FontAwesomeIcon icon={faAngleLeft} /> + </button> + + <button + className="create-panel__form__environment__picker__controls__next" + onClick={this.setToNextEnvironment} + > + <FontAwesomeIcon icon={faAngleRight} /> + </button> + </div> + </div> + </div> + )} + <input + className={formNameClassNames} + value={this.state.name} + onChange={e => this.setState({ name: e.target.value })} + onFocus={e => e.target.select()} + required + pattern={HUB_NAME_PATTERN} + title={formatMessage({ id: "home.create_name.validation_warning" })} + /> + </div> + </div> + </form> + ); + } +} + +export default injectIntl(HubCreatePanel); diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js index 26ffdfbf3d55227218ea4c36f3752fbe888461df..5c8918cd5646b779efd79295a42e0b38370c973a 100644 --- a/src/react-components/ui-root.js +++ b/src/react-components/ui-root.js @@ -88,10 +88,12 @@ class UIRoot extends Component { autoExitTimerInterval: null, secondsRemainingBeforeAutoExit: Infinity, - sceneLoaded: false, + initialEnvironmentLoaded: false, exited: false, - showProfileEntry: false + showProfileEntry: false, + + janusRoomId: null }; componentDidMount() { @@ -118,6 +120,7 @@ class UIRoot extends Component { muted: this.props.scene.is("muted") }); }; + toggleMute = () => { this.props.scene.emit("action_mute"); }; @@ -210,18 +213,17 @@ class UIRoot extends Component { hasGrantedMicPermissions = async () => { if (this.state.requestedScreen) { - // There is no way to tell if you've granted mic permissions in a previous session if we've + // There is no way to tell if you've granted mic permissions in a previous session if we've // already prompted for screen sharing permissions, so we have to assume that we've never granted permissions. - // Fortunately, if you *have* granted permissions permanently, there won't be a second browser prompt, but we + // Fortunately, if you *have* granted permissions permanently, there won't be a second browser prompt, but we // can't determine that before hand. // See https://bugzilla.mozilla.org/show_bug.cgi?id=1449783 for a potential solution in the future. return false; - } - else { + } else { // If we haven't requested the screen in this session, check if we've granted permissions in a previous session. return (await grantedMicLabels()).length > 0; } - } + }; performDirectEntryFlow = async enterInVR => { this.startTestTone(); @@ -286,35 +288,36 @@ class UIRoot extends Component { const constraints = { audio: { deviceId: { exact: [ev.target.value] } } }; await this.fetchAudioTrack(constraints); await this.setupNewMediaStream(); - } + }; setMediaStreamToDefault = async () => { await this.fetchAudioTrack({ audio: true }); await this.setupNewMediaStream(); - } + }; setStateAndRequestScreen = async e => { const checked = e.target.checked; await this.setState({ requestedScreen: true, shareScreen: checked }); if (checked) { - this.fetchVideoTrack({ video: { - mediaSource: "screen", - // Work around BMO 1449832 by calculating the width. This will break for multi monitors if you share anything - // other than your current monitor that has a different aspect ratio. - width: screen.width / screen.height * 720, - height: 720, - frameRate: 30 - } }); - } - else { + this.fetchVideoTrack({ + video: { + mediaSource: "screen", + // Work around BMO 1449832 by calculating the width. This will break for multi monitors if you share anything + // other than your current monitor that has a different aspect ratio. + width: screen.width / screen.height * 720, + height: 720, + frameRate: 30 + } + }); + } else { this.setState({ videoTrack: null }); } - } + }; fetchVideoTrack = async constraints => { const mediaStream = await navigator.mediaDevices.getUserMedia(constraints); this.setState({ videoTrack: mediaStream.getVideoTracks()[0] }); - } + }; fetchAudioTrack = async constraints => { if (this.state.audioTrack) { @@ -322,12 +325,12 @@ class UIRoot extends Component { } const mediaStream = await navigator.mediaDevices.getUserMedia(constraints); this.setState({ audioTrack: mediaStream.getAudioTracks()[0] }); - } + }; setupNewMediaStream = async constraints => { const mediaStream = new MediaStream(); - // we should definitely have an audioTrack at this point. + // we should definitely have an audioTrack at this point. mediaStream.addTrack(this.state.audioTrack); if (this.state.videoTrack) { @@ -380,10 +383,8 @@ class UIRoot extends Component { fetchMicDevices = async () => { const mediaDevices = await navigator.mediaDevices.enumerateDevices(); - this.setState({ - micDevices: mediaDevices. - filter(d => d.kind === "audioinput"). - map(d => ({ deviceId: d.deviceId, label: d.label })) + this.setState({ + micDevices: mediaDevices.filter(d => d.kind === "audioinput").map(d => ({ deviceId: d.deviceId, label: d.label })) }); }; @@ -413,7 +414,7 @@ class UIRoot extends Component { }; onAudioReadyButton = () => { - this.props.enterScene(this.state.mediaStream, this.state.enterInVR); + this.props.enterScene(this.state.mediaStream, this.state.enterInVR, this.state.janusRoomId); const mediaStream = this.state.mediaStream; @@ -432,7 +433,7 @@ class UIRoot extends Component { }; render() { - if (!this.props.scene.hasLoaded || !this.state.availableVREntryTypes) { + if (!this.state.initialEnvironmentLoaded || !this.state.availableVREntryTypes || !this.state.janusRoomId) { return ( <IntlProvider locale={lang} messages={messages}> <div className="loading-panel"> @@ -468,45 +469,44 @@ class UIRoot extends Component { // Only show this in desktop firefox since other browsers/platforms will ignore the "screen" media constraint and // will attempt to share your webcam instead! - const screenSharingCheckbox = ( - this.props.enableScreenSharing && - !mobiledetect.mobile() && - /firefox/i.test(navigator.userAgent) && - ( + const screenSharingCheckbox = this.props.enableScreenSharing && + !mobiledetect.mobile() && + /firefox/i.test(navigator.userAgent) && ( <label className="entry-panel__screen-sharing"> - <input className="entry-panel__screen-sharing-checkbox" type="checkbox" + <input + className="entry-panel__screen-sharing-checkbox" + type="checkbox" value={this.state.shareScreen} onChange={this.setStateAndRequestScreen} /> <FormattedMessage id="entry.enable-screen-sharing" /> </label> - ) - ); + ); - const entryPanel = + const entryPanel = this.state.entryStep === ENTRY_STEPS.start ? ( <div className="entry-panel"> <TwoDEntryButton onClick={this.enter2D} /> - { this.state.availableVREntryTypes.generic !== VR_DEVICE_AVAILABILITY.no && ( - <GenericEntryButton onClick={this.enterVR} /> + {this.state.availableVREntryTypes.generic !== VR_DEVICE_AVAILABILITY.no && ( + <GenericEntryButton onClick={this.enterVR} /> )} - { this.state.availableVREntryTypes.gearvr !== VR_DEVICE_AVAILABILITY.no && ( - <GearVREntryButton onClick={this.enterGearVR} /> + {this.state.availableVREntryTypes.gearvr !== VR_DEVICE_AVAILABILITY.no && ( + <GearVREntryButton onClick={this.enterGearVR} /> )} - { this.state.availableVREntryTypes.daydream !== VR_DEVICE_AVAILABILITY.no && ( + {this.state.availableVREntryTypes.daydream !== VR_DEVICE_AVAILABILITY.no && ( <DaydreamEntryButton onClick={this.enterDaydream} subtitle={ - this.state.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe ? daydreamMaybeSubtitle : "" + this.state.availableVREntryTypes.daydream == VR_DEVICE_AVAILABILITY.maybe ? daydreamMaybeSubtitle : "" } - /> + /> )} {this.state.availableVREntryTypes.cardboard !== VR_DEVICE_AVAILABILITY.no && ( <div className="entry-panel__secondary" onClick={this.enterVR}> <FormattedMessage id="entry.cardboard" /> </div> )} - { screenSharingCheckbox } + {screenSharingCheckbox} </div> ) : null; diff --git a/src/telemetry.js b/src/telemetry.js index 9e42e76a0a082e945189b560c4dbaf03bf0d733f..2a738593e98541d97e236a0a70d28619b4b10925 100644 --- a/src/telemetry.js +++ b/src/telemetry.js @@ -1,7 +1,5 @@ import Raven from "raven-js"; export default function registerTelemetry() { - Raven.config( - "https://f571beaf5cee4e3085e0bf436f3eb158@sentry.io/256771" - ).install(); + Raven.config("https://f571beaf5cee4e3085e0bf436f3eb158@sentry.io/256771").install(); } diff --git a/src/utils/name-generation.js b/src/utils/name-generation.js new file mode 100644 index 0000000000000000000000000000000000000000..385e62bd01890e983fd3a8fc9e38ecb7fd570130 --- /dev/null +++ b/src/utils/name-generation.js @@ -0,0 +1,673 @@ +const adjectives = [ + "able", + "absolute", + "acceptable", + "acclaimed", + "accomplished", + "accurate", + "aching", + "acrobatic", + "adorable", + "adventurous", + "basic", + "belated", + "beloved", + "calm", + "candid", + "capital", + "carefree", + "caring", + "cautious", + "celebrated", + "charming", + "daring", + "darling", + "dearest", + "each", + "eager", + "early", + "earnest", + "easy", + "easygoing", + "ecstatic", + "edible", + "fabulous", + "fair", + "faithful", + "familiar", + "famous", + "fancy", + "fantastic", + "far", + "generous", + "gentle", + "genuine", + "giant", + "handmade", + "handsome", + "handy", + "happy", + "icy", + "ideal", + "identical", + "keen", + "lasting", + "lavish", + "magnificent", + "majestic", + "mammoth", + "marvelous", + "natural", + "obedient", + "palatable", + "parched", + "passionate", + "pastel", + "peaceful", + "perfect", + "perfumed", + "quaint", + "qualified", + "radiant", + "rapid", + "rare", + "safe", + "sandy", + "satisfied", + "scaly", + "scarce", + "scared", + "scary", + "scented", + "scientific", + "secret", + "sentimental", + "talkative", + "tangible", + "tart", + "tasty", + "tattered", + "teeming", + "ultimate", + "uncommon", + "unconscious", + "understated", + "warm", + "active", + "adept", + "admirable", + "admired", + "adorable", + "adored", + "advanced", + "affectionate", + "beneficial", + "best", + "better", + "big", + "cheerful", + "cheery", + "chief", + "chilly", + "classic", + "clean", + "clear", + "clever", + "decent", + "decisive", + "deep", + "defiant", + "definitive", + "delectable", + "delicious", + "elaborate", + "elastic", + "elated", + "elegant", + "elementary", + "elliptical", + "fast", + "favorable", + "favorite", + "fearless", + "gifted", + "glamorous", + "gleaming", + "glittering", + "harmonious", + "imaginative", + "immense", + "jealous", + "kind", + "leafy", + "legal", + "mature", + "mean", + "meaty", + "nautical", + "neat", + "necessary", + "needy", + "oddball", + "offbeat", + "periodic", + "perky", + "personal", + "pertinent", + "petty", + "quarterly", + "ready", + "real", + "realistic", + "reasonable", + "regal", + "serene", + "shabby", + "sharp", + "shiny", + "showy", + "shy", + "silky", + "tempting", + "tense", + "terrific", + "testy", + "thankful", + "uniform", + "unique", + "vast", + "weary", + "wee", + "welcome", + "agile", + "alarmed", + "alert", + "alive", + "bleak", + "blissful", + "blushing", + "coarse", + "colorful", + "colossal", + "comfortable", + "compassionate", + "complete", + "delightful", + "dense", + "dependable", + "dependent", + "descriptive", + "detailed", + "determined", + "devoted", + "different", + "eminent", + "emotional", + "enchanted", + "enchanting", + "energetic", + "enormous", + "fine", + "finished", + "firm", + "firsthand", + "fixed", + "flashy", + "flawless", + "glorious", + "glossy", + "golden", + "good", + "gorgeous", + "graceful", + "healthy", + "heartfelt", + "hearty", + "helpful", + "impartial", + "impressive", + "jolly", + "jovial", + "lighthearted", + "likable", + "lined", + "mellow", + "melodic", + "memorable", + "mild", + "new", + "opulent", + "playful", + "pleasant", + "pleasing", + "plump", + "plush", + "polished", + "polite", + "reliable", + "relieved", + "remarkable", + "remote", + "respectful", + "responsible", + "simple", + "simplistic", + "sizzling", + "sleepy", + "slight", + "slim", + "smart", + "smooth", + "snappy", + "snoopy", + "thirsty", + "this", + "thorough", + "those", + "thoughtful", + "united", + "vibrant", + "vicious", + "wellmade", + "whimsical", + "whirlwind", + "zesty", + "amazing", + "ambitious", + "ample", + "amused", + "amusing", + "ancient", + "angelic", + "antique", + "bold", + "bossy", + "both", + "bouncy", + "bountiful", + "complex", + "conscious", + "considerate", + "constant", + "content", + "conventional", + "cooked", + "cool", + "cooperative", + "diligent", + "dimwitted", + "direct", + "discrete", + "envious", + "essential", + "ethical", + "euphoric", + "flippant", + "fluffy", + "fluid", + "flustered", + "focused", + "fond", + "gracious", + "grand", + "grandiose", + "granular", + "grateful", + "grave", + "great", + "hidden", + "high", + "hilarious", + "homely", + "incomparable", + "incredible", + "infamous", + "joyful", + "lively", + "loathsome", + "lonely", + "long", + "milky", + "mindless", + "miniature", + "minor", + "misty", + "next", + "nice", + "nifty", + "nimble", + "orderly", + "organic", + "ornate", + "popular", + "posh", + "positive", + "potable", + "powerful", + "powerless", + "precious", + "present", + "prestigious", + "quick", + "rewarding", + "rich", + "right", + "sociable", + "soft", + "solid", + "some", + "sophisticated", + "soulful", + "sparkling", + "spectacular", + "speedy", + "spicy", + "spiffy", + "spirited", + "spiteful", + "splendid", + "spotless", + "spry", + "thrifty", + "tidy", + "tight", + "timely", + "tinted", + "unruly", + "untimely", + "violet", + "wicked", + "wide", + "wild", + "willing", + "winding", + "windy", + "zigzag", + "apprehensive", + "appropriate", + "artistic", + "assured", + "astonishing", + "bright", + "brilliant", + "bronze", + "coordinated", + "courageous", + "courteous", + "crafty", + "crazy", + "creamy", + "creative", + "crisp", + "distant", + "distinct", + "downright", + "evergreen", + "everlasting", + "every", + "evil", + "excellent", + "excitable", + "exemplary", + "exhausted", + "forthright", + "fortunate", + "fragrant", + "frank", + "free", + "frequent", + "fresh", + "friendly", + "frightened", + "frigid", + "gripping", + "grounded", + "honest", + "honorable", + "honored", + "hopeful", + "hospitable", + "hot", + "huge", + "infatuated", + "infinite", + "informal", + "insistent", + "instructive", + "juicy", + "jumbo", + "knowing", + "knowledgeable", + "longterm", + "loud", + "lovable", + "loving", + "modern", + "modest", + "moist", + "monumental", + "normal", + "notable", + "outgoing", + "precious", + "pretty", + "prickly", + "primary", + "pristine", + "private", + "prize", + "productive", + "profitable", + "quiet", + "quintessential", + "roasted", + "robust", + "square", + "squiggly", + "stable", + "staid", + "starry", + "steel", + "stimulating", + "striking", + "striped", + "strong", + "studious", + "stunning", + "tough", + "trained", + "treasured", + "tremendous", + "triangular", + "tricky", + "unused", + "unusual", + "upbeat", + "virtual", + "witty", + "wonderful", + "wooden", + "worldly", + "youthful", + "attached", + "attentive", + "attractive", + "austere", + "authentic", + "automatic", + "aware", + "awesome", + "bubbly", + "bustling", + "busy", + "buttery", + "cuddly", + "cultured", + "curly", + "curvy", + "cute", + "cylindrical", + "downright", + "dramatic", + "excited", + "exciting", + "exotic", + "experienced", + "expert", + "frosty", + "fruitful", + "full", + "fumbling", + "funny", + "fussy", + "growing", + "grown", + "gummy", + "humble", + "humongous", + "hungry", + "intelligent", + "interesting", + "known", + "kooky", + "kosher", + "loyal", + "lucky", + "luminous", + "lustrous", + "luxurious", + "multicolored", + "mysterious", + "noteworthy", + "numb", + "nutritious", + "outstanding", + "overjoyed", + "proper", + "proud", + "prudent", + "punctual", + "puny", + "pure", + "puzzled", + "puzzling", + "quirky", + "stupendous", + "sturdy", + "stylish", + "subdued", + "subtle", + "sunny", + "super", + "superb", + "supportive", + "surprised", + "sweet", + "swift", + "sympathetic", + "trivial", + "trusting", + "trustworthy", + "trusty", + "truthful", + "twin", + "usable", + "used", + "useful", + "utilized", + "vital", + "vivid", + "worried", + "worthwhile", + "worthy", + "writhing", + "wry", + "yummy", + "chocolate", + "crimson", + "cyan", + "fuchsia", + "gold", + "honeydew", + "lime", + "linen", + "magenta", + "olive", + "peru", + "salmon", + "seashell", + "sienna", + "snow", + "thistle", + "tomato", + "transparent", + "turquoise", + "violet" +]; + +const nouns = [ + "space", + "land", + "world", + "universe", + "plane", + "room", + "nation", + "plaza", + "gathering", + "meetup", + "get together", + "conclave", + "party", + "powwow", + "domain", + "dominion", + "realm", + "square", + "commons", + "park", + "cosmos", + "sphere", + "terrain", + "spot", + "zone", + "area", + "tract", + "turf", + "place", + "territory", + "volume", + "camp", + "picnic", + "outing", + "vacation", + "adventure", + "exploration", + "outing", + "walkabout", + "safari", + "venture", + "roundtable", + "barbecue", + "celebration", + "festivity", + "gala", + "shindig", + "social", + "convention", + "assembly", + "congregation", + "rendezvous", + "huddle", + "meet", + "soiree" +]; + +export function generateHubName() { + const randItem = set => { + const s = set[Math.floor(Math.random() * set.length)]; + return s.charAt(0).toUpperCase() + s.slice(1); + }; + + return `${randItem(adjectives)} ${randItem(adjectives)} ${randItem(nouns)}`; +} diff --git a/webpack.config.js b/webpack.config.js index d404babbb6d5af438271621b4e3f2fbac235a266..1fdc22406d4a3ab182b072c6aca32e96cb4d6b23 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,6 +3,7 @@ require("dotenv").config(); const fs = require("fs"); const path = require("path"); +const glob = require("glob"); const selfsigned = require("selfsigned"); const webpack = require("webpack"); const HTMLWebpackPlugin = require("html-webpack-plugin"); @@ -75,14 +76,13 @@ class LodashTemplatePlugin { const config = { entry: { - lobby: path.join(__dirname, "src", "lobby.js"), - room: path.join(__dirname, "src", "room.js"), - 'avatar-selector': path.join(__dirname, "src", "avatar-selector.js"), - onboarding: path.join(__dirname, "src", "onboarding.js") + index: path.join(__dirname, "src", "index.js"), + hub: path.join(__dirname, "src", "hub.js"), + "avatar-selector": path.join(__dirname, "src", "avatar-selector.js") }, output: { path: path.join(__dirname, "public"), - filename: "[name]-[chunkhash].js", + filename: "assets/js/[name]-[chunkhash].js", publicPath: process.env.BASE_ASSETS_PATH || "" }, mode: "development", @@ -97,7 +97,7 @@ const config = { // networked-aframe makes HEAD requests to the server for time syncing. Respond with an empty body. app.head("*", function(req, res, next) { if (req.method === "HEAD") { - res.append("Date", (new Date()).toGMTString()); + res.append("Date", new Date().toGMTString()); res.send(""); } else { next(); @@ -108,7 +108,7 @@ const config = { performance: { // Ignore media and sourcemaps when warning about file size. assetFilter(assetFilename) { - return !/\.(map|png|jpg|gif|glb)$/.test(assetFilename); + return !/\.(map|png|jpg|gif|glb|webm)$/.test(assetFilename); } }, module: { @@ -170,7 +170,7 @@ const config = { }) }, { - test: /\.(png|jpg|gif|glb|ogg|woff2|svg)$/, + test: /\.(png|jpg|gif|glb|ogg|woff2|svg|webm)$/, use: { loader: "file-loader", options: { @@ -187,29 +187,33 @@ const config = { // Each output page needs a HTMLWebpackPlugin entry new HTMLWebpackPlugin({ filename: "index.html", - template: path.join(__dirname, "src", "lobby.html"), + template: path.join(__dirname, "src", "index.html"), // Chunks correspond with the entries you wish to include in your html template - chunks: ["lobby"] + chunks: ["index"] }), new HTMLWebpackPlugin({ - filename: "room.html", - template: path.join(__dirname, "src", "room.html"), - chunks: ["room"], + filename: "hub.html", + template: path.join(__dirname, "src", "hub.html"), + chunks: ["hub"], inject: "head" }), + // Build the GLTF asset bundle json files + ...glob.sync("src/assets/**/*.tpl").map( + f => + new HTMLWebpackPlugin({ + filename: f.replace(".tpl", "").replace("src/", ""), + template: path.join(...[__dirname, ...f.split("/")]), + chunks: [] + }) + ), new HTMLWebpackPlugin({ filename: "avatar-selector.html", template: path.join(__dirname, "src", "avatar-selector.html"), chunks: ["avatar-selector"], inject: "head" }), - new HTMLWebpackPlugin({ - filename: "onboarding.html", - template: path.join(__dirname, "src", "onboarding.html"), - chunks: ["onboarding"] - }), // Extract required css and add a content hash. - new ExtractTextPlugin("[name]-[contenthash].css", { + new ExtractTextPlugin("assets/stylesheets/[name]-[contenthash].css", { disable: process.env.NODE_ENV !== "production" }), // Transform the output of the html-loader using _.template diff --git a/yarn.lock b/yarn.lock index 71b37b2f51e39ff013774a7a96b8e2e23c8441b2..18f7727e7dd7217a0e581df22c2ddfc12a8ff16a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,70 +2,77 @@ # yarn lockfile v1 -"@babel/code-frame@7.0.0-beta.40", "@babel/code-frame@^7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.40.tgz#37e2b0cf7c56026b4b21d3927cadf81adec32ac6" +"@babel/code-frame@7.0.0-beta.42", "@babel/code-frame@^7.0.0-beta.40": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.42.tgz#a9c83233fa7cd06b39dc77adbb908616ff4f1962" dependencies: - "@babel/highlight" "7.0.0-beta.40" + "@babel/highlight" "7.0.0-beta.42" -"@babel/generator@7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.40.tgz#ab61f9556f4f71dbd1138949c795bb9a21e302ea" +"@babel/generator@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.42.tgz#777bb50f39c94a7e57f73202d833141f8159af33" dependencies: - "@babel/types" "7.0.0-beta.40" + "@babel/types" "7.0.0-beta.42" jsesc "^2.5.1" lodash "^4.2.0" source-map "^0.5.0" trim-right "^1.0.1" -"@babel/helper-function-name@7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.40.tgz#9d033341ab16517f40d43a73f2d81fc431ccd7b6" +"@babel/helper-function-name@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.42.tgz#b38b8f4f85168d1812c543dd700b5d549b0c4658" dependencies: - "@babel/helper-get-function-arity" "7.0.0-beta.40" - "@babel/template" "7.0.0-beta.40" - "@babel/types" "7.0.0-beta.40" + "@babel/helper-get-function-arity" "7.0.0-beta.42" + "@babel/template" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" -"@babel/helper-get-function-arity@7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.40.tgz#ac0419cf067b0ec16453e1274f03878195791c6e" +"@babel/helper-get-function-arity@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.42.tgz#ad072e32f912c033053fc80478169aeadc22191e" dependencies: - "@babel/types" "7.0.0-beta.40" + "@babel/types" "7.0.0-beta.42" -"@babel/highlight@7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.40.tgz#b43d67d76bf46e1d10d227f68cddcd263786b255" +"@babel/helper-split-export-declaration@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.42.tgz#0d0d5254220a9cc4e7e226240306b939dc210ee7" + dependencies: + "@babel/types" "7.0.0-beta.42" + +"@babel/highlight@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.42.tgz#a502a1c0d6f99b2b0e81d468a1b0c0e81e3f3623" dependencies: chalk "^2.0.0" esutils "^2.0.2" js-tokens "^3.0.0" -"@babel/template@7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.40.tgz#034988c6424eb5c3268fe6a608626de1f4410fc8" +"@babel/template@7.0.0-beta.42": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.42.tgz#7186d4e70d44cdec975049ba0a73bdaf5cdee052" dependencies: - "@babel/code-frame" "7.0.0-beta.40" - "@babel/types" "7.0.0-beta.40" - babylon "7.0.0-beta.40" + "@babel/code-frame" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + babylon "7.0.0-beta.42" lodash "^4.2.0" "@babel/traverse@^7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.40.tgz#d140e449b2e093ef9fe1a2eecc28421ffb4e521e" - dependencies: - "@babel/code-frame" "7.0.0-beta.40" - "@babel/generator" "7.0.0-beta.40" - "@babel/helper-function-name" "7.0.0-beta.40" - "@babel/types" "7.0.0-beta.40" - babylon "7.0.0-beta.40" - debug "^3.0.1" + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.42.tgz#f4bf4d1e33d41baf45205e2d0463591d57326285" + dependencies: + "@babel/code-frame" "7.0.0-beta.42" + "@babel/generator" "7.0.0-beta.42" + "@babel/helper-function-name" "7.0.0-beta.42" + "@babel/helper-split-export-declaration" "7.0.0-beta.42" + "@babel/types" "7.0.0-beta.42" + babylon "7.0.0-beta.42" + debug "^3.1.0" globals "^11.1.0" invariant "^2.2.0" lodash "^4.2.0" -"@babel/types@7.0.0-beta.40", "@babel/types@^7.0.0-beta.40": - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.40.tgz#25c3d7aae14126abe05fcb098c65a66b6d6b8c14" +"@babel/types@7.0.0-beta.42", "@babel/types@^7.0.0-beta.40": + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.42.tgz#1e2118767684880f6963801b272fd2b3348efacc" dependencies: esutils "^2.0.2" lodash "^4.2.0" @@ -433,6 +440,16 @@ assert@^1.1.1, assert@^1.4.0: dependencies: util "0.10.3" +assets-webpack-plugin@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/assets-webpack-plugin/-/assets-webpack-plugin-3.5.1.tgz#931ce0d66d42e88ed5e7f18d65522943c57a387d" + dependencies: + camelcase "^1.2.1" + escape-string-regexp "^1.0.3" + lodash.assign "^3.2.0" + lodash.merge "^3.3.2" + mkdirp "^0.5.1" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -536,9 +553,9 @@ babel-core@^6.26.0: slash "^1.0.0" source-map "^0.5.6" -babel-eslint@^8.2.2: +babel-eslint@8: version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b" + resolved "http://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.2.tgz#1102273354c6f0b29b4ea28a65f97d122296b68b" dependencies: "@babel/code-frame" "^7.0.0-beta.40" "@babel/traverse" "^7.0.0-beta.40" @@ -1210,9 +1227,9 @@ babel-types@^6.10.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26 lodash "^4.17.4" to-fast-properties "^1.0.3" -babylon@7.0.0-beta.40, babylon@^7.0.0-beta.40: - version "7.0.0-beta.40" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.40.tgz#91fc8cd56d5eb98b28e6fde41045f2957779940a" +babylon@7.0.0-beta.42, babylon@^7.0.0-beta.40: + version "7.0.0-beta.42" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.42.tgz#67cfabcd4f3ec82999d29031ccdea89d0ba99657" babylon@^6.17.3, babylon@^6.18.0: version "6.18.0" @@ -1702,6 +1719,10 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" +camelcase@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" @@ -2391,7 +2412,7 @@ debug@2.6.9, debug@^2.0.0, debug@^2.1.0, debug@^2.2.0, debug@^2.3.3, debug@^2.6. dependencies: ms "2.0.0" -debug@^3.0.1, debug@^3.1.0: +debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -2837,7 +2858,7 @@ escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -4724,6 +4745,57 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +lodash._arraycopy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz#76e7b7c1f1fb92547374878a562ed06a3e50f6e1" + +lodash._arrayeach@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz#bab156b2a90d3f1bbd5c653403349e5e5933ef9e" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basefor@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2" + +lodash._bindcallback@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" + +lodash._createassigner@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" + dependencies: + lodash._bindcallback "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash.restparam "^3.0.0" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.assign@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" + dependencies: + lodash._baseassign "^3.0.0" + lodash._createassigner "^3.0.0" + lodash.keys "^3.0.0" + lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -4740,14 +4812,49 @@ lodash.endswith@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.endswith/-/lodash.endswith-4.2.1.tgz#fed59ac1738ed3e236edd7064ec456448b37bc09" +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + lodash.isfunction@^3.0.8: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" +lodash.isplainobject@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz#9a8238ae16b200432960cd7346512d0123fbf4c5" + dependencies: + lodash._basefor "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.keysin "^3.0.0" + lodash.isstring@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" +lodash.istypedarray@^3.0.0: + version "3.0.6" + resolved "https://registry.yarnpkg.com/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz#c9a477498607501d8e8494d283b87c39281cef62" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.keysin@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/lodash.keysin/-/lodash.keysin-3.0.8.tgz#22c4493ebbedb1427962a54b445b2c8a767fb47f" + dependencies: + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -4756,10 +4863,30 @@ lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" +lodash.merge@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-3.3.2.tgz#0d90d93ed637b1878437bb3e21601260d7afe994" + dependencies: + lodash._arraycopy "^3.0.0" + lodash._arrayeach "^3.0.0" + lodash._createassigner "^3.0.0" + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + lodash.isplainobject "^3.0.0" + lodash.istypedarray "^3.0.0" + lodash.keys "^3.0.0" + lodash.keysin "^3.0.0" + lodash.toplainobject "^3.0.0" + lodash.mergewith@^4.6.0: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + lodash.startswith@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.startswith/-/lodash.startswith-4.2.1.tgz#c598c4adce188a27e53145731cdc6c0e7177600c" @@ -4768,6 +4895,13 @@ lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" +lodash.toplainobject@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz#28790ad942d293d78aa663a07ecf7f52ca04198d" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keysin "^3.0.0" + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"