Newer
Older
const whitelistedHosts = [/^.*\.reticulum\.io$/, /^.*hubs\.mozilla\.com$/, /^hubs\.local$/];
const isHostWhitelisted = hostname => !!whitelistedHosts.filter(r => r.test(hostname)).length;
let resolveMediaUrl = "/api/v1/media";
if (process.env.NODE_ENV === "development") {
resolveMediaUrl = `https://${process.env.DEV_RETICULUM_SERVER}${resolveMediaUrl}`;
}
export const resolveFarsparkUrl = async url => {
const parsedUrl = new URL(url);
if ((parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") || isHostWhitelisted(parsedUrl.hostname))
return { raw: url, origin: url };
return await fetch(resolveMediaUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ media: { url } })
}).then(r => r.json());
const fetchContentType = async url => fetch(url, { method: "HEAD" }).then(r => r.headers.get("content-type"));
let interactableId = 0;
const offset = { x: 0, y: 0, z: -1.5 };
export const spawnNetworkedImage = (src, contentType) => {
const scene = AFRAME.scenes[0];
const image = document.createElement("a-entity");
image.id = "interactable-image-" + interactableId++;
image.setAttribute("networked", { template: "#interactable-image" });
image.setAttribute("offset-relative-to", {
target: "#player-camera",
offset: offset,
selfDestruct: true
});
image.setAttribute("image-plus", { src, contentType });
scene.appendChild(image);
return image;
};
export const spawnNetworkedInteractable = (src, basePath) => {
const scene = AFRAME.scenes[0];
const model = document.createElement("a-entity");
model.id = "interactable-model-" + interactableId++;
model.setAttribute("networked", { template: "#interactable-model" });
model.setAttribute("offset-relative-to", {
target: "#player-camera",
offset: offset,
selfDestruct: true
});
model.setAttribute("gltf-model-plus", { src, basePath });
model.setAttribute("auto-box-collider", { resize: true });
scene.appendChild(model);
return model;
};
export const addMedia = async url => {
try {
const { raw, origin, meta } = await resolveFarsparkUrl(url);
console.log("resolved", url, raw, origin, meta);
const contentType = (meta && meta.expected_content_type) || (await fetchContentType(raw));
if (contentType.startsWith("image/") || contentType.startsWith("video/")) {
return spawnNetworkedImage(raw, contentType);
} else if (contentType.startsWith("model/gltf") || url.endsWith(".gltf") || url.endsWith(".glb")) {
return spawnNetworkedInteractable(raw, THREE.LoaderUtils.extractUrlBase(origin));