Bug 1072323: Hook up the contact menus to be able to start outgoing calls. r=mikedeboer
This commit is contained in:
@@ -592,11 +592,26 @@ function injectLoopAPI(targetWindow) {
|
|||||||
return MozLoopService.generateUUID();
|
return MozLoopService.generateUUID();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a direct call to the contact addresses.
|
||||||
|
*
|
||||||
|
* @param {Object} contact The contact to call
|
||||||
|
* @param {String} callType The type of call, e.g. "audio-video" or "audio-only"
|
||||||
|
* @return true if the call is opened, false if it is not opened (i.e. busy)
|
||||||
|
*/
|
||||||
|
startDirectCall: {
|
||||||
|
enumerable: true,
|
||||||
|
writable: true,
|
||||||
|
value: function(contact, callType) {
|
||||||
|
MozLoopService.startDirectCall(contact, callType);
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function onStatusChanged(aSubject, aTopic, aData) {
|
function onStatusChanged(aSubject, aTopic, aData) {
|
||||||
let event = new targetWindow.CustomEvent("LoopStatusChanged");
|
let event = new targetWindow.CustomEvent("LoopStatusChanged");
|
||||||
targetWindow.dispatchEvent(event)
|
targetWindow.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
function onDOMWindowDestroyed(aSubject, aTopic, aData) {
|
function onDOMWindowDestroyed(aSubject, aTopic, aData) {
|
||||||
|
|||||||
@@ -719,13 +719,8 @@ let MozLoopServiceInternal = {
|
|||||||
if (respData.calls && Array.isArray(respData.calls)) {
|
if (respData.calls && Array.isArray(respData.calls)) {
|
||||||
respData.calls.forEach((callData) => {
|
respData.calls.forEach((callData) => {
|
||||||
if (!this.callsData.inUse) {
|
if (!this.callsData.inUse) {
|
||||||
this.callsData.inUse = true;
|
|
||||||
callData.sessionType = sessionType;
|
callData.sessionType = sessionType;
|
||||||
this.callsData.data = callData;
|
this._startCall(callData, "incoming");
|
||||||
this.openChatWindow(
|
|
||||||
null,
|
|
||||||
this.localizedStrings["incoming_call_title2"].textContent,
|
|
||||||
"about:loopconversation#incoming/" + callData.callId);
|
|
||||||
} else {
|
} else {
|
||||||
this._returnBusy(callData);
|
this._returnBusy(callData);
|
||||||
}
|
}
|
||||||
@@ -738,6 +733,44 @@ let MozLoopServiceInternal = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a call, saves the call data, and opens a chat window.
|
||||||
|
*
|
||||||
|
* @param {Object} callData The data associated with the call including an id.
|
||||||
|
* @param {Boolean} conversationType Whether or not the call is "incoming"
|
||||||
|
* or "outgoing"
|
||||||
|
*/
|
||||||
|
_startCall: function(callData, conversationType) {
|
||||||
|
this.callsData.inUse = true;
|
||||||
|
this.callsData.data = callData;
|
||||||
|
this.openChatWindow(
|
||||||
|
null,
|
||||||
|
// No title, let the page set that, to avoid flickering.
|
||||||
|
"",
|
||||||
|
"about:loopconversation#" + conversationType + "/" + callData.callId);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a direct call to the contact addresses.
|
||||||
|
*
|
||||||
|
* @param {Object} contact The contact to call
|
||||||
|
* @param {String} callType The type of call, e.g. "audio-video" or "audio-only"
|
||||||
|
* @return true if the call is opened, false if it is not opened (i.e. busy)
|
||||||
|
*/
|
||||||
|
startDirectCall: function(contact, callType) {
|
||||||
|
if (this.callsData.inUse)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var callData = {
|
||||||
|
contact: contact,
|
||||||
|
callType: callType,
|
||||||
|
callId: Math.floor((Math.random() * 10))
|
||||||
|
};
|
||||||
|
|
||||||
|
this._startCall(callData, "outgoing");
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open call progress websocket and terminate with a reason of busy
|
* Open call progress websocket and terminate with a reason of busy
|
||||||
* the server.
|
* the server.
|
||||||
@@ -1505,4 +1538,15 @@ this.MozLoopService = {
|
|||||||
return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj).catch(
|
return MozLoopServiceInternal.hawkRequest(sessionType, path, method, payloadObj).catch(
|
||||||
error => {MozLoopServiceInternal._hawkRequestError(error);});
|
error => {MozLoopServiceInternal._hawkRequestError(error);});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a direct call to the contact addresses.
|
||||||
|
*
|
||||||
|
* @param {Object} contact The contact to call
|
||||||
|
* @param {String} callType The type of call, e.g. "audio-video" or "audio-only"
|
||||||
|
* @return true if the call is opened, false if it is not opened (i.e. busy)
|
||||||
|
*/
|
||||||
|
startDirectCall: function(contact, callType) {
|
||||||
|
MozLoopServiceInternal.startDirectCall(contact, callType);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
|
|
||||||
const Button = loop.shared.views.Button;
|
const Button = loop.shared.views.Button;
|
||||||
const ButtonGroup = loop.shared.views.ButtonGroup;
|
const ButtonGroup = loop.shared.views.ButtonGroup;
|
||||||
|
const CALL_TYPES = loop.shared.utils.CALL_TYPES;
|
||||||
|
|
||||||
// Number of contacts to add to the list at the same time.
|
// Number of contacts to add to the list at the same time.
|
||||||
const CONTACTS_CHUNK_SIZE = 100;
|
const CONTACTS_CHUNK_SIZE = 100;
|
||||||
@@ -85,14 +86,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
return (
|
return (
|
||||||
React.DOM.ul({className: cx({ "dropdown-menu": true,
|
React.DOM.ul({className: cx({ "dropdown-menu": true,
|
||||||
"dropdown-menu-up": this.state.openDirUp })},
|
"dropdown-menu-up": this.state.openDirUp })},
|
||||||
React.DOM.li({className: cx({ "dropdown-menu-item": true,
|
React.DOM.li({className: cx({ "dropdown-menu-item": true }),
|
||||||
"disabled": true }),
|
|
||||||
onClick: this.onItemClick, 'data-action': "video-call"},
|
onClick: this.onItemClick, 'data-action': "video-call"},
|
||||||
React.DOM.i({className: "icon icon-video-call"}),
|
React.DOM.i({className: "icon icon-video-call"}),
|
||||||
mozL10n.get("video_call_menu_button")
|
mozL10n.get("video_call_menu_button")
|
||||||
),
|
),
|
||||||
React.DOM.li({className: cx({ "dropdown-menu-item": true,
|
React.DOM.li({className: cx({ "dropdown-menu-item": true }),
|
||||||
"disabled": true }),
|
|
||||||
onClick: this.onItemClick, 'data-action': "audio-call"},
|
onClick: this.onItemClick, 'data-action': "audio-call"},
|
||||||
React.DOM.i({className: "icon icon-audio-call"}),
|
React.DOM.i({className: "icon icon-audio-call"}),
|
||||||
mozL10n.get("audio_call_menu_button")
|
mozL10n.get("audio_call_menu_button")
|
||||||
@@ -160,7 +159,8 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
return (
|
return (
|
||||||
currContact.name[0] !== nextContact.name[0] ||
|
currContact.name[0] !== nextContact.name[0] ||
|
||||||
currContact.blocked !== nextContact.blocked ||
|
currContact.blocked !== nextContact.blocked ||
|
||||||
getPreferredEmail(currContact).value !== getPreferredEmail(nextContact).value
|
getPreferredEmail(currContact).value !==
|
||||||
|
getPreferredEmail(nextContact).value
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -316,6 +316,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "video-call":
|
||||||
|
navigator.mozLoop.startDirectCall(contact, CALL_TYPES.AUDIO_VIDEO);
|
||||||
|
break;
|
||||||
|
case "audio-call":
|
||||||
|
navigator.mozLoop.startDirectCall(contact, CALL_TYPES.AUDIO_ONLY);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Unrecognized action: " + actionName);
|
console.error("Unrecognized action: " + actionName);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
|
|
||||||
const Button = loop.shared.views.Button;
|
const Button = loop.shared.views.Button;
|
||||||
const ButtonGroup = loop.shared.views.ButtonGroup;
|
const ButtonGroup = loop.shared.views.ButtonGroup;
|
||||||
|
const CALL_TYPES = loop.shared.utils.CALL_TYPES;
|
||||||
|
|
||||||
// Number of contacts to add to the list at the same time.
|
// Number of contacts to add to the list at the same time.
|
||||||
const CONTACTS_CHUNK_SIZE = 100;
|
const CONTACTS_CHUNK_SIZE = 100;
|
||||||
@@ -85,14 +86,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
return (
|
return (
|
||||||
<ul className={cx({ "dropdown-menu": true,
|
<ul className={cx({ "dropdown-menu": true,
|
||||||
"dropdown-menu-up": this.state.openDirUp })}>
|
"dropdown-menu-up": this.state.openDirUp })}>
|
||||||
<li className={cx({ "dropdown-menu-item": true,
|
<li className={cx({ "dropdown-menu-item": true })}
|
||||||
"disabled": true })}
|
|
||||||
onClick={this.onItemClick} data-action="video-call">
|
onClick={this.onItemClick} data-action="video-call">
|
||||||
<i className="icon icon-video-call" />
|
<i className="icon icon-video-call" />
|
||||||
{mozL10n.get("video_call_menu_button")}
|
{mozL10n.get("video_call_menu_button")}
|
||||||
</li>
|
</li>
|
||||||
<li className={cx({ "dropdown-menu-item": true,
|
<li className={cx({ "dropdown-menu-item": true })}
|
||||||
"disabled": true })}
|
|
||||||
onClick={this.onItemClick} data-action="audio-call">
|
onClick={this.onItemClick} data-action="audio-call">
|
||||||
<i className="icon icon-audio-call" />
|
<i className="icon icon-audio-call" />
|
||||||
{mozL10n.get("audio_call_menu_button")}
|
{mozL10n.get("audio_call_menu_button")}
|
||||||
@@ -160,7 +159,8 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
return (
|
return (
|
||||||
currContact.name[0] !== nextContact.name[0] ||
|
currContact.name[0] !== nextContact.name[0] ||
|
||||||
currContact.blocked !== nextContact.blocked ||
|
currContact.blocked !== nextContact.blocked ||
|
||||||
getPreferredEmail(currContact).value !== getPreferredEmail(nextContact).value
|
getPreferredEmail(currContact).value !==
|
||||||
|
getPreferredEmail(nextContact).value
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -316,6 +316,12 @@ loop.contacts = (function(_, mozL10n) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "video-call":
|
||||||
|
navigator.mozLoop.startDirectCall(contact, CALL_TYPES.AUDIO_VIDEO);
|
||||||
|
break;
|
||||||
|
case "audio-call":
|
||||||
|
navigator.mozLoop.startDirectCall(contact, CALL_TYPES.AUDIO_ONLY);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Unrecognized action: " + actionName);
|
console.error("Unrecognized action: " + actionName);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -551,10 +551,6 @@ loop.conversation = (function(mozL10n) {
|
|||||||
sdkDriver: sdkDriver
|
sdkDriver: sdkDriver
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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");
|
|
||||||
|
|
||||||
// XXX Old class creation for the incoming conversation view, whilst
|
// XXX Old class creation for the incoming conversation view, whilst
|
||||||
// we transition across (bug 1072323).
|
// we transition across (bug 1072323).
|
||||||
var conversation = new sharedModels.ConversationModel(
|
var conversation = new sharedModels.ConversationModel(
|
||||||
@@ -566,14 +562,25 @@ loop.conversation = (function(mozL10n) {
|
|||||||
var helper = new loop.shared.utils.Helper();
|
var helper = new loop.shared.utils.Helper();
|
||||||
var locationHash = helper.locationHash();
|
var locationHash = helper.locationHash();
|
||||||
var callId;
|
var callId;
|
||||||
if (locationHash) {
|
var outgoing;
|
||||||
callId = locationHash.match(/\#incoming\/(.*)/)[1]
|
|
||||||
conversation.set("callId", callId);
|
var hash = locationHash.match(/\#incoming\/(.*)/);
|
||||||
|
if (hash) {
|
||||||
|
callId = hash[1];
|
||||||
|
outgoing = false;
|
||||||
|
} else {
|
||||||
|
hash = locationHash.match(/\#outgoing\/(.*)/);
|
||||||
|
if (hash) {
|
||||||
|
callId = hash[1];
|
||||||
|
outgoing = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conversation.set({callId: callId});
|
||||||
|
|
||||||
window.addEventListener("unload", function(event) {
|
window.addEventListener("unload", function(event) {
|
||||||
// Handle direct close of dialog box via [x] control.
|
// Handle direct close of dialog box via [x] control.
|
||||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
navigator.mozLoop.releaseCallData(callId);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||||
@@ -588,7 +595,7 @@ loop.conversation = (function(mozL10n) {
|
|||||||
|
|
||||||
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
||||||
callId: callId,
|
callId: callId,
|
||||||
calleeId: outgoingEmail
|
outgoing: outgoing
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -551,10 +551,6 @@ loop.conversation = (function(mozL10n) {
|
|||||||
sdkDriver: sdkDriver
|
sdkDriver: sdkDriver
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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");
|
|
||||||
|
|
||||||
// XXX Old class creation for the incoming conversation view, whilst
|
// XXX Old class creation for the incoming conversation view, whilst
|
||||||
// we transition across (bug 1072323).
|
// we transition across (bug 1072323).
|
||||||
var conversation = new sharedModels.ConversationModel(
|
var conversation = new sharedModels.ConversationModel(
|
||||||
@@ -566,14 +562,25 @@ loop.conversation = (function(mozL10n) {
|
|||||||
var helper = new loop.shared.utils.Helper();
|
var helper = new loop.shared.utils.Helper();
|
||||||
var locationHash = helper.locationHash();
|
var locationHash = helper.locationHash();
|
||||||
var callId;
|
var callId;
|
||||||
if (locationHash) {
|
var outgoing;
|
||||||
callId = locationHash.match(/\#incoming\/(.*)/)[1]
|
|
||||||
conversation.set("callId", callId);
|
var hash = locationHash.match(/\#incoming\/(.*)/);
|
||||||
|
if (hash) {
|
||||||
|
callId = hash[1];
|
||||||
|
outgoing = false;
|
||||||
|
} else {
|
||||||
|
hash = locationHash.match(/\#outgoing\/(.*)/);
|
||||||
|
if (hash) {
|
||||||
|
callId = hash[1];
|
||||||
|
outgoing = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conversation.set({callId: callId});
|
||||||
|
|
||||||
window.addEventListener("unload", function(event) {
|
window.addEventListener("unload", function(event) {
|
||||||
// Handle direct close of dialog box via [x] control.
|
// Handle direct close of dialog box via [x] control.
|
||||||
navigator.mozLoop.releaseCallData(conversation.get("callId"));
|
navigator.mozLoop.releaseCallData(callId);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
document.body.classList.add(loop.shared.utils.getTargetPlatform());
|
||||||
@@ -588,7 +595,7 @@ loop.conversation = (function(mozL10n) {
|
|||||||
|
|
||||||
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
||||||
callId: callId,
|
callId: callId,
|
||||||
calleeId: outgoingEmail
|
outgoing: outgoing
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,15 +23,35 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
*/
|
*/
|
||||||
var ConversationDetailView = React.createClass({displayName: 'ConversationDetailView',
|
var ConversationDetailView = React.createClass({displayName: 'ConversationDetailView',
|
||||||
propTypes: {
|
propTypes: {
|
||||||
calleeId: React.PropTypes.string,
|
contact: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
// This duplicates a similar function in contacts.jsx that isn't used in the
|
||||||
|
// conversation window. If we get too many of these, we might want to consider
|
||||||
|
// finding a logical place for them to be shared.
|
||||||
|
_getPreferredEmail: function(contact) {
|
||||||
|
// A contact may not contain email addresses, but only a phone number.
|
||||||
|
if (!contact.email || contact.email.length == 0) {
|
||||||
|
return { value: "" };
|
||||||
|
}
|
||||||
|
return contact.email.find(e => e.pref) || contact.email[0];
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
document.title = this.props.calleeId;
|
var contactName;
|
||||||
|
|
||||||
|
if (this.props.contact.name &&
|
||||||
|
this.props.contact.name[0]) {
|
||||||
|
contactName = this.props.contact.name[0];
|
||||||
|
} else {
|
||||||
|
contactName = this._getPreferredEmail(this.props.contact).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.title = contactName;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
React.DOM.div({className: "call-window"},
|
React.DOM.div({className: "call-window"},
|
||||||
React.DOM.h2(null, this.props.calleeId),
|
React.DOM.h2(null, contactName),
|
||||||
React.DOM.div(null, this.props.children)
|
React.DOM.div(null, this.props.children)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -46,7 +66,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
propTypes: {
|
propTypes: {
|
||||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||||
callState: React.PropTypes.string,
|
callState: React.PropTypes.string,
|
||||||
calleeId: React.PropTypes.string,
|
contact: React.PropTypes.object,
|
||||||
enableCancelButton: React.PropTypes.bool
|
enableCancelButton: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -76,7 +96,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
ConversationDetailView({calleeId: this.props.calleeId},
|
ConversationDetailView({contact: this.props.contact},
|
||||||
|
|
||||||
React.DOM.p({className: "btn-label"}, pendingStateString),
|
React.DOM.p({className: "btn-label"}, pendingStateString),
|
||||||
|
|
||||||
@@ -340,8 +360,8 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
case CALL_STATES.ONGOING: {
|
case CALL_STATES.ONGOING: {
|
||||||
return (OngoingConversationView({
|
return (OngoingConversationView({
|
||||||
dispatcher: this.props.dispatcher,
|
dispatcher: this.props.dispatcher,
|
||||||
video: {enabled: this.state.videoMuted},
|
video: {enabled: !this.state.videoMuted},
|
||||||
audio: {enabled: this.state.audioMuted}}
|
audio: {enabled: !this.state.audioMuted}}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -352,7 +372,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
return (PendingConversationView({
|
return (PendingConversationView({
|
||||||
dispatcher: this.props.dispatcher,
|
dispatcher: this.props.dispatcher,
|
||||||
callState: this.state.callState,
|
callState: this.state.callState,
|
||||||
calleeId: this.state.calleeId,
|
contact: this.state.contact,
|
||||||
enableCancelButton: this._isCancellable()}
|
enableCancelButton: this._isCancellable()}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,35 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
*/
|
*/
|
||||||
var ConversationDetailView = React.createClass({
|
var ConversationDetailView = React.createClass({
|
||||||
propTypes: {
|
propTypes: {
|
||||||
calleeId: React.PropTypes.string,
|
contact: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
// This duplicates a similar function in contacts.jsx that isn't used in the
|
||||||
|
// conversation window. If we get too many of these, we might want to consider
|
||||||
|
// finding a logical place for them to be shared.
|
||||||
|
_getPreferredEmail: function(contact) {
|
||||||
|
// A contact may not contain email addresses, but only a phone number.
|
||||||
|
if (!contact.email || contact.email.length == 0) {
|
||||||
|
return { value: "" };
|
||||||
|
}
|
||||||
|
return contact.email.find(e => e.pref) || contact.email[0];
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
document.title = this.props.calleeId;
|
var contactName;
|
||||||
|
|
||||||
|
if (this.props.contact.name &&
|
||||||
|
this.props.contact.name[0]) {
|
||||||
|
contactName = this.props.contact.name[0];
|
||||||
|
} else {
|
||||||
|
contactName = this._getPreferredEmail(this.props.contact).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.title = contactName;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="call-window">
|
<div className="call-window">
|
||||||
<h2>{this.props.calleeId}</h2>
|
<h2>{contactName}</h2>
|
||||||
<div>{this.props.children}</div>
|
<div>{this.props.children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -46,7 +66,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
propTypes: {
|
propTypes: {
|
||||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||||
callState: React.PropTypes.string,
|
callState: React.PropTypes.string,
|
||||||
calleeId: React.PropTypes.string,
|
contact: React.PropTypes.object,
|
||||||
enableCancelButton: React.PropTypes.bool
|
enableCancelButton: React.PropTypes.bool
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -76,7 +96,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConversationDetailView calleeId={this.props.calleeId}>
|
<ConversationDetailView contact={this.props.contact}>
|
||||||
|
|
||||||
<p className="btn-label">{pendingStateString}</p>
|
<p className="btn-label">{pendingStateString}</p>
|
||||||
|
|
||||||
@@ -340,8 +360,8 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
case CALL_STATES.ONGOING: {
|
case CALL_STATES.ONGOING: {
|
||||||
return (<OngoingConversationView
|
return (<OngoingConversationView
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
video={{enabled: this.state.videoMuted}}
|
video={{enabled: !this.state.videoMuted}}
|
||||||
audio={{enabled: this.state.audioMuted}}
|
audio={{enabled: !this.state.audioMuted}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -352,7 +372,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||||||
return (<PendingConversationView
|
return (<PendingConversationView
|
||||||
dispatcher={this.props.dispatcher}
|
dispatcher={this.props.dispatcher}
|
||||||
callState={this.state.callState}
|
callState={this.state.callState}
|
||||||
calleeId={this.state.calleeId}
|
contact={this.state.contact}
|
||||||
enableCancelButton={this._isCancellable()}
|
enableCancelButton={this._isCancellable()}
|
||||||
/>)
|
/>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,9 @@ loop.shared.actions = (function() {
|
|||||||
* Used to trigger gathering of initial call data.
|
* Used to trigger gathering of initial call data.
|
||||||
*/
|
*/
|
||||||
GatherCallData: Action.define("gatherCallData", {
|
GatherCallData: Action.define("gatherCallData", {
|
||||||
// XXX This may change when bug 1072323 is implemented.
|
|
||||||
// Optional: Specify the calleeId for an outgoing call
|
|
||||||
calleeId: [String, null],
|
|
||||||
// Specify the callId for an incoming call.
|
// Specify the callId for an incoming call.
|
||||||
callId: [String, null]
|
callId: [String, null],
|
||||||
|
outgoing: Boolean
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ loop.store = (function() {
|
|||||||
error: undefined,
|
error: undefined,
|
||||||
// True if the call is outgoing, false if not, undefined if unknown
|
// True if the call is outgoing, false if not, undefined if unknown
|
||||||
outgoing: undefined,
|
outgoing: undefined,
|
||||||
// The id of the person being called for outgoing calls
|
// The contact being called for outgoing calls
|
||||||
calleeId: undefined,
|
contact: undefined,
|
||||||
// The call type for the call.
|
// The call type for the call.
|
||||||
// XXX Don't hard-code, this comes from the data in bug 1072323
|
// XXX Don't hard-code, this comes from the data in bug 1072323
|
||||||
callType: CALL_TYPES.AUDIO_VIDEO,
|
callType: CALL_TYPES.AUDIO_VIDEO,
|
||||||
@@ -83,9 +83,9 @@ loop.store = (function() {
|
|||||||
// SDK session token
|
// SDK session token
|
||||||
sessionToken: undefined,
|
sessionToken: undefined,
|
||||||
// If the audio is muted
|
// If the audio is muted
|
||||||
audioMuted: true,
|
audioMuted: false,
|
||||||
// If the video is muted
|
// If the video is muted
|
||||||
videoMuted: true
|
videoMuted: false
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,14 +192,29 @@ loop.store = (function() {
|
|||||||
* @param {sharedActions.GatherCallData} actionData The action data.
|
* @param {sharedActions.GatherCallData} actionData The action data.
|
||||||
*/
|
*/
|
||||||
gatherCallData: function(actionData) {
|
gatherCallData: function(actionData) {
|
||||||
|
if (!actionData.outgoing) {
|
||||||
|
// XXX Other types aren't supported yet, but set the state for the
|
||||||
|
// view selection.
|
||||||
|
this.set({outgoing: false});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var callData = navigator.mozLoop.getCallData(actionData.callId);
|
||||||
|
if (!callData) {
|
||||||
|
console.error("Failed to get the call data");
|
||||||
|
this.set({callState: CALL_STATES.TERMINATED});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.set({
|
this.set({
|
||||||
calleeId: actionData.calleeId,
|
contact: callData.contact,
|
||||||
outgoing: !!actionData.calleeId,
|
outgoing: actionData.outgoing,
|
||||||
callId: actionData.callId,
|
callId: actionData.callId,
|
||||||
|
callType: callData.callType,
|
||||||
callState: CALL_STATES.GATHER
|
callState: CALL_STATES.GATHER
|
||||||
});
|
});
|
||||||
|
|
||||||
this.videoMuted = this.get("callType") !== CALL_TYPES.AUDIO_VIDEO;
|
this.set({videoMuted: this.get("callType") === CALL_TYPES.AUDIO_ONLY});
|
||||||
|
|
||||||
if (this.get("outgoing")) {
|
if (this.get("outgoing")) {
|
||||||
this._setupOutgoingCall();
|
this._setupOutgoingCall();
|
||||||
@@ -285,7 +300,7 @@ loop.store = (function() {
|
|||||||
*/
|
*/
|
||||||
setMute: function(actionData) {
|
setMute: function(actionData) {
|
||||||
var muteType = actionData.type + "Muted";
|
var muteType = actionData.type + "Muted";
|
||||||
this.set(muteType, actionData.enabled);
|
this.set(muteType, !actionData.enabled);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,8 +308,13 @@ loop.store = (function() {
|
|||||||
* result.
|
* result.
|
||||||
*/
|
*/
|
||||||
_setupOutgoingCall: function() {
|
_setupOutgoingCall: function() {
|
||||||
// XXX For now, we only have one calleeId, so just wrap that in an array.
|
var contactAddresses = [];
|
||||||
this.client.setupOutgoingCall([this.get("calleeId")],
|
|
||||||
|
this.get("contact").email.forEach(function(address) {
|
||||||
|
contactAddresses.push(address.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.setupOutgoingCall(contactAddresses,
|
||||||
this.get("callType"),
|
this.get("callType"),
|
||||||
function(err, result) {
|
function(err, result) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
var expect = chai.expect;
|
var expect = chai.expect;
|
||||||
|
|
||||||
describe("loop.conversationViews", function () {
|
describe("loop.conversationViews", function () {
|
||||||
var sandbox, oldTitle, view, dispatcher;
|
var sandbox, oldTitle, view, dispatcher, contact;
|
||||||
|
|
||||||
var CALL_STATES = loop.store.CALL_STATES;
|
var CALL_STATES = loop.store.CALL_STATES;
|
||||||
|
|
||||||
@@ -18,6 +18,15 @@ describe("loop.conversationViews", function () {
|
|||||||
|
|
||||||
dispatcher = new loop.Dispatcher();
|
dispatcher = new loop.Dispatcher();
|
||||||
sandbox.stub(dispatcher, "dispatch");
|
sandbox.stub(dispatcher, "dispatch");
|
||||||
|
|
||||||
|
contact = {
|
||||||
|
name: [ "mrsmith" ],
|
||||||
|
email: [{
|
||||||
|
type: "home",
|
||||||
|
value: "fakeEmail",
|
||||||
|
pref: true
|
||||||
|
}]
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@@ -33,17 +42,28 @@ describe("loop.conversationViews", function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it("should set the document title to the calledId", function() {
|
it("should set the document title to the calledId", function() {
|
||||||
mountTestComponent({calleeId: "mrsmith"});
|
mountTestComponent({contact: contact});
|
||||||
|
|
||||||
expect(document.title).eql("mrsmith");
|
expect(document.title).eql("mrsmith");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set display the calledId", function() {
|
it("should set display the calledId", function() {
|
||||||
view = mountTestComponent({calleeId: "mrsmith"});
|
view = mountTestComponent({contact: contact});
|
||||||
|
|
||||||
expect(TestUtils.findRenderedDOMComponentWithTag(
|
expect(TestUtils.findRenderedDOMComponentWithTag(
|
||||||
view, "h2").props.children).eql("mrsmith");
|
view, "h2").props.children).eql("mrsmith");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should fallback to the email if the contact name is not defined",
|
||||||
|
function() {
|
||||||
|
delete contact.name;
|
||||||
|
|
||||||
|
view = mountTestComponent({contact: contact});
|
||||||
|
|
||||||
|
expect(TestUtils.findRenderedDOMComponentWithTag(
|
||||||
|
view, "h2").props.children).eql("fakeEmail");
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("PendingConversationView", function() {
|
describe("PendingConversationView", function() {
|
||||||
@@ -56,7 +76,7 @@ describe("loop.conversationViews", function () {
|
|||||||
function() {
|
function() {
|
||||||
view = mountTestComponent({
|
view = mountTestComponent({
|
||||||
callState: CALL_STATES.CONNECTING,
|
callState: CALL_STATES.CONNECTING,
|
||||||
calleeId: "mrsmith",
|
contact: contact,
|
||||||
dispatcher: dispatcher
|
dispatcher: dispatcher
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -70,7 +90,7 @@ describe("loop.conversationViews", function () {
|
|||||||
function() {
|
function() {
|
||||||
view = mountTestComponent({
|
view = mountTestComponent({
|
||||||
callState: CALL_STATES.ALERTING,
|
callState: CALL_STATES.ALERTING,
|
||||||
calleeId: "mrsmith",
|
contact: contact,
|
||||||
dispatcher: dispatcher
|
dispatcher: dispatcher
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,7 +104,7 @@ describe("loop.conversationViews", function () {
|
|||||||
function() {
|
function() {
|
||||||
view = mountTestComponent({
|
view = mountTestComponent({
|
||||||
callState: CALL_STATES.CONNECTING,
|
callState: CALL_STATES.CONNECTING,
|
||||||
calleeId: "mrsmith",
|
contact: contact,
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
enableCancelButton: false
|
enableCancelButton: false
|
||||||
});
|
});
|
||||||
@@ -98,7 +118,7 @@ describe("loop.conversationViews", function () {
|
|||||||
function() {
|
function() {
|
||||||
view = mountTestComponent({
|
view = mountTestComponent({
|
||||||
callState: CALL_STATES.CONNECTING,
|
callState: CALL_STATES.CONNECTING,
|
||||||
calleeId: "mrsmith",
|
contact: contact,
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
enableCancelButton: true
|
enableCancelButton: true
|
||||||
});
|
});
|
||||||
@@ -112,7 +132,7 @@ describe("loop.conversationViews", function () {
|
|||||||
function() {
|
function() {
|
||||||
view = mountTestComponent({
|
view = mountTestComponent({
|
||||||
callState: CALL_STATES.CONNECTING,
|
callState: CALL_STATES.CONNECTING,
|
||||||
calleeId: "mrsmith",
|
contact: contact,
|
||||||
dispatcher: dispatcher
|
dispatcher: dispatcher
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -293,7 +313,10 @@ describe("loop.conversationViews", function () {
|
|||||||
|
|
||||||
it("should render the PendingConversationView when the call state is 'init'",
|
it("should render the PendingConversationView when the call state is 'init'",
|
||||||
function() {
|
function() {
|
||||||
store.set({callState: CALL_STATES.INIT});
|
store.set({
|
||||||
|
callState: CALL_STATES.INIT,
|
||||||
|
contact: contact
|
||||||
|
});
|
||||||
|
|
||||||
view = mountTestComponent();
|
view = mountTestComponent();
|
||||||
|
|
||||||
@@ -323,7 +346,10 @@ describe("loop.conversationViews", function () {
|
|||||||
|
|
||||||
it("should update the rendered views when the state is changed.",
|
it("should update the rendered views when the state is changed.",
|
||||||
function() {
|
function() {
|
||||||
store.set({callState: CALL_STATES.INIT});
|
store.set({
|
||||||
|
callState: CALL_STATES.INIT,
|
||||||
|
contact: contact
|
||||||
|
});
|
||||||
|
|
||||||
view = mountTestComponent();
|
view = mountTestComponent();
|
||||||
|
|
||||||
|
|||||||
@@ -115,10 +115,24 @@ describe("loop.conversation", function() {
|
|||||||
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
||||||
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
||||||
new loop.shared.actions.GatherCallData({
|
new loop.shared.actions.GatherCallData({
|
||||||
calleeId: null,
|
callId: "42",
|
||||||
callId: "42"
|
outgoing: false
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should trigger an outgoing gatherCallData action for outgoing calls",
|
||||||
|
function() {
|
||||||
|
loop.shared.utils.Helper.prototype.locationHash.returns("#outgoing/24");
|
||||||
|
|
||||||
|
loop.conversation.init();
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
||||||
|
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
||||||
|
new loop.shared.actions.GatherCallData({
|
||||||
|
callId: "24",
|
||||||
|
outgoing: true
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ConversationControllerView", function() {
|
describe("ConversationControllerView", function() {
|
||||||
@@ -141,7 +155,16 @@ describe("loop.conversation", function() {
|
|||||||
sdk: {}
|
sdk: {}
|
||||||
});
|
});
|
||||||
dispatcher = new loop.Dispatcher();
|
dispatcher = new loop.Dispatcher();
|
||||||
store = new loop.store.ConversationStore({}, {
|
store = new loop.store.ConversationStore({
|
||||||
|
contact: {
|
||||||
|
name: [ "Mr Smith" ],
|
||||||
|
email: [{
|
||||||
|
type: "home",
|
||||||
|
value: "fakeEmail",
|
||||||
|
pref: true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
client: client,
|
client: client,
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
sdkDriver: {}
|
sdkDriver: {}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ describe("loop.ConversationStore", function () {
|
|||||||
var sharedActions = loop.shared.actions;
|
var sharedActions = loop.shared.actions;
|
||||||
var sharedUtils = loop.shared.utils;
|
var sharedUtils = loop.shared.utils;
|
||||||
var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver;
|
var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver;
|
||||||
|
var contact;
|
||||||
var connectPromise, resolveConnectPromise, rejectConnectPromise;
|
var connectPromise, resolveConnectPromise, rejectConnectPromise;
|
||||||
var wsCancelSpy, wsCloseSpy, wsMediaUpSpy, fakeWebsocket;
|
var wsCancelSpy, wsCloseSpy, wsMediaUpSpy, fakeWebsocket;
|
||||||
|
|
||||||
@@ -26,6 +27,15 @@ describe("loop.ConversationStore", function () {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
contact = {
|
||||||
|
name: [ "Mr Smith" ],
|
||||||
|
email: [{
|
||||||
|
type: "home",
|
||||||
|
value: "fakeEmail",
|
||||||
|
pref: true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
dispatcher = new loop.Dispatcher();
|
dispatcher = new loop.Dispatcher();
|
||||||
client = {
|
client = {
|
||||||
setupOutgoingCall: sinon.stub()
|
setupOutgoingCall: sinon.stub()
|
||||||
@@ -199,13 +209,26 @@ describe("loop.ConversationStore", function () {
|
|||||||
describe("#gatherCallData", function() {
|
describe("#gatherCallData", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
store.set({callState: CALL_STATES.INIT});
|
store.set({callState: CALL_STATES.INIT});
|
||||||
|
|
||||||
|
navigator.mozLoop = {
|
||||||
|
getCallData: function() {
|
||||||
|
return {
|
||||||
|
contact: contact,
|
||||||
|
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
delete navigator.mozLoop;
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set the state to 'gather'", function() {
|
it("should set the state to 'gather'", function() {
|
||||||
dispatcher.dispatch(
|
dispatcher.dispatch(
|
||||||
new sharedActions.GatherCallData({
|
new sharedActions.GatherCallData({
|
||||||
calleeId: "",
|
callId: "76543218",
|
||||||
callId: "76543218"
|
outgoing: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(store.get("callState")).eql(CALL_STATES.GATHER);
|
expect(store.get("callState")).eql(CALL_STATES.GATHER);
|
||||||
@@ -214,22 +237,32 @@ describe("loop.ConversationStore", function () {
|
|||||||
it("should save the basic call information", function() {
|
it("should save the basic call information", function() {
|
||||||
dispatcher.dispatch(
|
dispatcher.dispatch(
|
||||||
new sharedActions.GatherCallData({
|
new sharedActions.GatherCallData({
|
||||||
calleeId: "fake",
|
callId: "123456",
|
||||||
callId: "123456"
|
outgoing: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(store.get("calleeId")).eql("fake");
|
|
||||||
expect(store.get("callId")).eql("123456");
|
expect(store.get("callId")).eql("123456");
|
||||||
expect(store.get("outgoing")).eql(true);
|
expect(store.get("outgoing")).eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should save the basic information from the mozLoop api", function() {
|
||||||
|
dispatcher.dispatch(
|
||||||
|
new sharedActions.GatherCallData({
|
||||||
|
callId: "123456",
|
||||||
|
outgoing: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(store.get("contact")).eql(contact);
|
||||||
|
expect(store.get("callType")).eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||||
|
});
|
||||||
|
|
||||||
describe("outgoing calls", function() {
|
describe("outgoing calls", function() {
|
||||||
var outgoingCallData;
|
var outgoingCallData;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
outgoingCallData = {
|
outgoingCallData = {
|
||||||
calleeId: "fake",
|
callId: "123456",
|
||||||
callId: "135246"
|
outgoing: true
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -239,7 +272,7 @@ describe("loop.ConversationStore", function () {
|
|||||||
|
|
||||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||||
["fake"], sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
["fakeEmail"], sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("server response handling", function() {
|
describe("server response handling", function() {
|
||||||
@@ -488,14 +521,14 @@ describe("loop.ConversationStore", function () {
|
|||||||
callState: CALL_STATES.TERMINATED,
|
callState: CALL_STATES.TERMINATED,
|
||||||
outgoing: true,
|
outgoing: true,
|
||||||
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO,
|
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO,
|
||||||
calleeId: "fake"
|
contact: contact
|
||||||
});
|
});
|
||||||
|
|
||||||
dispatcher.dispatch(new sharedActions.RetryCall());
|
dispatcher.dispatch(new sharedActions.RetryCall());
|
||||||
|
|
||||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||||
["fake"], sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
["fakeEmail"], sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -518,7 +551,7 @@ describe("loop.ConversationStore", function () {
|
|||||||
enabled: true
|
enabled: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(store.get("audioMuted")).eql(true);
|
expect(store.get("audioMuted")).eql(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should save the mute state for the video stream", function() {
|
it("should save the mute state for the video stream", function() {
|
||||||
@@ -529,7 +562,7 @@ describe("loop.ConversationStore", function () {
|
|||||||
enabled: false
|
enabled: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(store.get("videoMuted")).eql(false);
|
expect(store.get("videoMuted")).eql(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ describe("loop.Dispatcher", function () {
|
|||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
gatherAction = new sharedActions.GatherCallData({
|
gatherAction = new sharedActions.GatherCallData({
|
||||||
callId: "42",
|
callId: "42",
|
||||||
calleeId: null
|
outgoing: false
|
||||||
});
|
});
|
||||||
|
|
||||||
cancelAction = new sharedActions.CancelCall();
|
cancelAction = new sharedActions.CancelCall();
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "Chat",
|
||||||
|
"resource:///modules/Chat.jsm");
|
||||||
|
let openChatOrig = Chat.open;
|
||||||
|
|
||||||
|
const contact = {
|
||||||
|
name: [ "Mr Smith" ],
|
||||||
|
email: [{
|
||||||
|
type: "home",
|
||||||
|
value: "fakeEmail",
|
||||||
|
pref: true
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
add_task(function test_startDirectCall_opens_window() {
|
||||||
|
let openedUrl;
|
||||||
|
Chat.open = function(contentWindow, origin, title, url) {
|
||||||
|
openedUrl = url;
|
||||||
|
};
|
||||||
|
|
||||||
|
MozLoopService.startDirectCall(contact, "audio-video");
|
||||||
|
|
||||||
|
do_check_true(!!openedUrl, "should open a chat window");
|
||||||
|
|
||||||
|
// Stop the busy kicking in for following tests.
|
||||||
|
let callId = openedUrl.match(/about:loopconversation\#outgoing\/(.*)/)[1];
|
||||||
|
MozLoopService.releaseCallData(callId);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function test_startDirectCall_getCallData() {
|
||||||
|
let openedUrl;
|
||||||
|
Chat.open = function(contentWindow, origin, title, url) {
|
||||||
|
openedUrl = url;
|
||||||
|
};
|
||||||
|
|
||||||
|
MozLoopService.startDirectCall(contact, "audio-video");
|
||||||
|
|
||||||
|
let callId = openedUrl.match(/about:loopconversation\#outgoing\/(.*)/)[1];
|
||||||
|
|
||||||
|
let callData = MozLoopService.getCallData(callId);
|
||||||
|
|
||||||
|
do_check_eq(callData.callType, "audio-video", "should have the correct call type");
|
||||||
|
do_check_eq(callData.contact, contact, "should have the contact details");
|
||||||
|
|
||||||
|
// Stop the busy kicking in for following tests.
|
||||||
|
MozLoopService.releaseCallData(callId);
|
||||||
|
});
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
do_register_cleanup(function() {
|
||||||
|
// Revert original Chat.open implementation
|
||||||
|
Chat.open = openChatOrig;
|
||||||
|
});
|
||||||
|
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ firefox-appdir = browser
|
|||||||
|
|
||||||
[test_loopapi_hawk_request.js]
|
[test_loopapi_hawk_request.js]
|
||||||
[test_looppush_initialize.js]
|
[test_looppush_initialize.js]
|
||||||
|
[test_loopservice_directcall.js]
|
||||||
[test_loopservice_dnd.js]
|
[test_loopservice_dnd.js]
|
||||||
[test_loopservice_expiry.js]
|
[test_loopservice_expiry.js]
|
||||||
[test_loopservice_hawk_errors.js]
|
[test_loopservice_hawk_errors.js]
|
||||||
@@ -17,4 +18,4 @@ firefox-appdir = browser
|
|||||||
[test_loopservice_token_save.js]
|
[test_loopservice_token_save.js]
|
||||||
[test_loopservice_token_send.js]
|
[test_loopservice_token_send.js]
|
||||||
[test_loopservice_token_validation.js]
|
[test_loopservice_token_validation.js]
|
||||||
[test_loopservice_busy.js]
|
[test_loopservice_busy.js]
|
||||||
|
|||||||
Reference in New Issue
Block a user