+ );
+ }
+ });
+
/**
* Manages the text entries in the chat entries view. This is split out from
* TextChatView so that scrolling can be managed more efficiently - this
@@ -81,21 +97,28 @@ loop.shared.views.TextChatView = (function(mozL10n) {
- );
- }
- });
-
- var StandaloneRoomContextView = React.createClass({
- propTypes: {
- dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
- receivingScreenShare: React.PropTypes.bool.isRequired,
- roomContextUrls: React.PropTypes.array,
- roomName: React.PropTypes.string,
- roomInfoFailure: React.PropTypes.string
- },
-
- getInitialState: function() {
- return {
- failureLogged: false
- };
- },
-
- _logFailure: function(message) {
- if (!this.state.failureLogged) {
- console.error(mozL10n.get(message));
- this.state.failureLogged = true;
- }
- },
-
- render: function() {
- // For failures, we currently just log the messages - UX doesn't want them
- // displayed on primary UI at the moment.
- if (this.props.roomInfoFailure === ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED) {
- this._logFailure("room_information_failure_unsupported_browser");
- return null;
- } else if (this.props.roomInfoFailure) {
- this._logFailure("room_information_failure_not_available");
- return null;
- }
-
- // We only support one item in the context Urls array for now.
- var roomContextUrl = (this.props.roomContextUrls &&
- this.props.roomContextUrls.length > 0) ?
- this.props.roomContextUrls[0] : null;
- return (
-
-
{this.props.roomName}
-
-
- );
- }
- });
-
var StandaloneRoomView = React.createClass({
mixins: [
Backbone.Events,
sharedMixins.MediaSetupMixin,
- sharedMixins.RoomsAudioMixin
+ sharedMixins.RoomsAudioMixin,
+ loop.store.StoreMixin("activeRoomStore")
],
propTypes: {
@@ -352,32 +258,11 @@ loop.standaloneRoomViews = (function(mozL10n) {
});
},
- componentWillMount: function() {
- this.listenTo(this.props.activeRoomStore, "change",
- this._onActiveRoomStateChanged);
- },
-
- /**
- * Handles a "change" event on the roomStore, and updates this.state
- * to match the store.
- *
- * @private
- */
- _onActiveRoomStateChanged: function() {
- var state = this.props.activeRoomStore.getStoreState();
- this.updateVideoDimensions(state.localVideoDimensions, state.remoteVideoDimensions);
- this.setState(state);
- },
-
componentDidMount: function() {
// Adding a class to the document body element from here to ease styling it.
document.body.classList.add("is-standalone-room");
},
- componentWillUnmount: function() {
- this.stopListening(this.props.activeRoomStore);
- },
-
/**
* Watches for when we transition to MEDIA_WAIT room state, so we can request
* user media access.
@@ -393,30 +278,16 @@ loop.standaloneRoomViews = (function(mozL10n) {
}));
}
- if (this.state.roomState !== ROOM_STATES.JOINED &&
- nextState.roomState === ROOM_STATES.JOINED) {
- // This forces the video size to update - creating the publisher
- // first, and then connecting to the session doesn't seem to set the
- // initial size correctly.
- this.updateVideoContainer();
- }
-
- if (nextState.roomState === ROOM_STATES.INIT ||
- nextState.roomState === ROOM_STATES.GATHER ||
- nextState.roomState === ROOM_STATES.READY) {
- this.resetDimensionsCache();
- }
-
- // When screen sharing stops.
- if (this.state.receivingScreenShare && !nextState.receivingScreenShare) {
- // Remove the custom screenshare styles on the remote camera.
- var node = this._getElement(".remote");
- node.removeAttribute("style");
- }
-
- if (this.state.receivingScreenShare != nextState.receivingScreenShare ||
- this.state.remoteVideoEnabled != nextState.remoteVideoEnabled) {
- this.updateVideoContainer();
+ // UX don't want to surface these errors (as they would imply the user
+ // needs to do something to fix them, when if they're having a conversation
+ // they just need to connect). However, we do want there to be somewhere to
+ // find reasonably easily, in case there's issues raised.
+ if (!this.state.roomInfoFailure && nextState.roomInfoFailure) {
+ if (nextState.roomInfoFailure === ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED) {
+ console.error(mozL10n.get("room_information_failure_unsupported_browser"));
+ } else {
+ console.error(mozL10n.get("room_information_failure_not_available"));
+ }
}
},
@@ -428,32 +299,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
this.props.dispatcher.dispatch(new sharedActions.LeaveRoom());
},
- /**
- * Wrapper for window.matchMedia so that we use an appropriate version
- * for the ui-showcase, which puts views inside of their own iframes.
- *
- * Currently, we use an icky hack, and the showcase conspires with
- * react-frame-component to set iframe.contentWindow.matchMedia onto
- * activeRoomStore. Once React context matures a bit (somewhere between
- * 0.14 and 1.0, apparently):
- *
- * https://facebook.github.io/react/blog/2015/02/24/streamlining-react-elements.html#solution-make-context-parent-based-instead-of-owner-based
- *
- * we should be able to use those to clean this up.
- *
- * @param queryString
- * @returns {MediaQueryList|null}
- * @private
- */
- _matchMedia: function(queryString) {
- if ("matchMedia" in this.state) {
- return this.state.matchMedia(queryString);
- } else if ("matchMedia" in window) {
- return window.matchMedia(queryString);
- }
- return null;
- },
-
/**
* Toggles streaming status for a given stream type.
*
@@ -467,131 +312,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
}));
},
- /**
- * Specifically updates the local camera stream size and position, depending
- * on the size and position of the remote video stream.
- * This method gets called from `updateVideoContainer`, which is defined in
- * the `MediaSetupMixin`.
- *
- * @param {Object} ratio Aspect ratio of the local camera stream
- */
- updateLocalCameraPosition: function(ratio) {
- // The local stream is a quarter of the remote stream.
- var LOCAL_STREAM_SIZE = 0.25;
- // The local stream overlaps the remote stream by a quarter of the local stream.
- var LOCAL_STREAM_OVERLAP = 0.25;
- // The minimum size of video height/width allowed by the sdk css.
- var SDK_MIN_SIZE = 48;
-
- var node = this._getElement(".local");
- var targetWidth;
-
- node.style.right = "auto";
- if (this._matchMedia("screen and (max-width:640px)").matches) {
- // For reduced screen widths, we just go for a fixed size and no overlap.
- targetWidth = 180;
- node.style.width = (targetWidth * ratio.width) + "px";
- node.style.height = (targetWidth * ratio.height) + "px";
- node.style.left = "auto";
- } else {
- // The local camera view should be a quarter of the size of the remote stream
- // and positioned to overlap with the remote stream at a quarter of its width.
-
- // Now position the local camera view correctly with respect to the remote
- // video stream or the screen share stream.
- var remoteVideoDimensions;
- var isScreenShare = this.state.receivingScreenShare;
- var videoDisplayed = isScreenShare ?
- this.state.screenShareVideoObject || this.props.screenSharePosterUrl :
- this.state.remoteSrcVideoObject || this.props.remotePosterUrl;
-
- if ((isScreenShare || this.shouldRenderRemoteVideo()) && videoDisplayed) {
- remoteVideoDimensions = this.getRemoteVideoDimensions(
- isScreenShare ? "screen" : "camera");
- } else {
- var remoteElement = this.getDOMNode().querySelector(".remote.focus-stream");
- if (!remoteElement) {
- return;
- }
- remoteVideoDimensions = {
- streamWidth: remoteElement.offsetWidth,
- offsetX: remoteElement.offsetLeft
- };
- }
-
- targetWidth = remoteVideoDimensions.streamWidth * LOCAL_STREAM_SIZE;
-
- var realWidth = targetWidth * ratio.width;
- var realHeight = targetWidth * ratio.height;
-
- // If we've hit the min size limits, then limit at the minimum.
- if (realWidth < SDK_MIN_SIZE) {
- realWidth = SDK_MIN_SIZE;
- realHeight = realWidth / ratio.width * ratio.height;
- }
- if (realHeight < SDK_MIN_SIZE) {
- realHeight = SDK_MIN_SIZE;
- realWidth = realHeight / ratio.height * ratio.width;
- }
-
- var offsetX = (remoteVideoDimensions.streamWidth + remoteVideoDimensions.offsetX);
- // The horizontal offset of the stream, and the width of the resulting
- // pillarbox, is determined by the height exponent of the aspect ratio.
- // Therefore we multiply the width of the local camera view by the height
- // ratio.
- node.style.left = (offsetX - (realWidth * LOCAL_STREAM_OVERLAP)) + "px";
- node.style.width = realWidth + "px";
- node.style.height = realHeight + "px";
- }
- },
-
- /**
- * Specifically updates the remote camera stream size and position, if
- * a screen share is being received. It is slaved from the position of the
- * local stream.
- * This method gets called from `updateVideoContainer`, which is defined in
- * the `MediaSetupMixin`.
- *
- * @param {Object} ratio Aspect ratio of the remote camera stream
- */
- updateRemoteCameraPosition: function(ratio) {
- // Nothing to do for screenshare
- if (!this.state.receivingScreenShare) {
- return;
- }
- // XXX For the time being, if we're a narrow screen, aka mobile, we don't display
- // the remote media (bug 1133534).
- if (this._matchMedia("screen and (max-width:640px)").matches) {
- return;
- }
-
- // 10px separation between the two streams.
- var LOCAL_REMOTE_SEPARATION = 10;
-
- var node = this._getElement(".remote");
- var localNode = this._getElement(".local");
-
- // Match the width to the local video.
- node.style.width = localNode.offsetWidth + "px";
-
- // The height is then determined from the aspect ratio
- var height = ((localNode.offsetWidth / ratio.width) * ratio.height);
- node.style.height = height + "px";
-
- node.style.right = "auto";
- node.style.bottom = "auto";
-
- // Now position the local camera view correctly with respect to the remote
- // video stream.
-
- // The top is measured from the top of the element down the screen,
- // so subtract the height of the video and the separation distance.
- node.style.top = (localNode.offsetTop - height - LOCAL_REMOTE_SEPARATION) + "px";
-
- // Match the left-hand sides.
- node.style.left = localNode.offsetLeft + "px";
- },
-
/**
* Checks if current room is active.
*
@@ -647,34 +367,29 @@ loop.standaloneRoomViews = (function(mozL10n) {
},
render: function() {
- var localStreamClasses = React.addons.classSet({
- local: true,
- "local-stream": true,
- "local-stream-audio": this.state.videoMuted
- });
+ var displayScreenShare = this.state.receivingScreenShare ||
+ this.props.screenSharePosterUrl;
var remoteStreamClasses = React.addons.classSet({
- "video_inner": true,
"remote": true,
- "focus-stream": !this.state.receivingScreenShare,
- "remote-inset-stream": this.state.receivingScreenShare
+ "focus-stream": !displayScreenShare
});
var screenShareStreamClasses = React.addons.classSet({
"screen": true,
- "focus-stream": this.state.receivingScreenShare,
- hide: !this.state.receivingScreenShare
+ "focus-stream": displayScreenShare
+ });
+
+ var mediaWrapperClasses = React.addons.classSet({
+ "media-wrapper": true,
+ "receiving-screen-share": displayScreenShare,
+ "showing-local-streams": this.state.localSrcVideoObject ||
+ this.props.localPosterUrl
});
- // XXX Temporarily showAlways = showRoomName = false for TextChatView
- // until bug 1168829 is completed.
return (
-
-
-
-
-
-
- {mozL10n.get("self_view_hidden_message")}
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ {mozL10n.get("self_view_hidden_message")}
+
+
+
-
+
+
+
+ showAlways={true}
+ showRoomName={true} />
+
+
+
+
form > input");
+
+ TestUtils.Simulate.keyDown(entryNode, {
+ key: "Enter",
+ which: 13
+ });
+
+ sinon.assert.notCalled(dispatcher.dispatch);
+ });
});
});
diff --git a/browser/components/loop/test/shared/views_test.js b/browser/components/loop/test/shared/views_test.js
index 3e26c904048d..166475cdaffe 100644
--- a/browser/components/loop/test/shared/views_test.js
+++ b/browser/components/loop/test/shared/views_test.js
@@ -765,6 +765,26 @@ describe("loop.shared.views", function() {
expect(node.classList.contains("disabled")).to.eql(true);
expect(node.hasAttribute("disabled")).to.eql(true);
});
+
+ it("should render the checkbox as checked when the prop is set", function() {
+ view = mountTestComponent({
+ checked: true
+ });
+
+ var checkbox = view.getDOMNode().querySelector(".checkbox");
+ expect(checkbox.classList.contains("checked")).eql(true);
+ });
+
+ it("should alter the render state when the props are changed", function() {
+ view = mountTestComponent({
+ checked: true
+ });
+
+ view.setProps({checked: false});
+
+ var checkbox = view.getDOMNode().querySelector(".checkbox");
+ expect(checkbox.classList.contains("checked")).eql(false);
+ });
});
describe("#_handleClick", function() {
diff --git a/browser/components/loop/test/standalone/standaloneRoomViews_test.js b/browser/components/loop/test/standalone/standaloneRoomViews_test.js
index d55a1b864ef1..13bc3ba5b320 100644
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js
+++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js
@@ -31,6 +31,7 @@ describe("loop.standaloneRoomViews", function() {
feedbackClient: {}
});
loop.store.StoreMixin.register({
+ activeRoomStore: activeRoomStore,
feedbackStore: feedbackStore,
textChatStore: textChatStore
});
@@ -45,126 +46,6 @@ describe("loop.standaloneRoomViews", function() {
sandbox.restore();
});
- describe("StandaloneRoomContextView", function() {
- beforeEach(function() {
- sandbox.stub(navigator.mozL10n, "get").returnsArg(0);
- });
-
- function mountTestComponent(extraProps) {
- var props = _.extend({
- dispatcher: dispatcher,
- receivingScreenShare: false
- }, extraProps);
- return TestUtils.renderIntoDocument(
- React.createElement(
- loop.standaloneRoomViews.StandaloneRoomContextView, props));
- }
-
- it("should display the room name if no failures are known", function() {
- var view = mountTestComponent({
- roomName: "Mike's room",
- receivingScreenShare: false
- });
-
- expect(view.getDOMNode().textContent).eql("Mike's room");
- });
-
- it("should log an unsupported browser message if crypto is unsupported", function() {
- var view = mountTestComponent({
- roomName: "Mark's room",
- roomInfoFailure: ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED
- });
-
- sinon.assert.called(console.error);
- sinon.assert.calledWithMatch(console.error, sinon.match("unsupported"));
- });
-
- it("should display a general error message for any other failure", function() {
- var view = mountTestComponent({
- roomName: "Mark's room",
- roomInfoFailure: ROOM_INFO_FAILURES.NO_DATA
- });
-
- sinon.assert.called(console.error);
- sinon.assert.calledWithMatch(console.error, sinon.match("not_available"));
- });
-
- it("should display context information if a url is supplied", function() {
- var view = mountTestComponent({
- roomName: "Mike's room",
- roomContextUrls: [{
- description: "Mark's super page",
- location: "http://invalid.com",
- thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
- }]
- });
-
- expect(view.getDOMNode().querySelector(".standalone-context-url")).not.eql(null);
- });
-
- it("should format the url for display", function() {
- sandbox.stub(sharedUtils, "formatURL").returns({
- location: "location",
- hostname: "hostname"
- });
-
- var view = mountTestComponent({
- roomName: "Mike's room",
- roomContextUrls: [{
- description: "Mark's super page",
- location: "http://invalid.com",
- thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
- }]
- });
-
- expect(view.getDOMNode()
- .querySelector(".standalone-context-url-description-wrapper > a").textContent)
- .eql("hostname");
- });
-
- it("should not display context information if no urls are supplied", function() {
- var view = mountTestComponent({
- roomName: "Mike's room"
- });
-
- expect(view.getDOMNode().querySelector(".standalone-context-url")).eql(null);
- });
-
- it("should dispatch a RecordClick action when the link is clicked", function() {
- var view = mountTestComponent({
- roomName: "Mark's room",
- roomContextUrls: [{
- description: "Mark's super page",
- location: "http://invalid.com",
- thumbnail: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
- }]
- });
-
- TestUtils.Simulate.click(view.getDOMNode()
- .querySelector(".standalone-context-url-description-wrapper > a"));
-
- sinon.assert.calledOnce(dispatcher.dispatch);
- sinon.assert.calledWithExactly(dispatcher.dispatch,
- new sharedActions.RecordClick({
- linkInfo: "Shared URL"
- }));
- });
-
- it("should display the default favicon when no thumbnail is available", function() {
- var view = mountTestComponent({
- roomName: "Mike's room",
- roomContextUrls: [{
- description: "Mark's super page",
- location: "http://invalid.com",
- thumbnail: ""
- }]
- });
-
- expect(view.getDOMNode().querySelector(".standalone-context-url > img").src)
- .to.match(/shared\/img\/icons-16x16.svg#globe$/);
- });
- });
-
describe("StandaloneRoomHeader", function() {
function mountTestComponent() {
return TestUtils.renderIntoDocument(
@@ -224,43 +105,6 @@ describe("loop.standaloneRoomViews", function() {
expectActionDispatched(view);
});
-
- it("should updateVideoContainer when the JOINED state is entered", function() {
- activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
-
- var view = mountTestComponent();
-
- sandbox.stub(view, "updateVideoContainer");
-
- activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
-
- sinon.assert.calledOnce(view.updateVideoContainer);
- });
-
- it("should updateVideoContainer when the JOINED state is re-entered", function() {
- activeRoomStore.setStoreState({roomState: ROOM_STATES.ENDED});
-
- var view = mountTestComponent();
-
- sandbox.stub(view, "updateVideoContainer");
-
- activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
-
- sinon.assert.calledOnce(view.updateVideoContainer);
- });
-
- it("should reset the video dimensions cache when the gather state is entered", function() {
- activeRoomStore.setStoreState({roomState: ROOM_STATES.SESSION_CONNECTED});
-
- var view = mountTestComponent();
-
- activeRoomStore.setStoreState({roomState: ROOM_STATES.GATHER});
-
- expect(view._videoDimensionsCache).eql({
- local: {},
- remote: {}
- });
- });
});
describe("#publishStream", function() {
@@ -297,252 +141,6 @@ describe("loop.standaloneRoomViews", function() {
});
});
- describe("Local Stream Size Position", function() {
- var view, localElement;
-
- beforeEach(function() {
- sandbox.stub(window, "matchMedia").returns({
- matches: false
- });
- activeRoomStore.setStoreState({
- remoteSrcVideoObject: {},
- remoteVideoEnabled: true
- });
- view = mountTestComponent();
- localElement = view._getElement(".local");
- });
-
- it("should be a quarter of the width of the main stream", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 640,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(localElement.style.width).eql("160px");
- expect(localElement.style.height).eql("120px");
- });
-
- it("should be a quarter of the width of the remote view element when there is no stream", function() {
- activeRoomStore.setStoreState({
- remoteSrcVideoObject: null,
- remoteVideoEnabled: false
- });
-
- sandbox.stub(view, "getDOMNode").returns({
- querySelector: function(selector) {
- if (selector === ".local") {
- return localElement;
- }
-
- return {
- offsetWidth: 640,
- offsetLeft: 0
- };
- }
- });
-
- view.updateLocalCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(localElement.style.width).eql("160px");
- expect(localElement.style.height).eql("120px");
- });
-
- it("should be a quarter of the width reduced for aspect ratio", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 640,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 0.75,
- height: 1
- });
-
- expect(localElement.style.width).eql("120px");
- expect(localElement.style.height).eql("160px");
- });
-
- it("should ensure the height is a minimum of 48px", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 180,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(localElement.style.width).eql("64px");
- expect(localElement.style.height).eql("48px");
- });
-
- it("should ensure the width is a minimum of 48px", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 180,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 0.75,
- height: 1
- });
-
- expect(localElement.style.width).eql("48px");
- expect(localElement.style.height).eql("64px");
- });
-
- it("should position the stream to overlap the main stream by a quarter", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 640,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(localElement.style.width).eql("160px");
- expect(localElement.style.left).eql("600px");
- });
-
- it("should position the stream to overlap the remote view element when there is no stream", function() {
- activeRoomStore.setStoreState({
- remoteSrcVideoObject: null,
- remoteVideoEnabled: false
- });
-
- sandbox.stub(view, "getDOMNode").returns({
- querySelector: function(selector) {
- if (selector === ".local") {
- return localElement;
- }
-
- return {
- offsetWidth: 640,
- offsetLeft: 0
- };
- }
- });
-
- view.updateLocalCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(localElement.style.width).eql("160px");
- expect(localElement.style.left).eql("600px");
- });
-
- it("should position the stream to overlap the main stream by a quarter when the aspect ratio is vertical", function() {
- sandbox.stub(view, "getRemoteVideoDimensions").returns({
- streamWidth: 640,
- offsetX: 0
- });
-
- view.updateLocalCameraPosition({
- width: 0.75,
- height: 1
- });
-
- expect(localElement.style.width).eql("120px");
- expect(localElement.style.left).eql("610px");
- });
- });
-
- describe("Remote Stream Size Position", function() {
- var view, localElement, remoteElement;
-
- beforeEach(function() {
- sandbox.stub(window, "matchMedia").returns({
- matches: false
- });
- view = mountTestComponent();
-
- localElement = {
- style: {}
- };
- remoteElement = {
- style: {},
- removeAttribute: sinon.spy()
- };
-
- sandbox.stub(view, "_getElement", function(className) {
- return className === ".local" ? localElement : remoteElement;
- });
-
- view.setState({"receivingScreenShare": true});
- });
-
- it("should do nothing if not receiving screenshare", function() {
- view.setState({"receivingScreenShare": false});
- remoteElement.style.width = "10px";
-
- view.updateRemoteCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(remoteElement.style.width).eql("10px");
- });
-
- it("should be the same width as the local video", function() {
- localElement.offsetWidth = 100;
-
- view.updateRemoteCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(remoteElement.style.width).eql("100px");
- });
-
- it("should be the same left edge as the local video", function() {
- localElement.offsetLeft = 50;
-
- view.updateRemoteCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(remoteElement.style.left).eql("50px");
- });
-
- it("should have a height determined by the aspect ratio", function() {
- localElement.offsetWidth = 100;
-
- view.updateRemoteCameraPosition({
- width: 1,
- height: 0.75
- });
-
- expect(remoteElement.style.height).eql("75px");
- });
-
- it("should have the top be set such that the bottom is 10px above the local video", function() {
- localElement.offsetWidth = 100;
- localElement.offsetTop = 200;
-
- view.updateRemoteCameraPosition({
- width: 1,
- height: 0.75
- });
-
- // 200 (top) - 75 (height) - 10 (spacing) = 115
- expect(remoteElement.style.top).eql("115px");
- });
-
- });
-
describe("#render", function() {
var view;
@@ -827,14 +425,14 @@ describe("loop.standaloneRoomViews", function() {
});
describe("Mute", function() {
- it("should render local media as audio-only if video is muted",
+ it("should render a local avatar if video is muted",
function() {
activeRoomStore.setStoreState({
roomState: ROOM_STATES.SESSION_CONNECTED,
videoMuted: true
});
- expect(view.getDOMNode().querySelector(".local-stream-audio"))
+ expect(view.getDOMNode().querySelector(".local .avatar"))
.not.eql(null);
});
diff --git a/browser/components/loop/ui/ui-showcase.js b/browser/components/loop/ui/ui-showcase.js
index 68896a31fda5..c8faa8f35ba6 100644
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -270,6 +270,7 @@
}));
loop.store.StoreMixin.register({
+ activeRoomStore: activeRoomStore,
conversationStore: conversationStore,
feedbackStore: feedbackStore,
textChatStore: textChatStore
@@ -971,6 +972,21 @@
localPosterUrl: "sample-img/video-screen-local.png",
remotePosterUrl: "sample-img/video-screen-remote.png"})
)
+ ),
+
+ React.createElement(FramedExample, {width: 600, height: 480,
+ onContentsRendered: updatingSharingRoomStore.forcedUpdate,
+ summary: "Standalone room convo (has-participants, receivingScreenShare, 600x480)"},
+ React.createElement("div", {className: "standalone", cssClass: "standalone"},
+ React.createElement(StandaloneRoomView, {
+ dispatcher: dispatcher,
+ activeRoomStore: updatingSharingRoomStore,
+ roomState: ROOM_STATES.HAS_PARTICIPANTS,
+ isFirefox: true,
+ localPosterUrl: "sample-img/video-screen-local.png",
+ remotePosterUrl: "sample-img/video-screen-remote.png",
+ screenSharePosterUrl: "sample-img/video-screen-terminal.png"})
+ )
)
),
diff --git a/browser/components/loop/ui/ui-showcase.jsx b/browser/components/loop/ui/ui-showcase.jsx
index a5216b73e7d9..485db13dfede 100644
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -270,6 +270,7 @@
}));
loop.store.StoreMixin.register({
+ activeRoomStore: activeRoomStore,
conversationStore: conversationStore,
feedbackStore: feedbackStore,
textChatStore: textChatStore
@@ -972,6 +973,21 @@
remotePosterUrl="sample-img/video-screen-remote.png" />