Skip to content
Snippets Groups Projects
Unverified Commit d292b9c6 authored by Greg Fodor's avatar Greg Fodor Committed by GitHub
Browse files

Merge pull request #161 from mozilla/feature/basic-phoenix-channel

Feature/basic phoenix channel
parents 339fa099 20a10396
No related branches found
No related tags found
No related merge requests found
import "./assets/stylesheets/hub.scss";
import moment from "moment-timezone";
import uuid from "uuid/v4";
import queryString from "query-string";
import { Socket } from "phoenix";
import { patchWebGLRenderingContext } from "./utils/webgl";
patchWebGLRenderingContext();
......@@ -50,6 +53,7 @@ import "./components/hud-controller";
import ReactDOM from "react-dom";
import React from "react";
import UIRoot from "./react-components/ui-root";
import HubChannel from "./utils/hub-channel";
import "./systems/personal-space-bubble";
import "./systems/app-mode";
......@@ -106,6 +110,7 @@ AFRAME.registerInputMappings(inputConfig, true);
const store = new Store();
const concurrentLoadDetector = new ConcurrentLoadDetector();
const hubChannel = new HubChannel(store);
concurrentLoadDetector.start();
......@@ -113,6 +118,7 @@ concurrentLoadDetector.start();
store.update({ profile: { ...generateDefaultProfile(), ...(store.state.profile || {}) } });
async function exitScene() {
hubChannel.disconnect();
const scene = document.querySelector("a-scene");
scene.renderer.animate(null); // Stop animation loop, TODO A-Frame should do this
document.body.removeChild(scene);
......@@ -186,6 +192,12 @@ async function enterScene(mediaStream, enterInVR, janusRoomId) {
});
if (!qsTruthy("offline")) {
document.body.addEventListener("connected", () => {
hubChannel.sendEntryEvent().then(() => {
store.update({ lastEnteredAt: moment().toJSON() });
});
});
scene.components["networked-scene"].connect();
if (mediaStream) {
......@@ -274,15 +286,32 @@ const onReady = async () => {
return;
}
const hubId = document.location.pathname.substring(1).split("/")[0];
// Connect to reticulum over phoenix channels to get hub info.
const hubId = qs.hub_id || 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}`);
const socketProtocol = document.location.protocol === "https:" ? "wss:" : "ws:";
const socketPort = qs.phx_port || document.location.port;
const socketHost = qs.phx_host || document.location.hostname;
const socketUrl = `${socketProtocol}//${socketHost}${socketPort ? `:${socketPort}` : ""}/socket`;
console.log(`Phoenix Channel URL: ${socketUrl}`);
const socket = new Socket(socketUrl, { params: { session_id: uuid() } });
socket.connect();
const channel = socket.channel(`hub:${hubId}`, {});
channel
.join()
.receive("ok", data => {
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}`);
hubChannel.setPhoenixChannel(channel);
})
.receive("error", res => console.error(res));
};
document.addEventListener("DOMContentLoaded", onReady);
......@@ -27,7 +27,8 @@ export const SCHEMA = {
properties: {
id: { type: "string", pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" },
profile: { $ref: "#/definitions/profile" },
lastUsedMicDeviceId: { type: "string" }
lastUsedMicDeviceId: { type: "string" },
lastEnteredAt: { type: "string" }
},
additionalProperties: false
......
import moment from "moment-timezone";
export default class HubChannel {
constructor(store) {
this.store = store;
}
setPhoenixChannel = channel => {
this.channel = channel;
};
sendEntryEvent = async () => {
if (!this.channel) {
console.warn("No phoenix channel initialized before room entry.");
return;
}
let entryDisplayType = "Screen";
if (navigator.getVRDisplays) {
const vrDisplay = (await navigator.getVRDisplays()).find(d => d.isPresenting);
if (vrDisplay) {
entryDisplayType = vrDisplay.displayName;
}
}
// This is fairly hacky, but gets the # of initial occupants
let initialOccupantCount = 0;
if (NAF.connection.adapter && NAF.connection.adapter.publisher) {
initialOccupantCount = NAF.connection.adapter.publisher.initialOccupants.length;
}
const entryTimingFlags = this.getEntryTimingFlags();
const entryEvent = {
...entryTimingFlags,
initialOccupantCount,
entryDisplayType,
userAgent: navigator.userAgent
};
this.channel.push("events:entered", entryEvent);
};
getEntryTimingFlags = () => {
const entryTimingFlags = { isNewDaily: true, isNewMonthly: true, isNewDayWindow: true, isNewMonthWindow: true };
if (!this.store.state.lastEnteredAt) {
return entryTimingFlags;
}
const lastEntered = moment(this.store.state.lastEnteredAt);
const lastEnteredPst = moment(lastEntered).tz("America/Los_Angeles");
const nowPst = moment().tz("America/Los_Angeles");
const dayWindowAgo = moment().subtract(1, "day");
const monthWindowAgo = moment().subtract(1, "month");
entryTimingFlags.isNewDaily =
lastEnteredPst.dayOfYear() !== nowPst.dayOfYear() || lastEnteredPst.year() !== nowPst.year();
entryTimingFlags.isNewMonthly =
lastEnteredPst.month() !== nowPst.month() || lastEnteredPst.year() !== nowPst.year();
entryTimingFlags.isNewDayWindow = lastEntered.isBefore(dayWindowAgo);
entryTimingFlags.isNewMonthWindow = lastEntered.isBefore(monthWindowAgo);
return entryTimingFlags;
};
disconnect = () => {
if (this.channel) {
this.channel.socket.disconnect();
}
};
}
......@@ -5304,6 +5304,16 @@ module-deps@^6.0.0:
through2 "^2.0.0"
xtend "^4.0.0"
moment-timezone@^0.5.14:
version "0.5.14"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.14.tgz#4eb38ff9538b80108ba467a458f3ed4268ccfcb1"
dependencies:
moment ">= 2.9.0"
"moment@>= 2.9.0", moment@^2.22.0:
version "2.22.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.0.tgz#7921ade01017dd45186e7fee5f424f0b8663a730"
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
......@@ -6010,6 +6020,10 @@ performance-now@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
phoenix@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/phoenix/-/phoenix-1.3.0.tgz#1df2c27f986ee295e37c9983ec28ebac1d7f4a3e"
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment