Newer
Older
import React, { Component } from "react";
import PropTypes from "prop-types";
import { injectIntl, FormattedMessage } from "react-intl";
import { generateHubName } from "../utils/name-generation";
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons/faAngleLeft";
import { faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { resolveURL, extractUrlBase } from "../utils/resolveURL";
import { getReticulumFetchUrl } from "../utils/phoenix-utils";
import CreateRoomDialog from "./create-room-dialog.js";
import { WithHoverSound } from "./wrap-with-audio";
import default_scene_preview_thumbnail from "../assets/images/default_thumbnail.png";
import styles from "../assets/stylesheets/hub-create.scss";
const HUB_NAME_PATTERN = "^[A-Za-z0-9-'\":!@#$%^&*(),.?~ ]{4,64}$";
class HubCreatePanel extends Component {
static propTypes = {
intl: PropTypes.object,
environments: PropTypes.array,
initialEnvironment: PropTypes.string
let environmentIndex = Math.floor(Math.random() * props.environments.length);
if (props.initialEnvironment) {
environmentIndex = props.environments.findIndex(
e => e.name.toLowerCase() === props.initialEnvironment.toLowerCase()
);
}
// Optimisticly preload all environment thumbnails
(async () => {
const environmentThumbnails = props.environments.map((_, i) => this._getEnvironmentThumbnail(i));
await Promise.all(
environmentThumbnails.map(environmentThumbnail => this._preloadImage(environmentThumbnail.srcset))
);
this.setState({ ready: true });
})();
_getEnvironmentThumbnail = environmentIndex => {
const environment = this.props.environments[environmentIndex];
const meta = environment.meta || {};
let environmentThumbnail = {
srcset: default_scene_preview_thumbnail
};
if (meta.images) {
const thumbnailImage = meta.images.find(i => i.type === "preview-thumbnail");
if (thumbnailImage) {
// TODO kill bundles
if (environment.bundle_url) {
const baseURL = new URL(extractUrlBase(environment.bundle_url), window.location.href);
environmentThumbnail = {
srcset: resolveURL(thumbnailImage.srcset, baseURL)
};
} else {
environmentThumbnail = {
srcset: thumbnailImage.srcset
};
}
const environment = this.props.environments[this.state.environmentIndex];
if (!this.state.customSceneUrl && environment.scene_id) {
payload.hub.scene_id = environment.scene_id;
} else {
const sceneUrl = this.state.customSceneUrl || environment.bundle_url;
payload.hub.default_environment_gltf_bundle_url = sceneUrl;
}
body: JSON.stringify(payload),
headers: { "content-type": "application/json" },
method: "POST"
});
const hub = await res.json();
if (!process.env.RETICULUM_SERVER || document.location.host === process.env.RETICULUM_SERVER) {
document.location = hub.url;
} else {
document.location = `/hub.html?hub_id=${hub.hub_id}`;
}
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);
};
const img = new Image();
const imgLoad = new Promise(resolve => img.addEventListener("load", resolve));
await imgLoad;
};
setToEnvironmentOffset = async offset => {
const environmentIndex = (((this.state.environmentIndex + offset) % numEnvs) + numEnvs) % numEnvs;
const environmentThumbnail = this._getEnvironmentThumbnail(environmentIndex);
await this._preloadImage(environmentThumbnail.srcset);
this.setState({ environmentIndex });
setToNextEnvironment = () => {
setToPreviousEnvironment = () => {
showCustomSceneDialog = e => {
e.preventDefault();
e.stopPropagation();
this.setState({ showCustomSceneDialog: true });
};
shuffle = () => {
this.setState({
name: generateHubName(),
environmentIndex: Math.floor(Math.random() * this.props.environments.length)
});
};
const environment = this.props.environments[this.state.environmentIndex];
const environmentTitle = meta.title || environment.name;
const environmentAuthor = (meta.authors || [])[0];
const environmentThumbnail = this._getEnvironmentThumbnail(this.state.environmentIndex);
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<div>
<form onSubmit={this.createHub}>
<div className={styles.createPanel}>
<div className={styles.form}>
<div className={styles.environment}>
<div className={styles.picker}>
<img className={styles.image} srcSet={environmentThumbnail.srcset} />
<div className={styles.labels}>
<div className={styles.header}>
<span className={styles.title}>{environmentTitle}</span>
{environmentAuthor &&
environmentAuthor.name &&
(environmentAuthor.url ? (
<WithHoverSound>
<a href={environmentAuthor.url} rel="noopener noreferrer" className={styles.author}>
<FormattedMessage id="home.environment_author_by" />
<span>{environmentAuthor.name}</span>
</a>
</WithHoverSound>
) : (
<span className={styles.author}>
<FormattedMessage id="home.environment_author_by" />
<span>{environmentAuthor.name}</span>
</span>
))}
{environmentAuthor &&
environmentAuthor.organization &&
(environmentAuthor.organization.url ? (
<WithHoverSound>
<a
href={environmentAuthor.organization.url}
rel="noopener noreferrer"
className={styles.org}
>
<span>{environmentAuthor.organization.name}</span>
</a>
</WithHoverSound>
) : (
<span className={styles.org}>
<span>{environmentAuthor.organization.name}</span>
</span>
))}
</div>
<div className={styles.footer}>
<WithHoverSound>
<button onClick={this.showCustomSceneDialog} className={styles.customButton}>
<FormattedMessage id="home.room_create_options" />
</WithHoverSound>
<div className={styles.controls}>
<WithHoverSound>
<button
className={styles.prev}
type="button"
tabIndex="1"
onClick={this.setToPreviousEnvironment}
>
<FontAwesomeIcon icon={faAngleLeft} />
</button>
</WithHoverSound>
<WithHoverSound>
<button className={styles.next} type="button" tabIndex="2" onClick={this.setToNextEnvironment}>
<FontAwesomeIcon icon={faAngleRight} />
</button>
</WithHoverSound>
<div className={styles.container}>
<WithHoverSound>
<button type="submit" tabIndex="5" className={styles.submitButton}>
<FormattedMessage id="home.room_create_button" />
</button>
</WithHoverSound>
</div>
</div>
</form>
{this.state.showCustomSceneDialog && (
<CreateRoomDialog
includeScenePrompt={true}
onClose={() => this.setState({ showCustomSceneDialog: false })}
onCustomScene={(name, url) => {
this.setState({ showCustomSceneDialog: false, name: name, customSceneUrl: url }, () => this.createHub());
}}
/>
</div>
);
}
}
export default injectIntl(HubCreatePanel);