mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 06:35:42 +00:00
Bug 972017 Part 1 - Add a new controller view for selecting between incoming and outgoing calls in the Loop Conversation window. Also, set up a bare-bones outgoing pending conversation view. r=mikedeboer
This commit is contained in:
parent
b743549be7
commit
631b97c2df
@ -30,8 +30,11 @@
|
||||
<script type="text/javascript" src="loop/shared/js/mixins.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/views.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/feedbackApiClient.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/conversationStore.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversationViews.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/websocket.js"></script>
|
||||
<script type="text/javascript" src="loop/js/client.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversationViews.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversation.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,8 +11,9 @@ var loop = loop || {};
|
||||
loop.conversation = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedViews = loop.shared.views,
|
||||
sharedModels = loop.shared.models;
|
||||
var sharedViews = loop.shared.views;
|
||||
var sharedModels = loop.shared.models;
|
||||
var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
|
||||
|
||||
var IncomingCallView = React.createClass({displayName: 'IncomingCallView',
|
||||
|
||||
@ -109,26 +110,23 @@ loop.conversation = (function(mozL10n) {
|
||||
|
||||
render: function() {
|
||||
/* jshint ignore:start */
|
||||
var btnClassAccept = "btn btn-accept";
|
||||
var btnClassDecline = "btn btn-error btn-decline";
|
||||
var conversationPanelClass = "incoming-call";
|
||||
var dropdownMenuClassesDecline = React.addons.classSet({
|
||||
"native-dropdown-menu": true,
|
||||
"conversation-window-dropdown": true,
|
||||
"visually-hidden": !this.state.showDeclineMenu
|
||||
});
|
||||
return (
|
||||
React.DOM.div({className: conversationPanelClass},
|
||||
React.DOM.div({className: "call-window"},
|
||||
React.DOM.h2(null, mozL10n.get("incoming_call_title2")),
|
||||
React.DOM.div({className: "btn-group incoming-call-action-group"},
|
||||
React.DOM.div({className: "btn-group call-action-group"},
|
||||
|
||||
React.DOM.div({className: "fx-embedded-incoming-call-button-spacer"}),
|
||||
React.DOM.div({className: "fx-embedded-call-button-spacer"}),
|
||||
|
||||
React.DOM.div({className: "btn-chevron-menu-group"},
|
||||
React.DOM.div({className: "btn-group-chevron"},
|
||||
React.DOM.div({className: "btn-group"},
|
||||
|
||||
React.DOM.button({className: btnClassDecline,
|
||||
React.DOM.button({className: "btn btn-error btn-decline",
|
||||
onClick: this._handleDecline},
|
||||
mozL10n.get("incoming_call_cancel_button")
|
||||
),
|
||||
@ -146,11 +144,11 @@ loop.conversation = (function(mozL10n) {
|
||||
)
|
||||
),
|
||||
|
||||
React.DOM.div({className: "fx-embedded-incoming-call-button-spacer"}),
|
||||
React.DOM.div({className: "fx-embedded-call-button-spacer"}),
|
||||
|
||||
AcceptCallButton({mode: this._answerModeProps()}),
|
||||
|
||||
React.DOM.div({className: "fx-embedded-incoming-call-button-spacer"})
|
||||
React.DOM.div({className: "fx-embedded-call-button-spacer"})
|
||||
|
||||
)
|
||||
)
|
||||
@ -489,6 +487,44 @@ loop.conversation = (function(mozL10n) {
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Master controller view for handling if incoming or outgoing calls are
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var ConversationControllerView = React.createClass({displayName: 'ConversationControllerView',
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
client: React.PropTypes.instanceOf(loop.Client).isRequired,
|
||||
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
|
||||
.isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
|
||||
.isRequired,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for OutgoingConversationView
|
||||
store: React.PropTypes.instanceOf(loop.ConversationStore).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.outgoing) {
|
||||
return (OutgoingConversationView({
|
||||
store: this.props.store}
|
||||
));
|
||||
}
|
||||
|
||||
return (IncomingConversationView({
|
||||
client: this.props.client,
|
||||
conversation: this.props.conversation,
|
||||
notifications: this.props.notifications,
|
||||
sdk: this.props.sdk}
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Panel initialisation.
|
||||
*/
|
||||
@ -509,8 +545,18 @@ loop.conversation = (function(mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||
var conversationStore = new loop.ConversationStore();
|
||||
|
||||
// XXX For now key this on the pref, but this should really be
|
||||
// set by the information from the mozLoop API when we can get it (bug 1072323).
|
||||
var outgoingEmail = navigator.mozLoop.getLoopCharPref("outgoingemail");
|
||||
if (outgoingEmail) {
|
||||
conversationStore.set("outgoing", true);
|
||||
conversationStore.set("calleeId", outgoingEmail);
|
||||
}
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
var client = new loop.Client();
|
||||
var conversation = new sharedModels.ConversationModel(
|
||||
{}, // Model attributes
|
||||
@ -518,19 +564,22 @@ loop.conversation = (function(mozL10n) {
|
||||
);
|
||||
var notifications = new sharedModels.NotificationCollection();
|
||||
|
||||
window.addEventListener("unload", function(event) {
|
||||
// Handle direct close of dialog box via [x] control.
|
||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
||||
});
|
||||
|
||||
// Obtain the callId and pass it to the conversation
|
||||
// Obtain the callId and pass it through
|
||||
var helper = new loop.shared.utils.Helper();
|
||||
var locationHash = helper.locationHash();
|
||||
if (locationHash) {
|
||||
conversation.set("callId", locationHash.match(/\#incoming\/(.*)/)[1]);
|
||||
}
|
||||
|
||||
React.renderComponent(IncomingConversationView({
|
||||
window.addEventListener("unload", function(event) {
|
||||
// Handle direct close of dialog box via [x] control.
|
||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
||||
});
|
||||
|
||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||
|
||||
React.renderComponent(ConversationControllerView({
|
||||
store: conversationStore,
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
notifications: notifications,
|
||||
@ -539,6 +588,7 @@ loop.conversation = (function(mozL10n) {
|
||||
}
|
||||
|
||||
return {
|
||||
ConversationControllerView: ConversationControllerView,
|
||||
IncomingConversationView: IncomingConversationView,
|
||||
IncomingCallView: IncomingCallView,
|
||||
init: init
|
||||
|
@ -11,8 +11,9 @@ var loop = loop || {};
|
||||
loop.conversation = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var sharedViews = loop.shared.views,
|
||||
sharedModels = loop.shared.models;
|
||||
var sharedViews = loop.shared.views;
|
||||
var sharedModels = loop.shared.models;
|
||||
var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
|
||||
|
||||
var IncomingCallView = React.createClass({
|
||||
|
||||
@ -109,26 +110,23 @@ loop.conversation = (function(mozL10n) {
|
||||
|
||||
render: function() {
|
||||
/* jshint ignore:start */
|
||||
var btnClassAccept = "btn btn-accept";
|
||||
var btnClassDecline = "btn btn-error btn-decline";
|
||||
var conversationPanelClass = "incoming-call";
|
||||
var dropdownMenuClassesDecline = React.addons.classSet({
|
||||
"native-dropdown-menu": true,
|
||||
"conversation-window-dropdown": true,
|
||||
"visually-hidden": !this.state.showDeclineMenu
|
||||
});
|
||||
return (
|
||||
<div className={conversationPanelClass}>
|
||||
<div className="call-window">
|
||||
<h2>{mozL10n.get("incoming_call_title2")}</h2>
|
||||
<div className="btn-group incoming-call-action-group">
|
||||
<div className="btn-group call-action-group">
|
||||
|
||||
<div className="fx-embedded-incoming-call-button-spacer"></div>
|
||||
<div className="fx-embedded-call-button-spacer"></div>
|
||||
|
||||
<div className="btn-chevron-menu-group">
|
||||
<div className="btn-group-chevron">
|
||||
<div className="btn-group">
|
||||
|
||||
<button className={btnClassDecline}
|
||||
<button className="btn btn-error btn-decline"
|
||||
onClick={this._handleDecline}>
|
||||
{mozL10n.get("incoming_call_cancel_button")}
|
||||
</button>
|
||||
@ -146,11 +144,11 @@ loop.conversation = (function(mozL10n) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="fx-embedded-incoming-call-button-spacer"></div>
|
||||
<div className="fx-embedded-call-button-spacer"></div>
|
||||
|
||||
<AcceptCallButton mode={this._answerModeProps()} />
|
||||
|
||||
<div className="fx-embedded-incoming-call-button-spacer"></div>
|
||||
<div className="fx-embedded-call-button-spacer"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -489,6 +487,44 @@ loop.conversation = (function(mozL10n) {
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Master controller view for handling if incoming or outgoing calls are
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var ConversationControllerView = React.createClass({
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
client: React.PropTypes.instanceOf(loop.Client).isRequired,
|
||||
conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
|
||||
.isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
|
||||
.isRequired,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for OutgoingConversationView
|
||||
store: React.PropTypes.instanceOf(loop.ConversationStore).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.state.outgoing) {
|
||||
return (<OutgoingConversationView
|
||||
store={this.props.store}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (<IncomingConversationView
|
||||
client={this.props.client}
|
||||
conversation={this.props.conversation}
|
||||
notifications={this.props.notifications}
|
||||
sdk={this.props.sdk}
|
||||
/>);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Panel initialisation.
|
||||
*/
|
||||
@ -509,8 +545,18 @@ loop.conversation = (function(mozL10n) {
|
||||
}
|
||||
});
|
||||
|
||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||
var conversationStore = new loop.ConversationStore();
|
||||
|
||||
// XXX For now key this on the pref, but this should really be
|
||||
// set by the information from the mozLoop API when we can get it (bug 1072323).
|
||||
var outgoingEmail = navigator.mozLoop.getLoopCharPref("outgoingemail");
|
||||
if (outgoingEmail) {
|
||||
conversationStore.set("outgoing", true);
|
||||
conversationStore.set("calleeId", outgoingEmail);
|
||||
}
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
var client = new loop.Client();
|
||||
var conversation = new sharedModels.ConversationModel(
|
||||
{}, // Model attributes
|
||||
@ -518,19 +564,22 @@ loop.conversation = (function(mozL10n) {
|
||||
);
|
||||
var notifications = new sharedModels.NotificationCollection();
|
||||
|
||||
window.addEventListener("unload", function(event) {
|
||||
// Handle direct close of dialog box via [x] control.
|
||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
||||
});
|
||||
|
||||
// Obtain the callId and pass it to the conversation
|
||||
// Obtain the callId and pass it through
|
||||
var helper = new loop.shared.utils.Helper();
|
||||
var locationHash = helper.locationHash();
|
||||
if (locationHash) {
|
||||
conversation.set("callId", locationHash.match(/\#incoming\/(.*)/)[1]);
|
||||
}
|
||||
|
||||
React.renderComponent(<IncomingConversationView
|
||||
window.addEventListener("unload", function(event) {
|
||||
// Handle direct close of dialog box via [x] control.
|
||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
||||
});
|
||||
|
||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||
|
||||
React.renderComponent(<ConversationControllerView
|
||||
store={conversationStore}
|
||||
client={client}
|
||||
conversation={conversation}
|
||||
notifications={notifications}
|
||||
@ -539,6 +588,7 @@ loop.conversation = (function(mozL10n) {
|
||||
}
|
||||
|
||||
return {
|
||||
ConversationControllerView: ConversationControllerView,
|
||||
IncomingConversationView: IncomingConversationView,
|
||||
IncomingCallView: IncomingCallView,
|
||||
init: init
|
||||
|
100
browser/components/loop/content/js/conversationViews.js
Normal file
100
browser/components/loop/content/js/conversationViews.js
Normal file
@ -0,0 +1,100 @@
|
||||
/** @jsx React.DOM */
|
||||
|
||||
/* 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 loop:true, React */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
/**
|
||||
* Displays details of the incoming/outgoing conversation
|
||||
* (name, link, audio/video type etc).
|
||||
*
|
||||
* Allows the view to be extended with different buttons and progress
|
||||
* via children properties.
|
||||
*/
|
||||
var ConversationDetailView = React.createClass({displayName: 'ConversationDetailView',
|
||||
propTypes: {
|
||||
calleeId: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
document.title = this.props.calleeId;
|
||||
|
||||
return (
|
||||
React.DOM.div({className: "call-window"},
|
||||
React.DOM.h2(null, this.props.calleeId),
|
||||
React.DOM.div(null, this.props.children)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* View for pending conversations. Displays a cancel button and appropriate
|
||||
* pending/ringing strings.
|
||||
*/
|
||||
var PendingConversationView = React.createClass({displayName: 'PendingConversationView',
|
||||
propTypes: {
|
||||
callState: React.PropTypes.string,
|
||||
calleeId: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var pendingStateString;
|
||||
if (this.props.callState === "ringing") {
|
||||
pendingStateString = mozL10n.get("call_progress_pending_description");
|
||||
} else {
|
||||
pendingStateString = mozL10n.get("call_progress_connecting_description");
|
||||
}
|
||||
|
||||
return (
|
||||
ConversationDetailView({calleeId: this.props.calleeId},
|
||||
|
||||
React.DOM.p({className: "btn-label"}, pendingStateString),
|
||||
|
||||
React.DOM.div({className: "btn-group call-action-group"},
|
||||
React.DOM.div({className: "fx-embedded-call-button-spacer"}),
|
||||
React.DOM.button({className: "btn btn-cancel"},
|
||||
mozL10n.get("initiate_call_cancel_button")
|
||||
),
|
||||
React.DOM.div({className: "fx-embedded-call-button-spacer"})
|
||||
)
|
||||
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Master View Controller for outgoing calls. This manages
|
||||
* the different views that need displaying.
|
||||
*/
|
||||
var OutgoingConversationView = React.createClass({displayName: 'OutgoingConversationView',
|
||||
propTypes: {
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.ConversationStore).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (PendingConversationView({
|
||||
callState: this.state.callState,
|
||||
calleeId: this.state.calleeId}
|
||||
))
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
PendingConversationView: PendingConversationView,
|
||||
ConversationDetailView: ConversationDetailView,
|
||||
OutgoingConversationView: OutgoingConversationView
|
||||
};
|
||||
|
||||
})(document.mozL10n || navigator.mozL10n);
|
100
browser/components/loop/content/js/conversationViews.jsx
Normal file
100
browser/components/loop/content/js/conversationViews.jsx
Normal file
@ -0,0 +1,100 @@
|
||||
/** @jsx React.DOM */
|
||||
|
||||
/* 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 loop:true, React */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
/**
|
||||
* Displays details of the incoming/outgoing conversation
|
||||
* (name, link, audio/video type etc).
|
||||
*
|
||||
* Allows the view to be extended with different buttons and progress
|
||||
* via children properties.
|
||||
*/
|
||||
var ConversationDetailView = React.createClass({
|
||||
propTypes: {
|
||||
calleeId: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
document.title = this.props.calleeId;
|
||||
|
||||
return (
|
||||
<div className="call-window">
|
||||
<h2>{this.props.calleeId}</h2>
|
||||
<div>{this.props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* View for pending conversations. Displays a cancel button and appropriate
|
||||
* pending/ringing strings.
|
||||
*/
|
||||
var PendingConversationView = React.createClass({
|
||||
propTypes: {
|
||||
callState: React.PropTypes.string,
|
||||
calleeId: React.PropTypes.string,
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var pendingStateString;
|
||||
if (this.props.callState === "ringing") {
|
||||
pendingStateString = mozL10n.get("call_progress_pending_description");
|
||||
} else {
|
||||
pendingStateString = mozL10n.get("call_progress_connecting_description");
|
||||
}
|
||||
|
||||
return (
|
||||
<ConversationDetailView calleeId={this.props.calleeId}>
|
||||
|
||||
<p className="btn-label">{pendingStateString}</p>
|
||||
|
||||
<div className="btn-group call-action-group">
|
||||
<div className="fx-embedded-call-button-spacer"></div>
|
||||
<button className="btn btn-cancel">
|
||||
{mozL10n.get("initiate_call_cancel_button")}
|
||||
</button>
|
||||
<div className="fx-embedded-call-button-spacer"></div>
|
||||
</div>
|
||||
|
||||
</ConversationDetailView>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Master View Controller for outgoing calls. This manages
|
||||
* the different views that need displaying.
|
||||
*/
|
||||
var OutgoingConversationView = React.createClass({
|
||||
propTypes: {
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.ConversationStore).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (<PendingConversationView
|
||||
callState={this.state.callState}
|
||||
calleeId={this.state.calleeId}
|
||||
/>)
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
PendingConversationView: PendingConversationView,
|
||||
ConversationDetailView: ConversationDetailView,
|
||||
OutgoingConversationView: OutgoingConversationView
|
||||
};
|
||||
|
||||
})(document.mozL10n || navigator.mozL10n);
|
@ -223,14 +223,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Incoming call */
|
||||
/* General Call (incoming or outgoing). */
|
||||
|
||||
/*
|
||||
* Height matches the height of the docked window
|
||||
* but the UI breaks when you pop out
|
||||
* Bug 1040985
|
||||
*/
|
||||
.incoming-call {
|
||||
.call-window {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@ -238,26 +238,27 @@
|
||||
min-height: 230px;
|
||||
}
|
||||
|
||||
.incoming-call-action-group {
|
||||
.call-action-group {
|
||||
display: flex;
|
||||
padding: 2.5em 0 0 0;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.incoming-call-action-group > .btn {
|
||||
.call-action-group > .btn {
|
||||
margin-left: .5em;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.incoming-call-action-group .btn-group-chevron,
|
||||
.incoming-call-action-group .btn-group {
|
||||
.call-action-group .btn-group-chevron,
|
||||
.call-action-group .btn-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* XXX Once we get the incoming call avatar, bug 1047435, the H2 should
|
||||
* disappear from our markup, and we should remove this rule entirely.
|
||||
*/
|
||||
.incoming-call h2 {
|
||||
.call-window h2 {
|
||||
font-size: 1.5em;
|
||||
font-weight: normal;
|
||||
|
||||
@ -266,7 +267,7 @@
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
|
||||
.fx-embedded-incoming-call-button-spacer {
|
||||
.fx-embedded-call-button-spacer {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
/* 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 loop:true */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.ConversationStore = (function() {
|
||||
|
||||
var ConversationStore = Backbone.Model.extend({
|
||||
defaults: {
|
||||
outgoing: false,
|
||||
calleeId: undefined,
|
||||
callState: "gather"
|
||||
},
|
||||
});
|
||||
|
||||
return ConversationStore;
|
||||
})();
|
@ -16,6 +16,7 @@ browser.jar:
|
||||
content/browser/loop/js/otconfig.js (content/js/otconfig.js)
|
||||
content/browser/loop/js/panel.js (content/js/panel.js)
|
||||
content/browser/loop/js/contacts.js (content/js/contacts.js)
|
||||
content/browser/loop/js/conversationViews.js (content/js/conversationViews.js)
|
||||
|
||||
# Shared styles
|
||||
content/browser/loop/shared/css/reset.css (content/shared/css/reset.css)
|
||||
@ -58,6 +59,7 @@ browser.jar:
|
||||
content/browser/loop/shared/js/views.js (content/shared/js/views.js)
|
||||
content/browser/loop/shared/js/utils.js (content/shared/js/utils.js)
|
||||
content/browser/loop/shared/js/websocket.js (content/shared/js/websocket.js)
|
||||
content/browser/loop/shared/js/conversationStore.js (content/shared/js/conversationStore.js)
|
||||
|
||||
# Shared libs
|
||||
#ifdef DEBUG
|
||||
|
@ -68,8 +68,6 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
|
||||
describe("#init", function() {
|
||||
var oldTitle;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox.stub(React, "renderComponent");
|
||||
sandbox.stub(document.mozL10n, "initialize");
|
||||
@ -94,17 +92,63 @@ describe("loop.conversation", function() {
|
||||
navigator.mozLoop);
|
||||
});
|
||||
|
||||
it("should create the IncomingConversationView", function() {
|
||||
it("should create the ConversationControllerView", function() {
|
||||
loop.conversation.init();
|
||||
|
||||
sinon.assert.calledOnce(React.renderComponent);
|
||||
sinon.assert.calledWith(React.renderComponent,
|
||||
sinon.match(function(value) {
|
||||
return TestUtils.isDescriptorOfType(value,
|
||||
loop.conversation.IncomingConversationView);
|
||||
loop.conversation.ConversationControllerView);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe("ConversationControllerView", function() {
|
||||
var store, conversation, client, ccView, oldTitle;
|
||||
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
loop.conversation.ConversationControllerView({
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
notifications: notifications,
|
||||
sdk: {},
|
||||
store: store
|
||||
}));
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
oldTitle = document.title;
|
||||
client = new loop.Client();
|
||||
conversation = new loop.shared.models.ConversationModel({}, {
|
||||
sdk: {}
|
||||
});
|
||||
store = new loop.ConversationStore();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
ccView = undefined;
|
||||
document.title = oldTitle;
|
||||
});
|
||||
|
||||
it("should display the OutgoingConversationView for outgoing calls", function() {
|
||||
store.set({outgoing: true});
|
||||
|
||||
ccView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(ccView,
|
||||
loop.conversationViews.OutgoingConversationView);
|
||||
});
|
||||
|
||||
it("should display the IncomingConversationView for incoming calls", function() {
|
||||
store.set({outgoing: false});
|
||||
|
||||
ccView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(ccView,
|
||||
loop.conversation.IncomingConversationView);
|
||||
});
|
||||
});
|
||||
|
||||
describe("IncomingConversationView", function() {
|
||||
|
@ -34,11 +34,13 @@
|
||||
<!-- App scripts -->
|
||||
<script src="../../content/shared/js/utils.js"></script>
|
||||
<script src="../../content/shared/js/feedbackApiClient.js"></script>
|
||||
<script src="../../content/shared/js/conversationStore.js"></script>
|
||||
<script src="../../content/shared/js/models.js"></script>
|
||||
<script src="../../content/shared/js/mixins.js"></script>
|
||||
<script src="../../content/shared/js/views.js"></script>
|
||||
<script src="../../content/shared/js/websocket.js"></script>
|
||||
<script src="../../content/js/client.js"></script>
|
||||
<script src="../../content/js/conversationViews.js"></script>
|
||||
<script src="../../content/js/conversation.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="../../content/js/contacts.js"></script>
|
||||
<script src="../../content/js/panel.js"></script>
|
||||
|
@ -32,10 +32,13 @@
|
||||
<script src="../content/shared/libs/lodash-2.4.1.js"></script>
|
||||
<script src="../content/shared/libs/backbone-1.1.2.js"></script>
|
||||
<script src="../content/shared/js/feedbackApiClient.js"></script>
|
||||
<script src="../content/shared/js/conversationStore.js"></script>
|
||||
<script src="../content/shared/js/utils.js"></script>
|
||||
<script src="../content/shared/js/models.js"></script>
|
||||
<script src="../content/shared/js/mixins.js"></script>
|
||||
<script src="../content/shared/js/views.js"></script>
|
||||
<script src="../content/shared/js/websocket.js"></script>
|
||||
<script src="../content/js/conversationViews.js"></script>
|
||||
<script src="../content/js/client.js"></script>
|
||||
<script src="../standalone/content/js/webapp.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="../content/js/contacts.js"></script>
|
||||
|
@ -138,8 +138,8 @@
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.incoming-call-action-group .btn-group-chevron,
|
||||
.incoming-call-action-group .btn-group {
|
||||
.call-action-group .btn-group-chevron,
|
||||
.call-action-group .btn-group {
|
||||
/* Prevent box overflow due to long string */
|
||||
max-width: 120px;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
var PanelView = loop.panel.PanelView;
|
||||
// 1.2. Conversation Window
|
||||
var IncomingCallView = loop.conversation.IncomingCallView;
|
||||
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
|
||||
|
||||
// 2. Standalone webapp
|
||||
var HomeView = loop.webapp.HomeView;
|
||||
@ -63,6 +64,12 @@
|
||||
});
|
||||
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.error("Error!");
|
||||
@ -223,12 +230,21 @@
|
||||
Section({name: "PendingConversationView"},
|
||||
Example({summary: "Pending conversation view (connecting)", dashed: "true"},
|
||||
React.DOM.div({className: "standalone"},
|
||||
PendingConversationView(null)
|
||||
PendingConversationView({websocket: mockWebSocket})
|
||||
)
|
||||
),
|
||||
Example({summary: "Pending conversation view (ringing)", dashed: "true"},
|
||||
React.DOM.div({className: "standalone"},
|
||||
PendingConversationView({callState: "ringing"})
|
||||
PendingConversationView({websocket: mockWebSocket, callState: "ringing"})
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
Section({name: "PendingConversationView (Desktop)"},
|
||||
Example({summary: "Connecting", dashed: "true",
|
||||
style: {width: "260px", height: "265px"}},
|
||||
React.DOM.div({className: "fx-embedded"},
|
||||
DesktopPendingConversationView({callState: "gather", calleeId: "Mr Smith"})
|
||||
)
|
||||
)
|
||||
),
|
||||
@ -446,6 +462,9 @@
|
||||
React.renderComponent(App(null), body);
|
||||
|
||||
_renderComponentsInIframes();
|
||||
|
||||
// Put the title back, in case views changed it.
|
||||
document.title = "Loop UI Components Showcase";
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -15,6 +15,7 @@
|
||||
var PanelView = loop.panel.PanelView;
|
||||
// 1.2. Conversation Window
|
||||
var IncomingCallView = loop.conversation.IncomingCallView;
|
||||
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
|
||||
|
||||
// 2. Standalone webapp
|
||||
var HomeView = loop.webapp.HomeView;
|
||||
@ -63,6 +64,12 @@
|
||||
});
|
||||
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.error("Error!");
|
||||
@ -223,12 +230,21 @@
|
||||
<Section name="PendingConversationView">
|
||||
<Example summary="Pending conversation view (connecting)" dashed="true">
|
||||
<div className="standalone">
|
||||
<PendingConversationView />
|
||||
<PendingConversationView websocket={mockWebSocket}/>
|
||||
</div>
|
||||
</Example>
|
||||
<Example summary="Pending conversation view (ringing)" dashed="true">
|
||||
<div className="standalone">
|
||||
<PendingConversationView callState="ringing"/>
|
||||
<PendingConversationView websocket={mockWebSocket} callState="ringing"/>
|
||||
</div>
|
||||
</Example>
|
||||
</Section>
|
||||
|
||||
<Section name="PendingConversationView (Desktop)">
|
||||
<Example summary="Connecting" dashed="true"
|
||||
style={{width: "260px", height: "265px"}}>
|
||||
<div className="fx-embedded">
|
||||
<DesktopPendingConversationView callState={"gather"} calleeId="Mr Smith" />
|
||||
</div>
|
||||
</Example>
|
||||
</Section>
|
||||
@ -446,6 +462,9 @@
|
||||
React.renderComponent(<App />, body);
|
||||
|
||||
_renderComponentsInIframes();
|
||||
|
||||
// Put the title back, in case views changed it.
|
||||
document.title = "Loop UI Components Showcase";
|
||||
});
|
||||
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user