Files
tubestation/browser/components/loop/ui/ui-showcase.js

1341 lines
54 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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 */
(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 PanelView = loop.panel.PanelView;
var SignInRequestView = loop.panel.SignInRequestView;
// 1.2. Conversation Window
var AcceptCallView = loop.conversationViews.AcceptCallView;
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
var OngoingConversationView = loop.conversationViews.OngoingConversationView;
var CallFailedView = loop.conversationViews.CallFailedView;
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;
// 3. Shared components
var ConversationToolbar = loop.shared.views.ConversationToolbar;
var FeedbackView = loop.shared.views.FeedbackView;
var Checkbox = loop.shared.views.Checkbox;
var TextChatView = loop.shared.views.chat.TextChatView;
// Store constants
var ROOM_STATES = loop.store.ROOM_STATES;
var FEEDBACK_STATES = loop.store.FEEDBACK_STATES;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;
// 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();
// Feedback API client configured to send data to the stage input server,
// which is available at https://input.allizom.org
var stageFeedbackApiClient = new loop.FeedbackAPIClient(
"https://input.allizom.org/api/v1/feedback", {
product: "Loop"
}
);
var mockSDK = _.extend({
sendTextChatMessage: function(message) {
dispatcher.dispatch(new loop.shared.actions.ReceivedTextChatMessage({
message: message.message
}));
}
}, Backbone.Events);
/**
* 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,
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,
remoteSrcVideoObject: false
});
var readyRoomStore = makeActiveRoomStore({
mediaConnected: false,
roomState: ROOM_STATES.READY
});
var updatingActiveRoomStore = 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 loadingRemoteLoadingScreenStore = makeActiveRoomStore({
mediaConnected: false,
roomState: ROOM_STATES.HAS_PARTICIPANTS,
remoteSrcVideoObject: false
});
var loadingScreenSharingRoomStore = makeActiveRoomStore({
roomState: ROOM_STATES.HAS_PARTICIPANTS
});
/* Set up the stores for pending screen sharing */
loadingScreenSharingRoomStore.receivingScreenShare({
receiving: true,
srcVideoObject: false
});
loadingRemoteLoadingScreenStore.receivingScreenShare({
receiving: true,
srcVideoObject: 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
});
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,
remoteSrcVideoObject: false
})
});
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 feedbackStore = new loop.store.FeedbackStore(dispatcher, {
feedbackClient: stageFeedbackApiClient
});
var conversationStore = new loop.store.ConversationStore(dispatcher, {
client: {},
mozLoop: navigator.mozLoop,
sdkDriver: mockSDK
});
var textChatStore = new loop.store.TextChatStore(dispatcher, {
sdkDriver: mockSDK
});
// Update the text chat store with the room info.
textChatStore.updateRoomInfo(new sharedActions.UpdateRoomInfo({
roomName: "A Very Long Conversation Name",
roomOwner: "fake",
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.store.CHAT_CONTENT_TYPES.TEXT,
message: "Rheet!",
sentTimestamp: "2015-06-23T22:21:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.store.CHAT_CONTENT_TYPES.TEXT,
message: "Hi there",
receivedTimestamp: "2015-06-23T22:21:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.store.CHAT_CONTENT_TYPES.TEXT,
message: "Hello",
receivedTimestamp: "2015-06-23T23:24:45.590Z"
}));
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.store.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.SendTextChatMessage({
contentType: loop.store.CHAT_CONTENT_TYPES.TEXT,
message: "Nowforareallylongwordwithoutspacesorpunctuationwhichshouldcause" +
"linewrappingissuesifthecssiswrong",
sentTimestamp: "2015-06-23T22:23:45.590Z"
}));
dispatcher.dispatch(new sharedActions.ReceivedTextChatMessage({
contentType: loop.store.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.store.CHAT_CONTENT_TYPES.TEXT,
message: "What time should we meet?",
sentTimestamp: "2015-06-23T22:27:45.590Z"
}));
dispatcher.dispatch(new sharedActions.SendTextChatMessage({
contentType: loop.store.CHAT_CONTENT_TYPES.TEXT,
message: "Cool",
sentTimestamp: "2015-06-23T22:27:45.590Z"
}));
loop.store.StoreMixin.register({
activeRoomStore: activeRoomStore,
conversationStore: conversationStore,
feedbackStore: feedbackStore,
textChatStore: textChatStore
});
// Local mocks
var mockMozLoopRooms = _.extend({}, navigator.mozLoop);
var mockContact = {
name: ["Mr Smith"],
email: [{
value: "smith@invalid.com"
}]
};
var mockClient = {
requestCallUrlInfo: noop
};
var mockConversationModel = new loop.shared.models.ConversationModel({
callerId: "Mrs Jones",
urlCreationDate: (new Date() / 1000).toString()
}, {
sdk: mockSDK
});
mockConversationModel.startSession = 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({displayName: "SVGIcon",
propTypes: {
shapeId: React.PropTypes.string.isRequired,
size: React.PropTypes.string.isRequired
},
render: function() {
var sizeUnit = this.props.size.split("x");
return (
React.createElement("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({displayName: "SVGIcons",
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"
],
"14x14": ["audio", "audio-active", "audio-disabled", "facemute",
"facemute-active", "facemute-disabled", "hangup", "hangup-active",
"hangup-disabled", "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"
],
"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",
"precall", "precall-hover", "precall-active", "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", "tour"
]
},
render: function() {
var icons = this.shapes[this.props.size].map(function(shapeId, i) {
return (
React.createElement("li", {className: "svg-icon-entry", key: this.props.size + "-" + i},
React.createElement("p", null, React.createElement(SVGIcon, {shapeId: shapeId, size: this.props.size})),
React.createElement("p", null, shapeId)
)
);
}, this);
return (
React.createElement("ul", {className: "svg-icon-list"}, icons)
);
}
});
var FramedExample = React.createClass({displayName: "FramedExample",
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 (
React.createElement("div", {className: "example"},
React.createElement("h3", {id: this.makeId()},
this.props.summary,
React.createElement("a", {href: this.makeId("#")}, " ¶")
),
React.createElement("div", {className: "comp"},
React.createElement(Frame, {className: cx({dashed: this.props.dashed}),
cssClass: this.props.cssClass,
height: height,
onContentsRendered: this.props.onContentsRendered,
width: width},
this.props.children
)
)
)
);
}
});
var Example = React.createClass({displayName: "Example",
propTypes: {
children: React.PropTypes.oneOfType([
React.PropTypes.element,
React.PropTypes.arrayOf(React.PropTypes.element)
]).isRequired,
dashed: React.PropTypes.bool,
style: React.PropTypes.object,
summary: React.PropTypes.string.isRequired
},
makeId: function(prefix) {
return (prefix || "") + this.props.summary.toLowerCase().replace(/\s/g, "-");
},
render: function() {
var cx = React.addons.classSet;
return (
React.createElement("div", {className: "example"},
React.createElement("h3", {id: this.makeId()},
this.props.summary,
React.createElement("a", {href: this.makeId("#")}, " ¶")
),
React.createElement("div", {className: cx({comp: true, dashed: this.props.dashed}),
style: this.props.style},
this.props.children
)
)
);
}
});
var Section = React.createClass({displayName: "Section",
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 (
React.createElement("section", {className: this.props.className, id: this.props.name},
React.createElement("h1", null, this.props.name),
this.props.children
)
);
}
});
var ShowCase = React.createClass({displayName: "ShowCase",
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 (
React.createElement("div", {className: "showcase"},
React.createElement("header", null,
React.createElement("h1", null, "Loop UI Components Showcase"),
React.createElement(Checkbox, {checked: this.state.rtlMode, label: "RTL mode?",
onChange: this._handleCheckboxChange}),
React.createElement("nav", {className: "showcase-menu"},
React.Children.map(this.props.children, function(section) {
return (
React.createElement("a", {className: "btn btn-info", href: "#" + section.props.name},
section.props.name
)
);
})
)
),
this.props.children
)
);
}
});
var App = React.createClass({displayName: "App",
render: function() {
return (
React.createElement(ShowCase, null,
React.createElement(Section, {name: "PanelView"},
React.createElement("p", {className: "note"},
React.createElement("strong", null, "Note:"), " 332px wide."
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Re-sign-in view"},
React.createElement(SignInRequestView, {mozLoop: mockMozLoopRooms})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Room list tab"},
React.createElement(PanelView, {client: mockClient,
dispatcher: dispatcher,
mozLoop: mockMozLoopRooms,
notifications: notifications,
roomStore: roomStore,
selectedTab: "rooms",
userProfile: {email: "test@example.com"}})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Contact list tab"},
React.createElement(PanelView, {client: mockClient,
dispatcher: dispatcher,
mozLoop: mockMozLoopRooms,
notifications: notifications,
roomStore: roomStore,
selectedTab: "contacts",
userProfile: {email: "test@example.com"}})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Error Notification"},
React.createElement(PanelView, {client: mockClient,
dispatcher: dispatcher,
mozLoop: navigator.mozLoop,
notifications: errNotifications,
roomStore: roomStore})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Error Notification - authenticated"},
React.createElement(PanelView, {client: mockClient,
dispatcher: dispatcher,
mozLoop: navigator.mozLoop,
notifications: errNotifications,
roomStore: roomStore,
userProfile: {email: "test@example.com"}})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Contact import success"},
React.createElement(PanelView, {dispatcher: dispatcher,
mozLoop: mockMozLoopRooms,
notifications: new loop.shared.models.NotificationCollection([{level: "success", message: "Import success"}]),
roomStore: roomStore,
selectedTab: "contacts",
userProfile: {email: "test@example.com"}})
),
React.createElement(Example, {dashed: true, style: {width: "332px"}, summary: "Contact import error"},
React.createElement(PanelView, {dispatcher: dispatcher,
mozLoop: mockMozLoopRooms,
notifications: new loop.shared.models.NotificationCollection([{level: "error", message: "Import error"}]),
roomStore: roomStore,
selectedTab: "contacts",
userProfile: {email: "test@example.com"}})
)
),
React.createElement(Section, {name: "AcceptCallView"},
React.createElement(Example, {dashed: true, style: {width: "300px", height: "272px"},
summary: "Default / incoming video call"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(AcceptCallView, {callType: CALL_TYPES.AUDIO_VIDEO,
callerId: "Mr Smith",
dispatcher: dispatcher,
mozLoop: mockMozLoopRooms})
)
),
React.createElement(Example, {dashed: true, style: {width: "300px", height: "272px"},
summary: "Default / incoming audio only call"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(AcceptCallView, {callType: CALL_TYPES.AUDIO_ONLY,
callerId: "Mr Smith",
dispatcher: dispatcher,
mozLoop: mockMozLoopRooms})
)
)
),
React.createElement(Section, {name: "AcceptCallView-ActiveState"},
React.createElement(Example, {dashed: true, style: {width: "300px", height: "272px"},
summary: "Default"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(AcceptCallView, {callType: CALL_TYPES.AUDIO_VIDEO,
callerId: "Mr Smith",
dispatcher: dispatcher,
mozLoop: mockMozLoopRooms,
showMenu: true})
)
)
),
React.createElement(Section, {name: "ConversationToolbar"},
React.createElement("h2", null, "Desktop Conversation Window"),
React.createElement("div", {className: "fx-embedded override-position"},
React.createElement(Example, {style: {width: "300px", height: "26px"}, summary: "Default"},
React.createElement(ConversationToolbar, {audio: {enabled: true},
hangup: noop,
publishStream: noop,
video: {enabled: true}})
),
React.createElement(Example, {style: {width: "300px", height: "26px"}, summary: "Video muted"},
React.createElement(ConversationToolbar, {audio: {enabled: true},
hangup: noop,
publishStream: noop,
video: {enabled: false}})
),
React.createElement(Example, {style: {width: "300px", height: "26px"}, summary: "Audio muted"},
React.createElement(ConversationToolbar, {audio: {enabled: false},
hangup: noop,
publishStream: noop,
video: {enabled: true}})
)
),
React.createElement("h2", null, "Standalone"),
React.createElement("div", {className: "standalone override-position"},
React.createElement(Example, {summary: "Default"},
React.createElement(ConversationToolbar, {audio: {enabled: true},
hangup: noop,
publishStream: noop,
video: {enabled: true}})
),
React.createElement(Example, {summary: "Video muted"},
React.createElement(ConversationToolbar, {audio: {enabled: true},
hangup: noop,
publishStream: noop,
video: {enabled: false}})
),
React.createElement(Example, {summary: "Audio muted"},
React.createElement(ConversationToolbar, {audio: {enabled: false},
hangup: noop,
publishStream: noop,
video: {enabled: true}})
)
)
),
React.createElement(Section, {name: "PendingConversationView (Desktop)"},
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Connecting"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(DesktopPendingConversationView, {callState: "gather",
contact: mockContact,
dispatcher: dispatcher})
)
)
),
React.createElement(Section, {name: "CallFailedView"},
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Call Failed - Incoming"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(CallFailedView, {dispatcher: dispatcher,
outgoing: false,
store: conversationStore})
)
),
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Call Failed - Outgoing"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(CallFailedView, {dispatcher: dispatcher,
outgoing: true,
store: conversationStore})
)
),
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Call Failed — with call URL error"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(CallFailedView, {dispatcher: dispatcher, emailLinkError: true,
outgoing: true,
store: conversationStore})
)
)
),
React.createElement(Section, {name: "OngoingConversationView"},
React.createElement(FramedExample, {height: 254,
summary: "Desktop ongoing conversation window",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(OngoingConversationView, {
audio: {enabled: true},
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mediaConnected: true,
remotePosterUrl: "sample-img/video-screen-remote.png",
remoteVideoEnabled: true,
video: {enabled: true}})
)
),
React.createElement(FramedExample, {height: 600,
summary: "Desktop ongoing conversation window large",
width: 800},
React.createElement("div", {className: "fx-embedded"},
React.createElement(OngoingConversationView, {
audio: {enabled: true},
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mediaConnected: true,
remotePosterUrl: "sample-img/video-screen-remote.png",
remoteVideoEnabled: true,
video: {enabled: true}})
)
),
React.createElement(FramedExample, {height: 254,
summary: "Desktop ongoing conversation window - local face mute",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(OngoingConversationView, {
audio: {enabled: true},
dispatcher: dispatcher,
mediaConnected: true,
remotePosterUrl: "sample-img/video-screen-remote.png",
remoteVideoEnabled: true,
video: {enabled: false}})
)
),
React.createElement(FramedExample, {height: 254,
summary: "Desktop ongoing conversation window - remote face mute",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(OngoingConversationView, {
audio: {enabled: true},
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mediaConnected: true,
remoteVideoEnabled: false,
video: {enabled: true}})
)
)
),
React.createElement(Section, {name: "FeedbackView"},
React.createElement("p", {className: "note"},
React.createElement("strong", null, "Note:"), " For the useable demo, you can access submitted data at ",
React.createElement("a", {href: "https://input.allizom.org/"}, "input.allizom.org"), "."
),
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Default (useable demo)"},
React.createElement(FeedbackView, {feedbackStore: feedbackStore})
),
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Detailed form"},
React.createElement(FeedbackView, {feedbackState: FEEDBACK_STATES.DETAILS, feedbackStore: feedbackStore})
),
React.createElement(Example, {dashed: true,
style: {width: "300px", height: "272px"},
summary: "Thank you!"},
React.createElement(FeedbackView, {feedbackState: FEEDBACK_STATES.SENT, feedbackStore: feedbackStore})
)
),
React.createElement(Section, {name: "AlertMessages"},
React.createElement(Example, {summary: "Various alerts"},
React.createElement("div", {className: "alert alert-warning"},
React.createElement("button", {className: "close"}),
React.createElement("p", {className: "message"},
"The person you were calling has ended the conversation."
)
),
React.createElement("br", null),
React.createElement("div", {className: "alert alert-error"},
React.createElement("button", {className: "close"}),
React.createElement("p", {className: "message"},
"The person you were calling has ended the conversation."
)
)
)
),
React.createElement(Section, {name: "UnsupportedBrowserView"},
React.createElement(Example, {summary: "Standalone Unsupported Browser"},
React.createElement("div", {className: "standalone"},
React.createElement(UnsupportedBrowserView, {isFirefox: false})
)
)
),
React.createElement(Section, {name: "UnsupportedDeviceView"},
React.createElement(Example, {summary: "Standalone Unsupported Device"},
React.createElement("div", {className: "standalone"},
React.createElement(UnsupportedDeviceView, {platform: "ios"})
)
)
),
React.createElement(Section, {name: "DesktopRoomConversationView"},
React.createElement(FramedExample, {
height: 254,
summary: "Desktop room conversation (invitation, text-chat inclusion/scrollbars don't happen in real client)",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(DesktopRoomConversationView, {
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mozLoop: navigator.mozLoop,
roomState: ROOM_STATES.INIT,
roomStore: invitationRoomStore})
)
),
React.createElement(FramedExample, {
dashed: true,
height: 394,
summary: "Desktop room conversation (loading)",
width: 298},
/* Hide scrollbars here. Rotating loading div overflows and causes
scrollbars to appear */
React.createElement("div", {className: "fx-embedded overflow-hidden"},
React.createElement(DesktopRoomConversationView, {
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mozLoop: navigator.mozLoop,
remotePosterUrl: "sample-img/video-screen-remote.png",
roomState: ROOM_STATES.HAS_PARTICIPANTS,
roomStore: desktopRoomStoreLoading})
)
),
React.createElement(FramedExample, {height: 254,
summary: "Desktop room conversation"},
React.createElement("div", {className: "fx-embedded"},
React.createElement(DesktopRoomConversationView, {
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mozLoop: navigator.mozLoop,
remotePosterUrl: "sample-img/video-screen-remote.png",
roomState: ROOM_STATES.HAS_PARTICIPANTS,
roomStore: roomStore})
)
),
React.createElement(FramedExample, {dashed: true,
height: 394,
summary: "Desktop room conversation local face-mute",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(DesktopRoomConversationView, {
dispatcher: dispatcher,
mozLoop: navigator.mozLoop,
remotePosterUrl: "sample-img/video-screen-remote.png",
roomStore: desktopLocalFaceMuteRoomStore})
)
),
React.createElement(FramedExample, {dashed: true, height: 394,
summary: "Desktop room conversation remote face-mute",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(DesktopRoomConversationView, {
dispatcher: dispatcher,
localPosterUrl: "sample-img/video-screen-local.png",
mozLoop: navigator.mozLoop,
roomStore: desktopRemoteFaceMuteRoomStore})
)
)
),
React.createElement(Section, {name: "StandaloneRoomView"},
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
summary: "Standalone room conversation (ready)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: readyRoomStore,
dispatcher: dispatcher,
isFirefox: true,
roomState: ROOM_STATES.READY})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
onContentsRendered: joinedRoomStore.forcedUpdate,
summary: "Standalone room conversation (joined)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: joinedRoomStore,
dispatcher: dispatcher,
isFirefox: true,
localPosterUrl: "sample-img/video-screen-local.png"})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
onContentsRendered: loadingRemoteVideoRoomStore.forcedUpdate,
summary: "Standalone room conversation (loading remote)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: loadingRemoteVideoRoomStore,
dispatcher: dispatcher,
isFirefox: true,
localPosterUrl: "sample-img/video-screen-local.png"})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
onContentsRendered: updatingActiveRoomStore.forcedUpdate,
summary: "Standalone room conversation (has-participants, 644x483)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(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})
)
),
React.createElement(FramedExample, {
cssClass: "standalone",
dashed: true,
height: 483,
onContentsRendered: localFaceMuteRoomStore.forcedUpdate,
summary: "Standalone room conversation (local face mute, has-participants, 644x483)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: localFaceMuteRoomStore,
dispatcher: dispatcher,
isFirefox: true,
localPosterUrl: "sample-img/video-screen-local.png",
remotePosterUrl: "sample-img/video-screen-remote.png"})
)
),
React.createElement(FramedExample, {
cssClass: "standalone",
dashed: true,
height: 483,
onContentsRendered: remoteFaceMuteRoomStore.forcedUpdate,
summary: "Standalone room conversation (remote face mute, has-participants, 644x483)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: remoteFaceMuteRoomStore,
dispatcher: dispatcher,
isFirefox: true,
localPosterUrl: "sample-img/video-screen-local.png",
remotePosterUrl: "sample-img/video-screen-remote.png"})
)
),
React.createElement(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 */
React.createElement("div", {className: "standalone overflow-hidden"},
React.createElement(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,
screenSharePosterUrl: "sample-img/video-screen-baz.png"})
)
),
React.createElement(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 */
React.createElement("div", {className: "standalone overflow-hidden"},
React.createElement(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,
screenSharePosterUrl: "sample-img/video-screen-baz.png"})
)
),
React.createElement(FramedExample, {
cssClass: "standalone",
dashed: true,
height: 660,
onContentsRendered: updatingSharingRoomStore.forcedUpdate,
summary: "Standalone room convo (has-participants, receivingScreenShare, 800x660)",
width: 800},
React.createElement("div", {className: "standalone"},
React.createElement(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"})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
summary: "Standalone room conversation (full - FFx user)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: fullActiveRoomStore,
dispatcher: dispatcher,
isFirefox: true})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
summary: "Standalone room conversation (full - non FFx user)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: fullActiveRoomStore,
dispatcher: dispatcher,
isFirefox: false})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
summary: "Standalone room conversation (feedback)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: endedRoomStore,
dispatcher: dispatcher,
feedbackStore: feedbackStore,
isFirefox: false})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 483,
summary: "Standalone room conversation (failed)",
width: 644},
React.createElement("div", {className: "standalone"},
React.createElement(StandaloneRoomView, {
activeRoomStore: failedRoomStore,
dispatcher: dispatcher,
isFirefox: false})
)
)
),
React.createElement(Section, {name: "StandaloneRoomView (Mobile)"},
React.createElement(FramedExample, {
cssClass: "standalone",
dashed: true,
height: 480,
onContentsRendered: updatingActiveRoomStore.forcedUpdate,
summary: "Standalone room conversation (has-participants, 600x480)",
width: 600},
React.createElement("div", {className: "standalone"},
React.createElement(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})
)
),
React.createElement(FramedExample, {
height: 480,
onContentsRendered: updatingSharingRoomStore.forcedUpdate,
summary: "Standalone room convo (has-participants, receivingScreenShare, 600x480)",
width: 600},
React.createElement("div", {className: "standalone", cssClass: "standalone"},
React.createElement(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"})
)
)
),
React.createElement(Section, {name: "TextChatView"},
React.createElement(FramedExample, {dashed: true,
height: 160,
summary: "TextChatView: desktop embedded",
width: 298},
React.createElement("div", {className: "fx-embedded"},
React.createElement(TextChatView, {dispatcher: dispatcher,
showRoomName: false,
useDesktopPaths: false})
)
),
React.createElement(FramedExample, {cssClass: "standalone",
dashed: true,
height: 400,
summary: "Standalone Text Chat conversation (200x400)",
width: 200},
React.createElement("div", {className: "standalone text-chat-example"},
React.createElement("div", {className: "media-wrapper"},
React.createElement(TextChatView, {
dispatcher: dispatcher,
showRoomName: true,
useDesktopPaths: false})
)
)
)
),
React.createElement(Section, {className: "svg-icons", name: "SVG icons preview"},
React.createElement(Example, {summary: "10x10"},
React.createElement(SVGIcons, {size: "10x10"})
),
React.createElement(Example, {summary: "14x14"},
React.createElement(SVGIcons, {size: "14x14"})
),
React.createElement(Example, {summary: "16x16"},
React.createElement(SVGIcons, {size: "16x16"})
)
)
)
);
}
});
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.renderComponent(React.createElement(App, null), 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 = 29;
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
if (uncaughtError || warningsMismatch) {
$("#results").append("<div class='failures'><em>" +
(!!(uncaughtError && warningsMismatch) ? 2 : 1) + "</em></div>");
if (warningsMismatch) {
$("#results").append("<li class='test fail'>" +
"<h2>Unexpected number of warnings detected in UI-Showcase</h2>" +
"<pre class='error'>Got: " + caughtWarnings.length + "\n" +
"Expected: " + expectedWarningsCount + "</pre></li>");
}
if (uncaughtError) {
$("#results").append("<li class='test fail'>" +
"<h2>Errors rendering UI-Showcase</h2>" +
"<pre class='error'>" + uncaughtError + "\n" + uncaughtError.stack + "</pre>" +
"</li>");
}
} else {
$("#results").append("<div class='failures'><em>0</em></div>");
}
$("#results").append("<p id='complete'>Complete.</p>");
}, 1000);
});
})();