fune/browser/components/loop/ui/ui-showcase.jsx

1899 lines
74 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global Frame:false uncaughtError:true fakeManyContacts:true fakeFewerContacts:true */
(function() {
"use strict";
// Stop the default init functions running to avoid conflicts.
document.removeEventListener("DOMContentLoaded", loop.panel.init);
document.removeEventListener("DOMContentLoaded", loop.conversation.init);
var sharedActions = loop.shared.actions;
// 1. Desktop components
// 1.1 Panel
var AvailabilityDropdown = loop.panel.AvailabilityDropdown;
var PanelView = loop.panel.PanelView;
var SignInRequestView = loop.panel.SignInRequestView;
var ContactDetailsForm = loop.contacts.ContactDetailsForm;
var ContactDropdown = loop.contacts.ContactDropdown;
var ContactDetail = loop.contacts.ContactDetail;
var GettingStartedView = loop.panel.GettingStartedView;
// 1.2. Conversation Window
var AcceptCallView = loop.conversationViews.AcceptCallView;
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
var OngoingConversationView = loop.conversationViews.OngoingConversationView;
var DirectCallFailureView = loop.conversationViews.DirectCallFailureView;
var DesktopRoomEditContextView = loop.roomViews.DesktopRoomEditContextView;
var RoomFailureView = loop.roomViews.RoomFailureView;
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
// 2. Standalone webapp
var HomeView = loop.webapp.HomeView;
var UnsupportedBrowserView = loop.webapp.UnsupportedBrowserView;
var UnsupportedDeviceView = loop.webapp.UnsupportedDeviceView;
var StandaloneRoomView = loop.standaloneRoomViews.StandaloneRoomView;
var StandaloneHandleUserAgentView = loop.standaloneRoomViews.StandaloneHandleUserAgentView;
// 3. Shared components
var ConversationToolbar = loop.shared.views.ConversationToolbar;
var FeedbackView = loop.feedbackViews.FeedbackView;
var Checkbox = loop.shared.views.Checkbox;
var TextChatView = loop.shared.views.chat.TextChatView;
// Store constants
var ROOM_STATES = loop.store.ROOM_STATES;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
// Local helpers
function returnTrue() {
return true;
}
function returnFalse() {
return false;
}
function noop(){}
// We save the visibility change listeners so that we can fake an event
// to the panel once we've loaded all the views.
var visibilityListeners = [];
var rootObject = window;
rootObject.document.addEventListener = function(eventName, func) {
if (eventName === "visibilitychange") {
visibilityListeners.push(func);
}
window.addEventListener(eventName, func);
};
rootObject.document.removeEventListener = function(eventName, func) {
if (eventName === "visibilitychange") {
var index = visibilityListeners.indexOf(func);
visibilityListeners.splice(index, 1);
}
window.removeEventListener(eventName, func);
};
loop.shared.mixins.setRootObject(rootObject);
var dispatcher = new loop.Dispatcher();
var MockSDK = function() {
dispatcher.register(this, [
"setupStreamElements"
]);
};
MockSDK.prototype = {
setupStreamElements: function() {
// Dummy function to stop warnings.
},
sendTextChatMessage: function(actionData) {
dispatcher.dispatch(new loop.shared.actions.ReceivedTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: actionData.message,
receivedTimestamp: actionData.sentTimestamp
}));
}
};
var mockSDK = new MockSDK();
/**
* Every view that uses an activeRoomStore needs its own; if they shared
* an active store, they'd interfere with each other.
*
* @param options
* @returns {loop.store.ActiveRoomStore}
*/
function makeActiveRoomStore(options) {
var roomDispatcher = new loop.Dispatcher();
var store = new loop.store.ActiveRoomStore(roomDispatcher, {
mozLoop: navigator.mozLoop,
sdkDriver: mockSDK
});
if (!("remoteVideoEnabled" in options)) {
options.remoteVideoEnabled = true;
}
if (!("mediaConnected" in options)) {
options.mediaConnected = true;
}
store.setStoreState({
mediaConnected: options.mediaConnected,
remoteVideoEnabled: options.remoteVideoEnabled,
roomName: "A Very Long Conversation Name",
roomState: options.roomState,
used: !!options.roomUsed,
videoMuted: !!options.videoMuted
});
store.forcedUpdate = function forcedUpdate(contentWindow) {
// Since this is called by setTimeout, we don't want to lose any
// exceptions if there's a problem and we need to debug, so...
try {
// the dimensions here are taken from the poster images that we're
// using, since they give the <video> elements their initial intrinsic
// size. This ensures that the right aspect ratios are calculated.
// These are forced to 640x480, because it makes it visually easy to
// validate that the showcase looks like the real app on a chine
// (eg MacBook Pro) where that is the default camera resolution.
var newStoreState = {
localVideoDimensions: {
camera: {height: 480, orientation: 0, width: 640}
},
mediaConnected: options.mediaConnected,
receivingScreenShare: !!options.receivingScreenShare,
remoteVideoDimensions: {
camera: {height: 480, orientation: 0, width: 640}
},
remoteVideoEnabled: options.remoteVideoEnabled,
// Override the matchMedia, this is so that the correct version is
// used for the frame.
//
// Currently, we use an icky hack, and the showcase conspires with
// react-frame-component to set iframe.contentWindow.matchMedia onto
// the store. 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.
matchMedia: contentWindow.matchMedia.bind(contentWindow),
roomState: options.roomState,
videoMuted: !!options.videoMuted
};
if (options.receivingScreenShare) {
// Note that the image we're using had to be scaled a bit, and
// it still ended up a bit narrower than the live thing that
// WebRTC sends; presumably a different scaling algorithm.
// For showcase purposes, this shouldn't matter much, as the sizes
// of things being shared will be fairly arbitrary.
newStoreState.remoteVideoDimensions.screen =
{height: 456, orientation: 0, width: 641};
}
store.setStoreState(newStoreState);
} catch (ex) {
console.error("exception in forcedUpdate:", ex);
}
};
return store;
}
var activeRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
});
var joinedRoomStore = makeActiveRoomStore({
mediaConnected: false,
roomState: ROOM_STATES.JOINED,
remoteVideoEnabled: false
});
var loadingRemoteVideoRoomStore = makeActiveRoomStore({
mediaConnected: false,
roomState: ROOM_STATES.HAS_PARTICIPANTS,
remoteSrcMediaElement: false
});
var readyRoomStore = makeActiveRoomStore({
mediaConnected: false,
roomState: ROOM_STATES.READY
});
var updatingActiveRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
});
var updatingMobileActiveRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
});
var localFaceMuteRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
videoMuted: true
});
var remoteFaceMuteRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
remoteVideoEnabled: false,
mediaConnected: true
});
var updatingSharingRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
receivingScreenShare: true
});
var updatingSharingRoomMobileStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
receivingScreenShare: true
});
var loadingRemoteLoadingScreenStore = makeActiveRoomStore({
mediaConnected: false,
receivingScreenShare: true,
roomState: ROOM_STATES.HAS_PARTICIPANTS,
remoteSrcMediaElement: false
});
var loadingScreenSharingRoomStore = makeActiveRoomStore({
receivingScreenShare: true,
roomState: ROOM_STATES.HAS_PARTICIPANTS
});
/* Set up the stores for pending screen sharing */
loadingScreenSharingRoomStore.receivingScreenShare({
receiving: true,
srcMediaElement: false
});
loadingRemoteLoadingScreenStore.receivingScreenShare({
receiving: true,
srcMediaElement: false
});
var fullActiveRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.FULL
});
var failedRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.FAILED
});
var endedRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.ENDED,
roomUsed: true
});
var invitationRoomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: makeActiveRoomStore({
roomState: ROOM_STATES.INIT
})
});
var roomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
})
});
var desktopRoomStoreLoading = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
mediaConnected: false,
remoteSrcMediaElement: false
})
});
var desktopRoomStoreMedium = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
})
});
var desktopRoomStoreLarge = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
})
});
var desktopLocalFaceMuteActiveRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
videoMuted: true
});
var desktopLocalFaceMuteRoomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: desktopLocalFaceMuteActiveRoomStore
});
var desktopRemoteFaceMuteActiveRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS,
remoteVideoEnabled: false,
mediaConnected: true
});
var desktopRemoteFaceMuteRoomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
activeRoomStore: desktopRemoteFaceMuteActiveRoomStore
});
var textChatStore = new loop.store.TextChatStore(dispatcher, {
sdkDriver: mockSDK
});
/**
* Every view that uses an conversationStore needs its own; if they shared
* a conversation store, they'd interfere with each other.
*
* @param options
* @returns {loop.store.ConversationStore}
*/
function makeConversationStore() {
var roomDispatcher = new loop.Dispatcher();
var store = new loop.store.ConversationStore(dispatcher, {
client: {},
mozLoop: navigator.mozLoop,
sdkDriver: mockSDK
});
store.forcedUpdate = function forcedUpdate(contentWindow) {
// Since this is called by setTimeout, we don't want to lose any
// exceptions if there's a problem and we need to debug, so...
try {
var newStoreState = {
// Override the matchMedia, this is so that the correct version is
// used for the frame.
//
// Currently, we use an icky hack, and the showcase conspires with
// react-frame-component to set iframe.contentWindow.matchMedia onto
// the store. 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.
matchMedia: contentWindow.matchMedia.bind(contentWindow)
};
store.setStoreState(newStoreState);
} catch (ex) {
console.error("exception in forcedUpdate:", ex);
}
};
return store;
}
var conversationStores = [];
for (var index = 0; index < 5; index++) {
conversationStores[index] = makeConversationStore();
}
conversationStores[0].setStoreState({
callStateReason: FAILURE_DETAILS.NO_MEDIA
});
conversationStores[1].setStoreState({
callStateReason: FAILURE_DETAILS.USER_UNAVAILABLE,
contact: fakeManyContacts[0]
});
// Update the text chat store with the room info.
textChatStore.updateRoomInfo(new sharedActions.UpdateRoomInfo({
roomName: "A Very Long Conversation Name",
roomUrl: "http://showcase",
urls: [{
description: "A wonderful page!",
location: "http://wonderful.invalid"
// use the fallback thumbnail
}]
}));
textChatStore.setStoreState({textChatEnabled: true});
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "Rheet!",
sentTimestamp: "2015-06-23T22:21:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "Hello",
receivedTimestamp: "2015-06-23T23:24:45.590Z"
}));
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "Nowforareallylongwordwithoutspacesorpunctuationwhichshouldcause" +
"linewrappingissuesifthecssiswrong",
sentTimestamp: "2015-06-23T22:23:45.590Z"
}));
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "Check out this menu from DNA Pizza:" +
" http://example.com/DNA/pizza/menu/lots-of-different-kinds-of-pizza/" +
"%8D%E0%B8%88%E0%B8%A1%E0%B8%A3%E0%8D%E0%B8%88%E0%B8%A1%E0%B8%A3%E0%",
sentTimestamp: "2015-06-23T22:23:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "That avocado monkey-brains pie sounds tasty!",
receivedTimestamp: "2015-06-23T22:25:45.590Z"
}));
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "What time should we meet?",
sentTimestamp: "2015-06-23T22:27:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.shared.utils.CHAT_CONTENT_TYPES.TEXT,
message: "8:00 PM",
receivedTimestamp: "2015-06-23T22:27:45.590Z"
}));
loop.store.StoreMixin.register({
activeRoomStore: activeRoomStore,
conversationStore: conversationStores[0],
textChatStore: textChatStore
});
// Local mocks
var mockMozLoopNoRooms = _.cloneDeep(navigator.mozLoop);
mockMozLoopNoRooms.rooms.getAll = function(version, callback) {
callback(null, []);
};
var mockMozLoopNoRoomsNoContext = _.cloneDeep(navigator.mozLoop);
mockMozLoopNoRoomsNoContext.getSelectedTabMetadata = function(){};
mockMozLoopNoRoomsNoContext.rooms.getAll = function(version, callback) {
callback(null, []);
};
var roomStoreNoRooms = new loop.store.RoomStore(new loop.Dispatcher(), {
mozLoop: mockMozLoopNoRooms,
activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
mozLoop: mockMozLoopNoRooms,
sdkDriver: mockSDK
})
});
/* xxx this is asynchronous - if start seeing things pending then this is the culprit */
roomStoreNoRooms.setStoreState({
pendingInitialRetrieval: false
});
var roomStoreNoRoomsPending = new loop.store.RoomStore(new loop.Dispatcher(), {
mozLoop: mockMozLoopNoRooms,
activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
mozLoop: mockMozLoopNoRooms,
sdkDriver: mockSDK
})
});
var mockMozLoopLoggedIn = _.cloneDeep(navigator.mozLoop);
mockMozLoopLoggedIn.userProfile = {
email: "text@example.com",
uid: "0354b278a381d3cb408bb46ffc01266"
};
var mockMozLoopLoggedInNoContext = _.cloneDeep(navigator.mozLoop);
mockMozLoopLoggedInNoContext.getSelectedTabMetadata = function(){};
mockMozLoopLoggedInNoContext.userProfile = _.cloneDeep(mockMozLoopLoggedIn.userProfile);
var mockMozLoopLoggedInLongEmail = _.cloneDeep(navigator.mozLoop);
mockMozLoopLoggedInLongEmail.userProfile = {
email: "reallyreallylongtext@example.com",
uid: "0354b278a381d3cb408bb46ffc01266"
};
var mockMozLoopRooms = _.extend({}, navigator.mozLoop);
var mozLoopNoContacts = _.cloneDeep(navigator.mozLoop);
mozLoopNoContacts.contacts.getAll = function(callback) {
callback(null, []);
};
mozLoopNoContacts.userProfile = {
email: "reallyreallylongtext@example.com",
uid: "0354b278a381d3cb408bb46ffc01266"
};
mozLoopNoContacts.contacts.getAll = function(callback) {
callback(null, []);
};
var mozLoopNoContactsFilter = _.cloneDeep(navigator.mozLoop);
mozLoopNoContactsFilter.userProfile = {
email: "reallyreallylongtext@example.com",
uid: "0354b278a381d3cb408bb46ffc01266"
};
mozLoopNoContactsFilter.contacts.getAll = function(callback) {
callback(null, fakeFewerContacts); // Defined in fake-mozLoop.js.
};
var firstTimeUseMozLoop = _.cloneDeep(navigator.mozLoop);
firstTimeUseMozLoop.getLoopPref = function(prop) {
if (prop === "gettingStarted.seen") {
return false;
}
return true;
};
var mockContact = {
name: ["Mr Smith"],
email: [{
value: "smith@invalid.com"
}]
};
var mockClient = {
requestCallUrlInfo: noop
};
var mockWebSocket = new loop.CallConnectionWebSocket({
url: "fake",
callId: "fakeId",
websocketToken: "fakeToken"
});
var notifications = new loop.shared.models.NotificationCollection();
var errNotifications = new loop.shared.models.NotificationCollection();
errNotifications.add({
level: "error",
message: "Could Not Authenticate",
details: "Did you change your password?",
detailsButtonLabel: "Retry"
});
var SVGIcon = React.createClass({
propTypes: {
shapeId: React.PropTypes.string.isRequired,
size: React.PropTypes.string.isRequired
},
render: function() {
var sizeUnit = this.props.size.split("x");
return (
<img className="svg-icon"
height={sizeUnit[1]}
src={"../content/shared/img/icons-" + this.props.size + ".svg#" + this.props.shapeId}
width={sizeUnit[0]} />
);
}
});
var SVGIcons = React.createClass({
propTypes: {
size: React.PropTypes.string.isRequired
},
shapes: {
"10x10": ["close", "close-active", "close-disabled", "dropdown",
"dropdown-white", "dropdown-active", "dropdown-disabled", "edit",
"edit-active", "edit-disabled", "edit-white", "expand", "expand-active",
"expand-disabled", "minimize", "minimize-active", "minimize-disabled",
"settings-cog-grey", "settings-cog-white"
],
"14x14": ["audio", "audio-active", "audio-disabled", "facemute",
"facemute-active", "facemute-disabled", "hangup", "hangup-active",
"hangup-disabled", "hello", "hello-hover", "hello-active",
"incoming", "incoming-active", "incoming-disabled",
"link", "link-active", "link-disabled", "mute", "mute-active",
"mute-disabled", "pause", "pause-active", "pause-disabled", "video",
"video-white", "video-active", "video-disabled", "volume", "volume-active",
"volume-disabled", "clear", "magnifier"
],
"16x16": ["add", "add-hover", "add-active", "audio", "audio-hover", "audio-active",
"block", "block-red", "block-hover", "block-active", "contacts", "contacts-hover",
"contacts-active", "copy", "checkmark", "delete", "globe", "google", "google-hover",
"google-active", "history", "history-hover", "history-active", "leave",
"screen-white", "screenmute-white", "settings", "settings-hover", "settings-active",
"share-darkgrey", "tag", "tag-hover", "tag-active", "trash", "unblock",
"unblock-hover", "unblock-active", "video", "video-hover", "video-active",
"status-available", "status-unavailable"
]
},
render: function() {
var icons = this.shapes[this.props.size].map(function(shapeId, i) {
return (
<li className="svg-icon-entry" key={this.props.size + "-" + i}>
<p><SVGIcon shapeId={shapeId} size={this.props.size} /></p>
<p>{shapeId}</p>
</li>
);
}, this);
return (
<ul className="svg-icon-list">{icons}</ul>
);
}
});
var FramedExample = React.createClass({
propTypes: {
children: React.PropTypes.element,
cssClass: React.PropTypes.string,
dashed: React.PropTypes.bool,
height: React.PropTypes.number,
onContentsRendered: React.PropTypes.func,
summary: React.PropTypes.string.isRequired,
width: React.PropTypes.number
},
makeId: function(prefix) {
return (prefix || "") + this.props.summary.toLowerCase().replace(/\s/g, "-");
},
render: function() {
var height = this.props.height;
var width = this.props.width;
// make room for a 1-pixel border on each edge
if (this.props.dashed) {
height += 2;
width += 2;
}
var cx = React.addons.classSet;
return (
<div className="example">
<h3 id={this.makeId()}>
{this.props.summary}
<a href={this.makeId("#")}>&nbsp;</a>
</h3>
<div className="comp">
<Frame className={cx({dashed: this.props.dashed})}
cssClass={this.props.cssClass}
height={height}
onContentsRendered={this.props.onContentsRendered}
width={width}>
{this.props.children}
</Frame>
</div>
</div>
);
}
});
var Section = React.createClass({
propTypes: {
children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element),
React.PropTypes.element
]).isRequired,
className: React.PropTypes.string,
name: React.PropTypes.string.isRequired
},
render: function() {
return (
<section className={this.props.className} id={this.props.name}>
<h1>{this.props.name}</h1>
{this.props.children}
</section>
);
}
});
var ShowCase = React.createClass({
propTypes: {
children: React.PropTypes.arrayOf(React.PropTypes.element).isRequired
},
getInitialState: function() {
// We assume for now that rtl is the only query parameter.
//
// Note: this check is repeated in react-frame-component to save passing
// rtlMode down the props tree.
var rtlMode = document.location.search === "?rtl=1";
return {
rtlMode: rtlMode
};
},
_handleCheckboxChange: function(newState) {
var newLocation = "";
if (newState.checked) {
newLocation = document.location.href.split("#")[0];
newLocation += "?rtl=1";
} else {
newLocation = document.location.href.split("?")[0];
}
newLocation += document.location.hash;
document.location = newLocation;
},
render: function() {
if (this.state.rtlMode) {
document.documentElement.setAttribute("lang", "ar");
document.documentElement.setAttribute("dir", "rtl");
}
return (
<div className="showcase">
<header>
<h1>Loop UI Components Showcase</h1>
<Checkbox checked={this.state.rtlMode} label="RTL mode?"
onChange={this._handleCheckboxChange} />
<nav className="showcase-menu">{
React.Children.map(this.props.children, function(section) {
return (
<a className="btn btn-info" href={"#" + section.props.name}>
{section.props.name}
</a>
);
})
}</nav>
</header>
{this.props.children}
</div>
);
}
});
var App = React.createClass({
render: function() {
return (
<ShowCase>
<Section name="PanelView">
<p className="note">
<strong>Note:</strong> 332px wide.
</p>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="First time experience view"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={firstTimeUseMozLoop}
notifications={notifications}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Re-sign-in view"
width={332}>
<div className="panel">
<SignInRequestView mozLoop={mockMozLoopLoggedIn} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Room list"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
notifications={notifications}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Room list (No Context)"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedInNoContext}
notifications={notifications}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Room list (no rooms)"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopNoRooms}
notifications={notifications}
roomStore={roomStoreNoRooms} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Room list (no rooms and no context)"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopNoRoomsNoContext}
notifications={notifications}
roomStore={roomStoreNoRooms} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Room list (loading view)"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopNoRoomsNoContext}
notifications={notifications}
roomStore={roomStoreNoRoomsPending} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact list tab"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact list tab (no search filter)"
width={332}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mozLoopNoContactsFilter}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact list tab long email"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedInLongEmail}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact list tab (no contacts)"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mozLoopNoContacts}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Error Notification"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={navigator.mozLoop}
notifications={errNotifications}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Error Notification - authenticated"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
notifications={errNotifications}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact import success"
width={330}>
<div className="panel">
<PanelView dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
notifications={new loop.shared.models.NotificationCollection([{level: "success", message: "Import success"}])}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact import error"
width={330}>
<div className="panel">
<PanelView dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
notifications={new loop.shared.models.NotificationCollection([{level: "error", message: "Import error"}])}
roomStore={roomStore}
selectedTab="contacts" />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact Form - Add"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
initialSelectedTabComponent="contactAdd"
mozLoop={mockMozLoopLoggedIn}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts"
userProfile={{email: "test@example.com"}} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={410}
summary="Contact Form - Edit"
width={330}>
<div className="panel">
<PanelView client={mockClient}
dispatcher={dispatcher}
initialSelectedTabComponent="contactEdit"
mozLoop={mockMozLoopLoggedIn}
notifications={notifications}
roomStore={roomStore}
selectedTab="contacts"
userProfile={{email: "test@example.com"}} />
</div>
</FramedExample>
</Section>
<Section name="Availability Dropdown">
<p className="note">
<strong>Note:</strong> 332px wide.
</p>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={200}
summary="AvailabilityDropdown"
width={332}>
<div className="panel">
<AvailabilityDropdown />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={200}
summary="AvailabilityDropdown Expanded"
width={332}>
<div className="panel force-menu-show" style={{"height": "100%", "paddingTop": "50px"}}>
<AvailabilityDropdown />
</div>
</FramedExample>
</Section>
<Section name="ContactDetail">
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={50}
summary="ContactDetail"
width={334}>
<div className="panel force-menu-show">
<ContactDetail contact={fakeManyContacts[0]}
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
handleContactAction={function() {}} />
</div>
</FramedExample>
</Section>
<Section name="ContactDropdown">
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={272}
summary="ContactDropdown not blocked can edit"
width={300}>
<div className="panel">
<ContactDropdown blocked={false}
canEdit={true}
eventPosY={0}
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
handleAction={function () {}} />
</div>
</FramedExample>
<FramedExample cssClass="fx-embedded-panel"
dashed={true}
height={272}
summary="ContactDropdown blocked can't edit"
width={300}>
<div className="panel">
<ContactDropdown blocked={true}
canEdit={false}
eventPosY={0}
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
handleAction={function () {}} />
</div>
</FramedExample>
</Section>
<Section name="AcceptCallView">
<FramedExample dashed={true}
height={272}
summary="Default / incoming video call"
width={332}>
<div className="fx-embedded">
<AcceptCallView callType={CALL_TYPES.AUDIO_VIDEO}
callerId="Mr Smith"
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={272}
summary="Default / incoming audio only call"
width={332}>
<div className="fx-embedded">
<AcceptCallView callType={CALL_TYPES.AUDIO_ONLY}
callerId="Mr Smith"
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn} />
</div>
</FramedExample>
</Section>
<Section name="AcceptCallView-ActiveState">
<FramedExample dashed={true}
height={272}
summary="Default"
width={332}>
<div className="fx-embedded">
<AcceptCallView callType={CALL_TYPES.AUDIO_VIDEO}
callerId="Mr Smith"
dispatcher={dispatcher}
mozLoop={mockMozLoopLoggedIn}
showMenu={true} />
</div>
</FramedExample>
</Section>
<Section name="ConversationToolbar">
<div>
<FramedExample dashed={true}
height={56}
summary="Default"
width={300}>
<div className="fx-embedded">
<ConversationToolbar audio={{ enabled: true, visible: true }}
dispatcher={dispatcher}
hangup={noop}
publishStream={noop}
screenShare={{ state: SCREEN_SHARE_STATES.INACTIVE, visible: true }}
settingsMenuItems={[{ id: "feedback" }]}
show={true}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={56}
summary="Video muted, Screen share pending"
width={300}>
<div className="fx-embedded">
<ConversationToolbar audio={{ enabled: true, visible: true }}
dispatcher={dispatcher}
hangup={noop}
publishStream={noop}
screenShare={{ state: SCREEN_SHARE_STATES.PENDING, visible: true }}
settingsMenuItems={[{ id: "feedback" }]}
show={true}
video={{ enabled: false, visible: true }} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={56}
summary="Audio muted, Screen share active"
width={300}>
<div className="fx-embedded">
<ConversationToolbar audio={{ enabled: false, visible: true }}
dispatcher={dispatcher}
hangup={noop}
publishStream={noop}
screenShare={{ state: SCREEN_SHARE_STATES.ACTIVE, visible: true }}
settingsMenuItems={[{ id: "feedback" }]}
show={true}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
</div>
</Section>
<Section name="PendingConversationView (Desktop)">
<FramedExample dashed={true}
height={272}
summary="Connecting"
width={300}>
<div className="fx-embedded">
<DesktopPendingConversationView callState={"gather"}
contact={mockContact}
dispatcher={dispatcher} />
</div>
</FramedExample>
</Section>
<Section name="DirectCallFailureView">
<FramedExample
dashed={true}
height={254}
summary="Call Failed - Incoming"
width={298}>
<div className="fx-embedded">
<DirectCallFailureView
conversationStore={conversationStores[0]}
dispatcher={dispatcher}
mozLoop={navigator.mozLoop}
outgoing={false} />
</div>
</FramedExample>
<FramedExample
dashed={true}
height={254}
summary="Call Failed - Outgoing"
width={298}>
<div className="fx-embedded">
<DirectCallFailureView
conversationStore={conversationStores[1]}
dispatcher={dispatcher}
mozLoop={navigator.mozLoop}
outgoing={true} />
</div>
</FramedExample>
<FramedExample
dashed={true}
height={254}
summary="Call Failed — with call URL error"
width={298}>
<div className="fx-embedded">
<DirectCallFailureView
conversationStore={conversationStores[0]}
dispatcher={dispatcher}
emailLinkError={true}
mozLoop={navigator.mozLoop}
outgoing={true} />
</div>
</FramedExample>
</Section>
<Section name="OngoingConversationView">
<FramedExample dashed={true}
height={398}
onContentsRendered={conversationStores[0].forcedUpdate}
summary="Desktop ongoing conversation window"
width={348}>
<div className="fx-embedded">
<OngoingConversationView
audio={{ enabled: true, visible: true }}
chatWindowDetached={false}
conversationStore={conversationStores[0]}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mediaConnected={true}
remotePosterUrl="sample-img/video-screen-remote.png"
remoteVideoEnabled={true}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={400}
onContentsRendered={conversationStores[1].forcedUpdate}
summary="Desktop ongoing conversation window (medium)"
width={600}>
<div className="fx-embedded">
<OngoingConversationView
audio={{ enabled: true, visible: true }}
chatWindowDetached={false}
conversationStore={conversationStores[1]}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mediaConnected={true}
remotePosterUrl="sample-img/video-screen-remote.png"
remoteVideoEnabled={true}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
<FramedExample height={600}
onContentsRendered={conversationStores[2].forcedUpdate}
summary="Desktop ongoing conversation window (large)"
width={800}>
<div className="fx-embedded">
<OngoingConversationView
audio={{ enabled: true, visible: true }}
chatWindowDetached={false}
conversationStore={conversationStores[2]}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mediaConnected={true}
remotePosterUrl="sample-img/video-screen-remote.png"
remoteVideoEnabled={true}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={conversationStores[3].forcedUpdate}
summary="Desktop ongoing conversation window - local face mute"
width={348}>
<div className="fx-embedded">
<OngoingConversationView
audio={{ enabled: true, visible: true }}
chatWindowDetached={false}
conversationStore={conversationStores[3]}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mediaConnected={true}
remotePosterUrl="sample-img/video-screen-remote.png"
remoteVideoEnabled={true}
video={{ enabled: false, visible: true }} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={conversationStores[4].forcedUpdate}
summary="Desktop ongoing conversation window - remote face mute"
width={348} >
<div className="fx-embedded">
<OngoingConversationView
audio={{ enabled: true, visible: true }}
chatWindowDetached={false}
conversationStore={conversationStores[4]}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mediaConnected={true}
remotePosterUrl="sample-img/video-screen-remote.png"
remoteVideoEnabled={false}
video={{ enabled: true, visible: true }} />
</div>
</FramedExample>
</Section>
<Section name="FeedbackView">
<p className="note">
</p>
<FramedExample dashed={true}
height={288}
summary="Default (useable demo)"
width={348}>
<div className="fx-embedded">
<FeedbackView mozLoop={{}}
onAfterFeedbackReceived={function() {}} />
</div>
</FramedExample>
</Section>
<Section name="AlertMessages">
<FramedExample dashed={true}
height={288}
summary="Various alerts"
width={348}>
<div>
<div className="alert alert-warning">
<button className="close"></button>
<p className="message">
The person you were calling has ended the conversation.
</p>
</div>
<br />
<div className="alert alert-error">
<button className="close"></button>
<p className="message">
The person you were calling has ended the conversation.
</p>
</div>
</div>
</FramedExample>
</Section>
<Section name="UnsupportedBrowserView">
<FramedExample cssClass="standalone"
dashed={true}
height={430}
summary="Standalone Unsupported Browser"
width={480}>
<div className="standalone">
<UnsupportedBrowserView isFirefox={false}/>
</div>
</FramedExample>
</Section>
<Section name="UnsupportedDeviceView">
<FramedExample cssClass="standalone"
dashed={true}
height={430}
summary="Standalone Unsupported Device"
width={480}>
<div className="standalone">
<UnsupportedDeviceView platform="ios"/>
</div>
</FramedExample>
</Section>
<Section name="RoomFailureView">
<FramedExample
dashed={true}
height={288}
summary="Desktop Room Failure View"
width={348}>
<div className="fx-embedded">
<RoomFailureView
dispatcher={dispatcher}
failureReason={FAILURE_DETAILS.UNKNOWN}
mozLoop={navigator.mozLoop} />
</div>
</FramedExample>
</Section>
<Section name="DesktopRoomConversationView">
<FramedExample height={398}
onContentsRendered={invitationRoomStore.activeRoomStore.forcedUpdate}
summary="Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)"
width={348}>
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
roomState={ROOM_STATES.INIT}
roomStore={invitationRoomStore} />
</div>
</FramedExample>
<FramedExample height={288}
onContentsRendered={invitationRoomStore.activeRoomStore.forcedUpdate}
summary="Desktop room Edit Context w/Error"
width={348}>
<div className="fx-embedded room-invitation-overlay">
<DesktopRoomEditContextView
dispatcher={dispatcher}
error={{}}
mozLoop={navigator.mozLoop}
onClose={function(){}}
roomData={{}}
savingContext={false}
show={true}
/>
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={desktopRoomStoreLoading.activeRoomStore.forcedUpdate}
summary="Desktop room conversation (loading)"
width={348}>
{/* Hide scrollbars here. Rotating loading div overflows and causes
scrollbars to appear */}
<div className="fx-embedded overflow-hidden">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
roomStore={desktopRoomStoreLoading} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={roomStore.activeRoomStore.forcedUpdate}
summary="Desktop room conversation"
width={348}>
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
roomStore={roomStore} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={482}
onContentsRendered={desktopRoomStoreMedium.activeRoomStore.forcedUpdate}
summary="Desktop room conversation (medium)"
width={602}>
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
roomStore={desktopRoomStoreMedium} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={485}
onContentsRendered={desktopRoomStoreLarge.activeRoomStore.forcedUpdate}
summary="Desktop room conversation (large)"
width={646}>
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
roomStore={desktopRoomStoreLarge} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={desktopLocalFaceMuteRoomStore.activeRoomStore.forcedUpdate}
summary="Desktop room conversation local face-mute"
width={348}>
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomStore={desktopLocalFaceMuteRoomStore} />
</div>
</FramedExample>
<FramedExample dashed={true}
height={398}
onContentsRendered={desktopRemoteFaceMuteRoomStore.activeRoomStore.forcedUpdate}
summary="Desktop room conversation remote face-mute"
width={348} >
<div className="fx-embedded">
<DesktopRoomConversationView
chatWindowDetached={false}
dispatcher={dispatcher}
localPosterUrl="sample-img/video-screen-local.png"
mozLoop={navigator.mozLoop}
onCallTerminated={function(){}}
remotePosterUrl="sample-img/video-screen-remote.png"
roomStore={desktopRemoteFaceMuteRoomStore} />
</div>
</FramedExample>
</Section>
<Section name="StandaloneHandleUserAgentView">
<FramedExample
cssClass="standalone"
dashed={true}
height={483}
summary="Standalone Room Handle Join in Firefox"
width={644} >
<div className="standalone">
<StandaloneHandleUserAgentView
activeRoomStore={readyRoomStore}
dispatcher={dispatcher} />
</div>
</FramedExample>
</Section>
<Section name="StandaloneRoomView">
<FramedExample cssClass="standalone"
dashed={true}
height={483}
summary="Standalone room conversation (ready)"
width={644} >
<div className="standalone">
<StandaloneRoomView
activeRoomStore={readyRoomStore}
dispatcher={dispatcher}
isFirefox={true}
roomState={ROOM_STATES.READY} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
onContentsRendered={joinedRoomStore.forcedUpdate}
summary="Standalone room conversation (joined)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={joinedRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png" />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
onContentsRendered={loadingRemoteVideoRoomStore.forcedUpdate}
summary="Standalone room conversation (loading remote)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={loadingRemoteVideoRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png" />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
onContentsRendered={updatingActiveRoomStore.forcedUpdate}
summary="Standalone room conversation (has-participants, 644x483)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={updatingActiveRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
onContentsRendered={localFaceMuteRoomStore.forcedUpdate}
summary="Standalone room conversation (local face mute, has-participants, 644x483)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={localFaceMuteRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png" />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
onContentsRendered={remoteFaceMuteRoomStore.forcedUpdate}
summary="Standalone room conversation (remote face mute, has-participants, 644x483)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={remoteFaceMuteRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png" />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={660}
onContentsRendered={loadingRemoteLoadingScreenStore.forcedUpdate}
summary="Standalone room convo (has-participants, loading screen share, loading remote video, 800x660)"
width={800}>
{/* Hide scrollbars here. Rotating loading div overflows and causes
scrollbars to appear */}
<div className="standalone overflow-hidden">
<StandaloneRoomView
activeRoomStore={loadingRemoteLoadingScreenStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={660}
onContentsRendered={loadingScreenSharingRoomStore.forcedUpdate}
summary="Standalone room convo (has-participants, loading screen share, 800x660)"
width={800}>
{/* Hide scrollbars here. Rotating loading div overflows and causes
scrollbars to appear */}
<div className="standalone overflow-hidden">
<StandaloneRoomView
activeRoomStore={loadingScreenSharingRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={660}
onContentsRendered={updatingSharingRoomStore.forcedUpdate}
summary="Standalone room convo (has-participants, receivingScreenShare, 800x660)"
width={800}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={updatingSharingRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
screenSharePosterUrl="sample-img/video-screen-terminal.png" />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
summary="Standalone room conversation (full - FFx user)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={fullActiveRoomStore}
dispatcher={dispatcher}
isFirefox={true} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
summary="Standalone room conversation (full - non FFx user)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={fullActiveRoomStore}
dispatcher={dispatcher}
isFirefox={false} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={483}
summary="Standalone room conversation (failed)"
width={644}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={failedRoomStore}
dispatcher={dispatcher}
isFirefox={false} />
</div>
</FramedExample>
</Section>
<Section name="StandaloneRoomView (Mobile)">
<FramedExample cssClass="standalone"
dashed={true}
height={480}
onContentsRendered={updatingMobileActiveRoomStore.forcedUpdate}
summary="Standalone room conversation (has-participants, 600x480)"
width={600}>
<div className="standalone">
<StandaloneRoomView
activeRoomStore={updatingMobileActiveRoomStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={480}
onContentsRendered={updatingSharingRoomMobileStore.forcedUpdate}
summary="Standalone room convo (has-participants, receivingScreenShare, 600x480)"
width={600} >
<div className="standalone" cssClass="standalone">
<StandaloneRoomView
activeRoomStore={updatingSharingRoomMobileStore}
dispatcher={dispatcher}
isFirefox={true}
localPosterUrl="sample-img/video-screen-local.png"
remotePosterUrl="sample-img/video-screen-remote.png"
roomState={ROOM_STATES.HAS_PARTICIPANTS}
screenSharePosterUrl="sample-img/video-screen-terminal.png" />
</div>
</FramedExample>
</Section>
<Section name="TextChatView">
<FramedExample dashed={true}
height={160}
summary="TextChatView: desktop embedded"
width={298}>
<div className="fx-embedded">
<TextChatView dispatcher={dispatcher}
showRoomName={false}
useDesktopPaths={false} />
</div>
</FramedExample>
<FramedExample cssClass="standalone"
dashed={true}
height={400}
summary="Standalone Text Chat conversation (200x400)"
width={200}>
<div className="standalone text-chat-example">
<div className="media-wrapper">
<TextChatView
dispatcher={dispatcher}
showRoomName={true}
useDesktopPaths={false} />
</div>
</div>
</FramedExample>
</Section>
<Section className="svg-icons" name="SVG icons preview">
<FramedExample height={240}
summary="10x10"
width={800}>
<SVGIcons size="10x10"/>
</FramedExample>
<FramedExample height={350}
summary="14x14"
width={800}>
<SVGIcons size="14x14" />
</FramedExample>
<FramedExample height={480}
summary="16x16"
width={800}>
<SVGIcons size="16x16"/>
</FramedExample>
</Section>
</ShowCase>
);
}
});
window.addEventListener("DOMContentLoaded", function() {
var uncaughtError;
var consoleWarn = console.warn;
var caughtWarnings = [];
console.warn = function() {
var args = Array.slice(arguments);
caughtWarnings.push(args);
consoleWarn.apply(console, args);
};
try {
React.render(<App />, document.getElementById("main"));
for (var listener of visibilityListeners) {
listener({target: {hidden: false}});
}
} catch(err) {
console.error(err);
uncaughtError = err;
}
// Wait until all the FramedExamples have been fully loaded.
setTimeout(function waitForQueuedFrames() {
if (window.queuedFrames.length !== 0) {
setTimeout(waitForQueuedFrames, 500);
return;
}
// Put the title back, in case views changed it.
document.title = "Loop UI Components Showcase";
// This simulates the mocha layout for errors which means we can run
// this alongside our other unit tests but use the same harness.
var expectedWarningsCount = 0;
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
var resultsElement = document.querySelector("#results");
var divFailuresNode = document.createElement("div");
var pCompleteNode = document.createElement("p");
var emNode = document.createElement("em");
if (uncaughtError || warningsMismatch) {
var liTestFail = document.createElement("li");
var h2Node = document.createElement("h2");
var preErrorNode = document.createElement("pre");
divFailuresNode.className = "failures";
emNode.innerHTML = ((uncaughtError && warningsMismatch) ? 2 : 1).toString();
divFailuresNode.appendChild(emNode);
resultsElement.appendChild(divFailuresNode);
if (warningsMismatch) {
liTestFail.className = "test";
liTestFail.className = liTestFail.className + " fail";
h2Node.innerHTML = "Unexpected number of warnings detected in UI-Showcase";
preErrorNode.className = "error";
preErrorNode.innerHTML = "Got: " + caughtWarnings.length + "\n" + "Expected: " + expectedWarningsCount;
liTestFail.appendChild(h2Node);
liTestFail.appendChild(preErrorNode);
resultsElement.appendChild(liTestFail);
}
if (uncaughtError) {
liTestFail.className = "test";
liTestFail.className = liTestFail.className + " fail";
h2Node.innerHTML = "Errors rendering UI-Showcase";
preErrorNode.className = "error";
preErrorNode.innerHTML = uncaughtError + "\n" + uncaughtError.stack;
liTestFail.appendChild(h2Node);
liTestFail.appendChild(preErrorNode);
resultsElement.appendChild(liTestFail);
}
} else {
divFailuresNode.className = "failures";
emNode.innerHTML = "0";
divFailuresNode.appendChild(emNode);
resultsElement.appendChild(divFailuresNode);
}
pCompleteNode.id = "complete";
pCompleteNode.innerHTML = "Completed";
resultsElement.appendChild(pCompleteNode);
}, 1000);
});
})();