зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1208466 - Part 2. If an owner of a Loop link clicks their own link and join, make it open the conversation window. r=mikedeboer
This commit is contained in:
Родитель
b082faea89
Коммит
aaca92e04c
Двоичные данные
browser/components/loop/content/shared/img/mozilla-logo.png
Двоичные данные
browser/components/loop/content/shared/img/mozilla-logo.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.9 KiB |
|
@ -468,6 +468,13 @@ loop.shared.actions = (function() {
|
|||
// socialShareProviders: Array - Optional.
|
||||
}),
|
||||
|
||||
/**
|
||||
* Notifies if the user agent will handle the room or not.
|
||||
*/
|
||||
UserAgentHandlesRoom: Action.define("userAgentHandlesRoom", {
|
||||
handlesRoom: Boolean
|
||||
}),
|
||||
|
||||
/**
|
||||
* Updates the Social API information when it is received.
|
||||
* XXX: should move to some roomActions module - refs bug 1079284
|
||||
|
@ -483,6 +490,16 @@ loop.shared.actions = (function() {
|
|||
JoinRoom: Action.define("joinRoom", {
|
||||
}),
|
||||
|
||||
/**
|
||||
* A special action for metrics logging to define what type of join
|
||||
* occurred when JoinRoom was activated.
|
||||
* XXX: should move to some roomActions module - refs bug 1079284
|
||||
*/
|
||||
MetricsLogJoinRoom: Action.define("metricsLogJoinRoom", {
|
||||
userAgentHandledRoom: Boolean
|
||||
// ownRoom: Boolean - Optional. Expected if firefoxHandledRoom is true.
|
||||
}),
|
||||
|
||||
/**
|
||||
* Starts the process for the user to join the room.
|
||||
* XXX: should move to some roomActions module - refs bug 1079284
|
||||
|
|
|
@ -132,6 +132,9 @@ loop.store.ActiveRoomStore = (function() {
|
|||
videoMuted: false,
|
||||
remoteVideoEnabled: false,
|
||||
failureReason: undefined,
|
||||
// Whether or not Firefox can handle this room in the conversation
|
||||
// window, rather than us handling it in the standalone.
|
||||
userAgentHandlesRoom: undefined,
|
||||
// Tracks if the room has been used during this
|
||||
// session. 'Used' means at least one call has been placed
|
||||
// with it. Entering and leaving the room without seeing
|
||||
|
@ -237,6 +240,7 @@ loop.store.ActiveRoomStore = (function() {
|
|||
"roomFailure",
|
||||
"retryAfterRoomFailure",
|
||||
"updateRoomInfo",
|
||||
"userAgentHandlesRoom",
|
||||
"gotMediaPermission",
|
||||
"joinRoom",
|
||||
"joinedRoom",
|
||||
|
@ -327,6 +331,9 @@ loop.store.ActiveRoomStore = (function() {
|
|||
* This action is only used for the standalone UI.
|
||||
*
|
||||
* @param {sharedActions.FetchServerData} actionData
|
||||
* @return {Promise} For testing purposes, returns a promise that is resolved
|
||||
* once data is received from the server, and it is determined
|
||||
* if Firefox handles the room or not.
|
||||
*/
|
||||
fetchServerData: function(actionData) {
|
||||
if (actionData.windowType !== "room") {
|
||||
|
@ -342,68 +349,144 @@ loop.store.ActiveRoomStore = (function() {
|
|||
|
||||
this._registerPostSetupActions();
|
||||
|
||||
this._getRoomDataForStandalone(actionData.cryptoKey);
|
||||
var dataPromise = this._getRoomDataForStandalone(actionData.cryptoKey);
|
||||
|
||||
var userAgentHandlesPromise = this._promiseDetectUserAgentHandles();
|
||||
|
||||
return Promise.all([dataPromise, userAgentHandlesPromise]).then(function(results) {
|
||||
results.forEach(function(result) {
|
||||
this.dispatcher.dispatch(result);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the room data for the standalone, decrypting it as necessary.
|
||||
*
|
||||
* @param {String} roomCryptoKey The crypto key associated to the room.
|
||||
* @return {Promise} A promise that is resolved once the get
|
||||
* and decryption is complete.
|
||||
*/
|
||||
_getRoomDataForStandalone: function(roomCryptoKey) {
|
||||
this._mozLoop.rooms.get(this._storeState.roomToken, function(err, result) {
|
||||
if (err) {
|
||||
this.dispatchAction(new sharedActions.RoomFailure({
|
||||
error: err,
|
||||
failedJoinRequest: false
|
||||
return new Promise(function(resolve, reject) {
|
||||
this._mozLoop.rooms.get(this._storeState.roomToken, function(err, result) {
|
||||
if (err) {
|
||||
resolve(new sharedActions.RoomFailure({
|
||||
error: err,
|
||||
failedJoinRequest: false
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
var roomInfoData = new sharedActions.UpdateRoomInfo({
|
||||
// If we've got this far, then we want to go to the ready state
|
||||
// regardless of success of failure. This is because failures of
|
||||
// crypto don't stop the user using the room, they just stop
|
||||
// us putting up the information.
|
||||
roomState: ROOM_STATES.READY,
|
||||
roomUrl: result.roomUrl
|
||||
});
|
||||
|
||||
if (!result.context && !result.roomName) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_DATA;
|
||||
resolve(roomInfoData);
|
||||
return;
|
||||
}
|
||||
|
||||
// This handles 'legacy', non-encrypted room names.
|
||||
if (result.roomName && !result.context) {
|
||||
roomInfoData.roomName = result.roomName;
|
||||
resolve(roomInfoData);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crypto.isSupported()) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED;
|
||||
resolve(roomInfoData);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!roomCryptoKey) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_CRYPTO_KEY;
|
||||
resolve(roomInfoData);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto.decryptBytes(roomCryptoKey, result.context.value)
|
||||
.then(function(decryptedResult) {
|
||||
var realResult = JSON.parse(decryptedResult);
|
||||
|
||||
roomInfoData.roomDescription = realResult.description;
|
||||
roomInfoData.roomContextUrls = realResult.urls;
|
||||
roomInfoData.roomName = realResult.roomName;
|
||||
|
||||
resolve(roomInfoData);
|
||||
}, function(error) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.DECRYPT_FAILED;
|
||||
resolve(roomInfoData);
|
||||
});
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* If the user agent is Firefox, it sends a message to Firefox to see if
|
||||
* the room can be handled within Firefox rather than the standalone UI.
|
||||
*
|
||||
* @return {Promise} A promise that is resolved once it has been determined
|
||||
* if Firefox can handle the room.
|
||||
*/
|
||||
_promiseDetectUserAgentHandles: function() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function resolveWithNotHandlingResponse() {
|
||||
resolve(new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
}
|
||||
|
||||
// If we're not Firefox, don't even try to see if it can be handled
|
||||
// in the browser.
|
||||
if (!loop.shared.utils.isFirefox(navigator.userAgent)) {
|
||||
resolveWithNotHandlingResponse();
|
||||
return;
|
||||
}
|
||||
|
||||
var roomInfoData = new sharedActions.UpdateRoomInfo({
|
||||
// If we've got this far, then we want to go to the ready state
|
||||
// regardless of success of failure. This is because failures of
|
||||
// crypto don't stop the user using the room, they just stop
|
||||
// us putting up the information.
|
||||
roomState: ROOM_STATES.READY,
|
||||
roomUrl: result.roomUrl
|
||||
});
|
||||
// Set up a timer in case older versions of Firefox don't give us a response.
|
||||
var timer = setTimeout(resolveWithNotHandlingResponse, 250);
|
||||
var webChannelListenerFunc;
|
||||
|
||||
if (!result.context && !result.roomName) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_DATA;
|
||||
this.dispatcher.dispatch(roomInfoData);
|
||||
return;
|
||||
// Listen for the result.
|
||||
function webChannelListener(e) {
|
||||
if (e.detail.id !== "loop-link-clicker") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop the default response.
|
||||
clearTimeout(timer);
|
||||
|
||||
// Remove the listener.
|
||||
window.removeEventListener("WebChannelMessageToContent", webChannelListenerFunc);
|
||||
|
||||
// Resolve with the details of if we're able to handle or not.
|
||||
resolve(new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: !!e.detail.message && e.detail.message.response
|
||||
}));
|
||||
}
|
||||
|
||||
// This handles 'legacy', non-encrypted room names.
|
||||
if (result.roomName && !result.context) {
|
||||
roomInfoData.roomName = result.roomName;
|
||||
this.dispatcher.dispatch(roomInfoData);
|
||||
return;
|
||||
}
|
||||
webChannelListenerFunc = webChannelListener.bind(this);
|
||||
|
||||
if (!crypto.isSupported()) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED;
|
||||
this.dispatcher.dispatch(roomInfoData);
|
||||
return;
|
||||
}
|
||||
window.addEventListener("WebChannelMessageToContent", webChannelListenerFunc);
|
||||
|
||||
if (!roomCryptoKey) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.NO_CRYPTO_KEY;
|
||||
this.dispatcher.dispatch(roomInfoData);
|
||||
return;
|
||||
}
|
||||
|
||||
var dispatcher = this.dispatcher;
|
||||
|
||||
crypto.decryptBytes(roomCryptoKey, result.context.value)
|
||||
.then(function(decryptedResult) {
|
||||
var realResult = JSON.parse(decryptedResult);
|
||||
|
||||
roomInfoData.roomDescription = realResult.description;
|
||||
roomInfoData.roomContextUrls = realResult.urls;
|
||||
roomInfoData.roomName = realResult.roomName;
|
||||
|
||||
dispatcher.dispatch(roomInfoData);
|
||||
}, function(error) {
|
||||
roomInfoData.roomInfoFailure = ROOM_INFO_FAILURES.DECRYPT_FAILED;
|
||||
dispatcher.dispatch(roomInfoData);
|
||||
});
|
||||
// Now send a message to the chrome to see if it can handle this room.
|
||||
window.dispatchEvent(new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
command: "checkWillOpenRoom",
|
||||
roomToken: this._storeState.roomToken
|
||||
}
|
||||
}
|
||||
}));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
@ -426,6 +509,18 @@ loop.store.ActiveRoomStore = (function() {
|
|||
this.setStoreState(newState);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the userAgentHandlesRoom action. Updates the store's data with
|
||||
* the new state.
|
||||
*
|
||||
* @param {sharedActions.userAgentHandlesRoom} actionData
|
||||
*/
|
||||
userAgentHandlesRoom: function(actionData) {
|
||||
this.setStoreState({
|
||||
userAgentHandlesRoom: actionData.handlesRoom
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the updateSocialShareInfo action. Updates the room data with new
|
||||
* Social API info.
|
||||
|
@ -477,14 +572,11 @@ loop.store.ActiveRoomStore = (function() {
|
|||
},
|
||||
|
||||
/**
|
||||
* Handles the action to join to a room.
|
||||
* Checks that there are audio and video devices available, and joins the
|
||||
* room if there are. If there aren't then it will dispatch a ConnectionFailure
|
||||
* action with NO_MEDIA.
|
||||
*/
|
||||
joinRoom: function() {
|
||||
// Reset the failure reason if necessary.
|
||||
if (this.getStoreState().failureReason) {
|
||||
this.setStoreState({failureReason: undefined});
|
||||
}
|
||||
|
||||
_checkDevicesAndJoinRoom: function() {
|
||||
// XXX Ideally we'd do this check before joining a room, but we're waiting
|
||||
// for the UX for that. See bug 1166824. In the meantime this gives us
|
||||
// additional information for analysis.
|
||||
|
@ -501,6 +593,77 @@ loop.store.ActiveRoomStore = (function() {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Hands off the room join to Firefox.
|
||||
*/
|
||||
_handoffRoomJoin: function() {
|
||||
var channelListener;
|
||||
|
||||
function handleRoomJoinResponse(e) {
|
||||
if (e.detail.id !== "loop-link-clicker") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.removeEventListener("WebChannelMessageToContent", channelListener);
|
||||
|
||||
if (!e.detail.message || !e.detail.message.response) {
|
||||
// XXX Firefox didn't handle this, even though it said it could
|
||||
// previously. We should add better user feedback here.
|
||||
console.error("Firefox didn't handle room it said it could.");
|
||||
} else {
|
||||
this.dispatcher.dispatch(new sharedActions.JoinedRoom({
|
||||
apiKey: "",
|
||||
sessionToken: "",
|
||||
sessionId: "",
|
||||
expires: 0
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
channelListener = handleRoomJoinResponse.bind(this);
|
||||
|
||||
window.addEventListener("WebChannelMessageToContent", channelListener);
|
||||
|
||||
// Now we're set up, dispatch an event.
|
||||
window.dispatchEvent(new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
command: "openRoom",
|
||||
roomToken: this._storeState.roomToken
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the action to join to a room.
|
||||
*/
|
||||
joinRoom: function() {
|
||||
// Reset the failure reason if necessary.
|
||||
if (this.getStoreState().failureReason) {
|
||||
this.setStoreState({ failureReason: undefined });
|
||||
}
|
||||
|
||||
// If we're standalone and we know Firefox can handle the room, then hand
|
||||
// it off.
|
||||
if (this._storeState.standalone && this._storeState.userAgentHandlesRoom) {
|
||||
this.dispatcher.dispatch(new sharedActions.MetricsLogJoinRoom({
|
||||
userAgentHandledRoom: true,
|
||||
ownRoom: true
|
||||
}));
|
||||
this._handoffRoomJoin();
|
||||
return;
|
||||
}
|
||||
|
||||
this.dispatcher.dispatch(new sharedActions.MetricsLogJoinRoom({
|
||||
userAgentHandledRoom: false
|
||||
}));
|
||||
|
||||
// Otherwise, we handle the room ourselves.
|
||||
this._checkDevicesAndJoinRoom();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the action that signifies when media permission has been
|
||||
* granted and starts joining the room.
|
||||
|
@ -540,6 +703,15 @@ loop.store.ActiveRoomStore = (function() {
|
|||
* @param {sharedActions.JoinedRoom} actionData
|
||||
*/
|
||||
joinedRoom: function(actionData) {
|
||||
// If we're standalone and firefox is handling, then just store the new
|
||||
// state. No need to do anything else.
|
||||
if (this._storeState.standalone && this._storeState.userAgentHandlesRoom) {
|
||||
this.setStoreState({
|
||||
roomState: ROOM_STATES.JOINED
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setStoreState({
|
||||
apiKey: actionData.apiKey,
|
||||
sessionToken: actionData.sessionToken,
|
||||
|
|
|
@ -25,6 +25,27 @@ body,
|
|||
background: #000;
|
||||
}
|
||||
|
||||
/* Logos */
|
||||
|
||||
.loop-logo-text {
|
||||
background: url("../img/hello-logo-text.svg") no-repeat;
|
||||
width: 200px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.loop-logo {
|
||||
background: url("../shared/img/helloicon.svg") no-repeat;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.mozilla-logo {
|
||||
background: url("../img/mozilla-logo.svg#logo") no-repeat;
|
||||
background-size: contain;
|
||||
width: 100px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.room-conversation-wrapper > .beta-logo {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
@ -43,7 +64,7 @@ body,
|
|||
margin: 0 auto;
|
||||
height: 30px;
|
||||
background-size: contain;
|
||||
background-image: url("../shared/img/mozilla-logo.png");
|
||||
background-image: url("../img/mozilla-logo.svg#logo-white");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
@ -138,6 +159,44 @@ html[dir="rtl"] .rooms-footer .footer-logo {
|
|||
line-height: 24px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle in Firefox views
|
||||
*/
|
||||
|
||||
.handle-user-agent-view-scroller {
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.handle-user-agent-view {
|
||||
margin: 2rem auto;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.handle-user-agent-view > .info-panel {
|
||||
padding-bottom: 40px;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.handle-user-agent-view > p,
|
||||
.handle-user-agent-view > .info-panel > p {
|
||||
margin-top: 0;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.handle-user-agent-view > .info-panel > button {
|
||||
width: 80%;
|
||||
height: 4rem;
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.handle-user-agent-view > .info-panel > button.disabled {
|
||||
background-color: #EBEBEB;
|
||||
border-color: #EBEBEB;
|
||||
color: #B2B0B3;
|
||||
}
|
||||
|
||||
/* Room wrapper layout */
|
||||
|
||||
.room-conversation-wrapper {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 467.5 76"><path fill="#5D5F64" d="M263.4 28.2c-.2.4-.5.8-.8 1.2-.3.3-.7.6-1.2.8-.5.2-.9.3-1.4.3-.5 0-1-.1-1.4-.3-.5-.2-.8-.4-1.2-.8-.3-.3-.6-.7-.8-1.2-.2-.4-.3-.9-.3-1.4 0-.5.1-1 .3-1.4.2-.4.4-.8.8-1.2.3-.3.7-.6 1.2-.8.4-.2.9-.3 1.4-.3.5 0 1 .1 1.4.3.4.2.8.4 1.2.8.3.3.6.7.8 1.2.2.5.3.9.3 1.4 0 .5-.1 1-.3 1.4zm-.7-2.6c-.2-.4-.4-.7-.6-1-.2-.3-.6-.5-.9-.7-.4-.2-.7-.2-1.1-.2-.4 0-.8.1-1.1.2-.4.2-.7.4-.9.7-.3.3-.5.6-.6 1-.2.4-.2.8-.2 1.2 0 .4.1.8.2 1.2.2.4.4.7.6 1 .3.3.6.5.9.7.3.2.7.2 1.1.2.4 0 .8-.1 1.1-.2.4-.2.7-.4.9-.7.3-.3.5-.6.6-1 .1-.4.2-.8.2-1.2.1-.4 0-.8-.2-1.2zm-2.2 2.6c-.1-.3-.3-.5-.4-.6-.1-.1-.2-.3-.3-.4l-.1-.1h-.2v1.8h-.7v-4.1h1.3c.2 0 .4 0 .6.1.2.1.3.1.4.2.1.1.2.2.2.4 0 .1.1.3.1.5 0 .3-.1.6-.3.8-.2.2-.4.3-.8.3l.1.1.2.2c.1.1.1.2.2.2.1.1.1.2.2.3l.6 1h-.8l-.3-.7zm0-2.8c-.1-.1-.3-.2-.6-.2h-.4v1.3h.8c.1 0 .2-.1.2-.1.1-.1.2-.3.2-.5s0-.3-.2-.5zM35.6 13.9h-24v19h19.5v9.4H11.6v32.1H0V4.3h37.1l-1.5 9.6zM41.7 8.2c0-4.1 3.2-7.5 7.4-7.5 3.9 0 7.3 3.2 7.3 7.5 0 4.1-3.3 7.4-7.5 7.4-4.1 0-7.2-3.4-7.2-7.4zm1.6 66.2V24l11.2-2v52.4H43.3zM89.2 32.9c-1.1-.4-1.9-.7-3.1-.7-4.7 0-8.6 3.4-9.6 7.6v34.6H65.3V38.3c0-6.5-.7-10.6-1.8-13.8l10.2-2.6c1.2 2.3 1.9 5.3 1.9 8.1 4-5.6 8.1-8.2 13.1-8.2 1.6 0 2.6.2 3.9.8l-3.4 10.3zM103.3 51.8v.8c0 7.1 2.6 14.6 12.7 14.6 4.8 0 8.9-1.7 12.7-5.1l4.4 6.8c-5.4 4.6-11.5 6.8-18.4 6.8-14.6 0-23.7-10.4-23.7-26.8 0-9 1.9-15 6.4-20 4.2-4.8 9.2-6.9 15.7-6.9 5.1 0 9.7 1.3 14.1 5.3 4.5 4 6.7 10.3 6.7 22.3v2.3h-30.6zm9.8-21.4c-6.3 0-9.7 5-9.7 13.3h18.9c0-8.4-3.6-13.3-9.2-13.3zM165.5 10c-2.5-1.2-4-1.8-6.2-1.8-3.8 0-6.3 2.6-6.3 7.2v7.8h13.4l-2.8 7.7h-10.4v43.5h-11V30.9h-4.8v-7.7h5s-.3-2.8-.3-7.6C142.1 5 148.5 0 157.6 0c4.4 0 8 .9 11.5 2.9l-3.6 7.1zM210.1 49c0 16.5-8.8 26.7-22.7 26.7-13.9 0-22.6-10.4-22.6-26.8S173.6 22 187.2 22c14.6 0 22.9 10.8 22.9 27zm-32.9-.8c0 14.9 3.7 19.2 10.4 19.2 6.6 0 10.2-5.4 10.2-18.2 0-14.5-4-18.8-10.5-18.8-7 0-10.1 5.3-10.1 17.8z"/><path fill="#5D5F64" d="M243.6 74.4c-1.8-2.9-10.1-17.3-11.1-19.1-1.9 3.8-9.2 16.3-11.1 19.1h-14.1l19-27.8-14.8-22 12-2.4c2.3 3.8 6.9 11.8 9.3 16.6 1.4-3.3 6.6-13.6 8.1-15.7h13l-15.1 23.3 18.7 27.9h-13.9z"/><g fill="#5D5F64"><path d="M280.6 4.5h8.2v29.3h29.5V4.5h8.4v70.1h-8.4V40.7h-29.5v33.9h-8.2V4.5zM371.5 64.3l3.1 5.1c-4.5 4.1-10.6 6.3-17.2 6.3-14.1 0-22.6-10.2-22.6-27.1 0-8.6 1.8-14.1 6.1-19.2 4.1-4.8 9.1-7.1 15.2-7.1 5.5 0 10.3 1.9 13.8 5.5 4.4 4.5 5.6 9.3 5.8 21.5v1.1H344v1.2c0 4.8.6 8.5 2.3 11.1 2.9 4.4 7.6 6.2 12.7 6.2 4.9.2 8.9-1.3 12.5-4.6zM344 44.5h23.3c-.1-5.5-.8-8.9-2.3-11.3-1.7-2.8-5.3-4.5-9.2-4.5-7.3-.1-11.4 5.2-11.8 15.8zM393.5 64.4c0 4 .6 5.1 2.9 5.1.3 0 1-.2 1-.2l1.6 5.2c-2 .9-3 1.1-5.1 1.1-2.5 0-4.5-.7-6-2.1-1.6-1.4-2.5-3.6-2.5-7.3v-54c0-6.6-1.2-10.4-1.2-10.4l8-1.5s1.3 4.3 1.3 12.1v52zM413.9 64.4c0 4 .6 5.1 2.9 5.1.3 0 1-.2 1-.2l1.6 5.2c-2 .9-3 1.1-5.1 1.1-2.5 0-4.5-.7-6-2.1-1.6-1.4-2.5-3.6-2.5-7.3v-54c0-6.6-1.2-10.4-1.2-10.4l8-1.5s1.3 4.3 1.3 12.1v52zM445.3 22.2c8.5 0 14 3.9 17.5 8.9 3.2 4.6 4.7 10.6 4.7 18.9 0 17-9.1 26-21.9 26-14 0-22-10.3-22-27.1 0-16.6 8.3-26.7 21.7-26.7zm-.1 6.5c-4.5 0-8.7 2.1-10.4 5.5-1.6 3.2-2.5 7.3-2.5 13.3 0 7.2 1.2 13.5 3.2 16.7 1.8 3.1 5.9 5.1 10.3 5.1 5.3 0 9.3-2.8 11-7.7 1.1-3.2 1.5-6 1.5-11 0-7.2-.7-12-2.4-15.3-2-4.5-6.5-6.6-10.7-6.6z"/></g></svg>
|
После Ширина: | Высота: | Размер: 3.2 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="568" height="148" viewBox="0 0 568 148" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Fill 1 Copy</title><style>use:not(:target) { display: none; } use { fill: #383838; } use[id$="-white"] { fill: #fff; }</style><defs><path id="mozilla-logo" d="M23.39 42.294c1.72 2.656 2.478 5.026 3.44 10.024 6.728-6.568 15.025-10.024 24.08-10.024 8.18 0 14.89 2.656 20.085 8.077 1.4 1.36 2.75 3.113 3.913 4.833 9.038-9.257 17.132-12.91 27.976-12.91 7.722 0 15.042 2.31 19.51 6.156 5.583 4.823 7.353 10.622 7.353 24.124v70.244h-25.092V77.606c0-11.82-1.4-14.107-8.13-14.107-4.822 0-11.6 3.29-17.166 8.305v71.013H54.872V78.533c0-12.326-1.787-15.22-8.97-15.22-4.773 0-11.384 2.472-16.95 7.514v71.99H3.694V73.913c0-14.266-.978-20.43-3.693-25.277l23.39-6.34zm152.244 28.92c-1.772 5.228-2.715 12.168-2.715 22.016 0 11.357 1.162 19.89 3.27 24.89 2.327 5.406 8.146 8.104 13.12 8.104 11.197 0 15.986-10.025 15.986-33.372 0-13.324-1.737-22.025-5.193-26.476-2.48-3.255-6.51-5.194-11.164-5.194-6.19 0-11.216 3.844-13.306 10.032zm46.49-14.265c7.893 9.257 11.418 20.057 11.418 36.07 0 16.982-3.895 28.582-12.412 38.212-7.486 8.483-17.352 13.71-32.563 13.71-26.863 0-44.384-20.076-44.384-51.13 0-31.08 17.706-51.738 44.384-51.738 14.08 0 25.077 4.84 33.558 14.875zm94.588-12.935V61.77l-43.64 63.096h45.344l-6.19 17.952h-72.713v-16.012l46.46-64.645H243.39V44.016h73.322zm40.694-2.328v101.13h-25.853V45.75l25.853-4.063zm3.035-24.874c0 8.89-7.066 15.987-16.002 15.987-8.652 0-15.767-7.098-15.767-15.987 0-8.87 7.353-16.03 16.204-16.03 8.67 0 15.567 7.16 15.567 16.03zm44.048 8.89v76.98c0 17.006.203 19.292 1.755 21.99.977 1.753 3.068 2.698 5.227 2.698.927 0 1.483 0 2.883-.354l4.42 15.42c-4.42 1.73-9.832 2.693-15.43 2.693-11.03 0-19.9-5.197-22.97-13.477-1.94-5.024-2.36-8.127-2.36-22.208V35.7c0-12.918-.337-20.81-1.3-29.722L403.157 0c.926 5.397 1.33 11.77 1.33 25.702zm53.625 0v76.98c0 17.006.22 19.292 1.806 21.99.91 1.753 3 2.698 5.16 2.698.977 0 1.567 0 2.933-.354l4.402 15.42c-4.402 1.73-9.816 2.693-15.432 2.693-11.01 0-19.897-5.197-22.983-13.477-1.973-5.024-2.294-8.127-2.294-22.208V35.7c0-12.918-.387-20.81-1.383-29.722L456.73 0c1.064 5.397 1.383 11.77 1.383 25.702zm74.082 73.894c-17.875 0-24.148 3.254-24.148 15.076 0 7.688 4.89 12.9 11.45 12.9 4.806 0 9.664-2.513 13.492-6.746l.42-21.23h-1.215zM498.687 47.69c9.613-4.064 17.878-5.785 26.983-5.785 16.628 0 27.993 6.157 31.888 17.167 1.282 4.05 1.872 7.135 1.755 17.757L558.687 110v1.752c0 10.607 1.755 14.672 9.313 20.255l-13.73 15.85c-6.038-2.53-11.416-6.98-13.93-11.982-1.905 1.948-4.047 3.837-6.003 5.202-4.79 3.476-11.787 5.414-19.883 5.414-22.005 0-33.96-11.215-33.96-30.86 0-23.196 16.053-34.015 47.485-34.015 1.888 0 3.676 0 5.818.22v-4.03c0-11.02-2.142-14.69-11.653-14.69-8.196 0-17.926 4.03-28.517 11.19l-11.012-18.533c5.245-3.29 9.108-5.203 16.07-8.087z"/></defs><use id="logo" xlink:href="#mozilla-logo"/><use id="logo-white" xlink:href="#mozilla-logo"/></svg>
|
После Ширина: | Высота: | Размер: 2.9 KiB |
|
@ -44,7 +44,7 @@ loop.store.StandaloneMetricsStore = (function() {
|
|||
"connectedToSdkServers",
|
||||
"connectionFailure",
|
||||
"gotMediaPermission",
|
||||
"joinRoom",
|
||||
"metricsLogJoinRoom",
|
||||
"joinedRoom",
|
||||
"leaveRoom",
|
||||
"mediaConnected",
|
||||
|
@ -144,10 +144,20 @@ loop.store.StandaloneMetricsStore = (function() {
|
|||
|
||||
/**
|
||||
* Handles the user clicking the join room button.
|
||||
*
|
||||
* @param {sharedActions.MetricsLogJoinRoom} actionData
|
||||
*/
|
||||
joinRoom: function() {
|
||||
this._storeEvent(METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Join the conversation");
|
||||
metricsLogJoinRoom: function(actionData) {
|
||||
var label;
|
||||
|
||||
if (actionData.userAgentHandledRoom) {
|
||||
label = actionData.ownRoom ? "Joined own room in Firefox" :
|
||||
"Joined in Firefox";
|
||||
} else {
|
||||
label = "Join the conversation";
|
||||
}
|
||||
|
||||
this._storeEvent(METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button, label);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,6 +58,59 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
var StandaloneHandleUserAgentView = React.createClass({displayName: "StandaloneHandleUserAgentView",
|
||||
mixins: [
|
||||
loop.store.StoreMixin("activeRoomStore")
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
handleJoinButton: function() {
|
||||
this.props.dispatcher.dispatch(new sharedActions.JoinRoom());
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var buttonMessage = this.state.roomState === ROOM_STATES.JOINED ?
|
||||
mozL10n.get("rooms_room_joined_own_conversation_label") :
|
||||
mozL10n.get("rooms_room_join_label");
|
||||
|
||||
var buttonClasses = React.addons.classSet({
|
||||
btn: true,
|
||||
"btn-info": true,
|
||||
disabled: this.state.roomState === ROOM_STATES.JOINED
|
||||
});
|
||||
|
||||
// The extra scroller div here is for providing a scroll view for shorter
|
||||
// screens, as the common.css specifies overflow:hidden for the body which
|
||||
// we need in some places.
|
||||
return (
|
||||
React.createElement("div", {className: "handle-user-agent-view-scroller"},
|
||||
React.createElement("div", {className: "handle-user-agent-view"},
|
||||
React.createElement("div", {className: "info-panel"},
|
||||
React.createElement("p", {className: "loop-logo-text", title: mozL10n.get("clientShortname2") }),
|
||||
React.createElement("p", {className: "roomName"}, this.state.roomName),
|
||||
React.createElement("p", {className: "loop-logo"}),
|
||||
React.createElement("button", {
|
||||
className: buttonClasses,
|
||||
onClick: this.handleJoinButton},
|
||||
buttonMessage
|
||||
)
|
||||
),
|
||||
React.createElement(ToSView, {
|
||||
dispatcher: this.props.dispatcher}),
|
||||
React.createElement("p", {className: "mozilla-logo"})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles display of failures, determining the correct messages and
|
||||
* displaying the retry button at appropriate times.
|
||||
|
@ -611,7 +664,45 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
var StandaloneRoomControllerView = React.createClass({displayName: "StandaloneRoomControllerView",
|
||||
mixins: [
|
||||
loop.store.StoreMixin("activeRoomStore")
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
isFirefox: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// If we don't know yet, don't display anything.
|
||||
if (this.state.firefoxHandlesRoom === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.firefoxHandlesRoom) {
|
||||
return (
|
||||
React.createElement(StandaloneHandleUserAgentView, {
|
||||
dispatcher: this.props.dispatcher})
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
React.createElement(StandaloneRoomView, {
|
||||
activeRoomStore: this.getStore(),
|
||||
dispatcher: this.props.dispatcher,
|
||||
isFirefox: this.props.isFirefox})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
StandaloneHandleUserAgentView: StandaloneHandleUserAgentView,
|
||||
StandaloneRoomControllerView: StandaloneRoomControllerView,
|
||||
StandaloneRoomFailureView: StandaloneRoomFailureView,
|
||||
StandaloneRoomFooter: StandaloneRoomFooter,
|
||||
StandaloneRoomHeader: StandaloneRoomHeader,
|
||||
|
|
|
@ -58,6 +58,59 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
var StandaloneHandleUserAgentView = React.createClass({
|
||||
mixins: [
|
||||
loop.store.StoreMixin("activeRoomStore")
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
handleJoinButton: function() {
|
||||
this.props.dispatcher.dispatch(new sharedActions.JoinRoom());
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var buttonMessage = this.state.roomState === ROOM_STATES.JOINED ?
|
||||
mozL10n.get("rooms_room_joined_own_conversation_label") :
|
||||
mozL10n.get("rooms_room_join_label");
|
||||
|
||||
var buttonClasses = React.addons.classSet({
|
||||
btn: true,
|
||||
"btn-info": true,
|
||||
disabled: this.state.roomState === ROOM_STATES.JOINED
|
||||
});
|
||||
|
||||
// The extra scroller div here is for providing a scroll view for shorter
|
||||
// screens, as the common.css specifies overflow:hidden for the body which
|
||||
// we need in some places.
|
||||
return (
|
||||
<div className="handle-user-agent-view-scroller">
|
||||
<div className="handle-user-agent-view">
|
||||
<div className="info-panel">
|
||||
<p className="loop-logo-text" title={ mozL10n.get("clientShortname2") }></p>
|
||||
<p className="roomName">{ this.state.roomName }</p>
|
||||
<p className="loop-logo" />
|
||||
<button
|
||||
className={buttonClasses}
|
||||
onClick={this.handleJoinButton}>
|
||||
{buttonMessage}
|
||||
</button>
|
||||
</div>
|
||||
<ToSView
|
||||
dispatcher={this.props.dispatcher} />
|
||||
<p className="mozilla-logo" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles display of failures, determining the correct messages and
|
||||
* displaying the retry button at appropriate times.
|
||||
|
@ -611,7 +664,45 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
var StandaloneRoomControllerView = React.createClass({
|
||||
mixins: [
|
||||
loop.store.StoreMixin("activeRoomStore")
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
isFirefox: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// If we don't know yet, don't display anything.
|
||||
if (this.state.firefoxHandlesRoom === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.firefoxHandlesRoom) {
|
||||
return (
|
||||
<StandaloneHandleUserAgentView
|
||||
dispatcher={this.props.dispatcher} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StandaloneRoomView
|
||||
activeRoomStore={this.getStore()}
|
||||
dispatcher={this.props.dispatcher}
|
||||
isFirefox={this.props.isFirefox} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
StandaloneHandleUserAgentView: StandaloneHandleUserAgentView,
|
||||
StandaloneRoomControllerView: StandaloneRoomControllerView,
|
||||
StandaloneRoomFailureView: StandaloneRoomFailureView,
|
||||
StandaloneRoomFooter: StandaloneRoomFooter,
|
||||
StandaloneRoomHeader: StandaloneRoomHeader,
|
||||
|
|
|
@ -153,7 +153,7 @@ loop.webapp = (function(_, OT, mozL10n) {
|
|||
}
|
||||
case "room": {
|
||||
return (
|
||||
React.createElement(loop.standaloneRoomViews.StandaloneRoomView, {
|
||||
React.createElement(loop.standaloneRoomViews.StandaloneRoomControllerView, {
|
||||
activeRoomStore: this.props.activeRoomStore,
|
||||
dispatcher: this.props.dispatcher,
|
||||
isFirefox: this.state.isFirefox})
|
||||
|
|
|
@ -153,7 +153,7 @@ loop.webapp = (function(_, OT, mozL10n) {
|
|||
}
|
||||
case "room": {
|
||||
return (
|
||||
<loop.standaloneRoomViews.StandaloneRoomView
|
||||
<loop.standaloneRoomViews.StandaloneRoomControllerView
|
||||
activeRoomStore={this.props.activeRoomStore}
|
||||
dispatcher={this.props.dispatcher}
|
||||
isFirefox={this.state.isFirefox} />
|
||||
|
|
|
@ -68,6 +68,7 @@ rooms_room_full_call_to_action_nonFx_label=Download {{brandShortname}} to start
|
|||
rooms_room_full_call_to_action_label=Learn more about {{clientShortname}} »
|
||||
rooms_room_joined_label=Someone has joined the conversation!
|
||||
rooms_room_join_label=Join the conversation
|
||||
rooms_room_joined_own_conversation_label=Enjoy your conversation
|
||||
rooms_display_name_guest=Guest
|
||||
rooms_unavailable_notification_message=Sorry, you cannot join this conversation. The link may be expired or invalid.
|
||||
rooms_media_denied_message=We could not get access to your microphone or camera. Please reload the page to try again.
|
||||
|
|
|
@ -6,6 +6,7 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
|
||||
var expect = chai.expect;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var REST_ERRNOS = loop.shared.utils.REST_ERRNOS;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
|
||||
|
@ -434,20 +435,20 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
sinon.assert.calledOnce(fakeMozLoop.rooms.get);
|
||||
});
|
||||
|
||||
it("should dispatch an UpdateRoomInfo message with 'no data' failure if neither roomName nor context are supplied", function() {
|
||||
it("should dispatch an UpdateRoomInfo message with failure if neither roomName nor context are supplied", function() {
|
||||
fakeMozLoop.rooms.get.callsArgWith(1, null, {
|
||||
roomUrl: "http://invalid"
|
||||
});
|
||||
|
||||
store.fetchServerData(fetchServerAction);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.NO_DATA,
|
||||
roomState: ROOM_STATES.READY,
|
||||
roomUrl: "http://invalid"
|
||||
}));
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.NO_DATA,
|
||||
roomState: ROOM_STATES.READY,
|
||||
roomUrl: "http://invalid"
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe("mozLoop.rooms.get returns roomName as a separate field (no context)", function() {
|
||||
|
@ -459,13 +460,13 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
|
||||
fakeMozLoop.rooms.get.callsArgWith(1, null, roomDetails);
|
||||
|
||||
store.fetchServerData(fetchServerAction);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomState: ROOM_STATES.READY
|
||||
}, roomDetails)));
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomState: ROOM_STATES.READY
|
||||
}, roomDetails)));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -491,25 +492,25 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
it("should dispatch UpdateRoomInfo message with 'unsupported' failure if WebCrypto is unsupported", function() {
|
||||
loop.crypto.isSupported.returns(false);
|
||||
|
||||
store.fetchServerData(fetchServerAction);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.WEB_CRYPTO_UNSUPPORTED,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch UpdateRoomInfo message with 'no crypto key' failure if there is no crypto key", function() {
|
||||
store.fetchServerData(fetchServerAction);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.NO_CRYPTO_KEY,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.NO_CRYPTO_KEY,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch UpdateRoomInfo message with 'decrypt failed' failure if decryption failed", function() {
|
||||
|
@ -525,14 +526,14 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
};
|
||||
});
|
||||
|
||||
store.fetchServerData(fetchServerAction);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.DECRYPT_FAILED,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomInfoFailure: ROOM_INFO_FAILURES.DECRYPT_FAILED,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails)));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch UpdateRoomInfo message with the context if decryption was successful", function() {
|
||||
|
@ -558,18 +559,175 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
};
|
||||
});
|
||||
|
||||
store.fetchServerData(fetchServerAction);
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
var expectedData = _.extend({
|
||||
roomContextUrls: roomContext.urls,
|
||||
roomDescription: roomContext.description,
|
||||
roomName: roomContext.roomName,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails);
|
||||
|
||||
var expectedData = _.extend({
|
||||
roomContextUrls: roomContext.urls,
|
||||
roomDescription: roomContext.description,
|
||||
roomName: roomContext.roomName,
|
||||
roomState: ROOM_STATES.READY
|
||||
}, expectedDetails);
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(expectedData));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(expectedData));
|
||||
describe("User Agent Room Handling", function() {
|
||||
var channelListener, roomDetails;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox.stub(sharedUtils, "isFirefox").returns(true);
|
||||
|
||||
roomDetails = {
|
||||
roomName: "fakeName",
|
||||
roomUrl: "http://invalid"
|
||||
};
|
||||
fakeMozLoop.rooms.get.callsArgWith(1, null, roomDetails);
|
||||
|
||||
sandbox.stub(window, "addEventListener", function(eventName, listener) {
|
||||
if (eventName === "WebChannelMessageToContent") {
|
||||
channelListener = listener;
|
||||
}
|
||||
});
|
||||
sandbox.stub(window, "removeEventListener", function(eventName, listener) {
|
||||
if (eventName === "WebChannelMessageToContent" &&
|
||||
listener === channelListener) {
|
||||
channelListener = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch UserAgentHandlesRoom with false if the user agent is not Firefox", function() {
|
||||
sharedUtils.isFirefox.returns(false);
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch with false after a timeout if there is no response from the channel", function() {
|
||||
// When the dispatchEvent is called, we know the setup code has run, so
|
||||
// advance the timer.
|
||||
sandbox.stub(window, "dispatchEvent", function() {
|
||||
sandbox.clock.tick(250);
|
||||
});
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should not dispatch if a message is returned not for the link-clicker", function() {
|
||||
// When the dispatchEvent is called, we know the setup code has run, so
|
||||
// advance the timer.
|
||||
sandbox.stub(window, "dispatchEvent", function() {
|
||||
// We call the listener twice, but the first time with an invalid id.
|
||||
// Hence we should only get the dispatch once.
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "invalid-id",
|
||||
message: null
|
||||
}
|
||||
});
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: null
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
// Although this is only called once for the UserAgentHandlesRoom,
|
||||
// it gets called twice due to the UpdateRoomInfo. Therefore,
|
||||
// we test both results here.
|
||||
sinon.assert.calledTwice(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UpdateRoomInfo(_.extend({
|
||||
roomState: ROOM_STATES.READY
|
||||
}, roomDetails)));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch with false if the user agent does not understand the message", function() {
|
||||
// When the dispatchEvent is called, we know the setup code has run, so
|
||||
// advance the timer.
|
||||
sandbox.stub(window, "dispatchEvent", function() {
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: null
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch with false if the user agent cannot handle the message", function() {
|
||||
// When the dispatchEvent is called, we know the setup code has run, so
|
||||
// advance the timer.
|
||||
sandbox.stub(window, "dispatchEvent", function() {
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
response: false
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: false
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should dispatch with true if the user agent can handle the message", function() {
|
||||
// When the dispatchEvent is called, we know the setup code has run, so
|
||||
// advance the timer.
|
||||
sandbox.stub(window, "dispatchEvent", function() {
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
response: true
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return store.fetchServerData(fetchServerAction).then(function() {
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: true
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -624,6 +782,20 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe("#userAgentHandlesRoom", function() {
|
||||
it("should update the store state", function() {
|
||||
store.setStoreState({
|
||||
UserAgentHandlesRoom: false
|
||||
});
|
||||
|
||||
store.userAgentHandlesRoom(new sharedActions.UserAgentHandlesRoom({
|
||||
handlesRoom: true
|
||||
}));
|
||||
|
||||
expect(store.getStoreState().userAgentHandlesRoom).eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#updateSocialShareInfo", function() {
|
||||
var fakeSocialShareInfo;
|
||||
|
||||
|
@ -659,32 +831,138 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
expect(store.getStoreState().failureReason).eql(undefined);
|
||||
});
|
||||
|
||||
it("should set the state to MEDIA_WAIT if media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, true);
|
||||
describe("Standalone Handles Room", function() {
|
||||
it("should dispatch a MetricsLogJoinRoom action", function() {
|
||||
store.joinRoom();
|
||||
|
||||
store.joinRoom();
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MetricsLogJoinRoom({
|
||||
userAgentHandledRoom: false
|
||||
}));
|
||||
});
|
||||
|
||||
expect(store.getStoreState().roomState).eql(ROOM_STATES.MEDIA_WAIT);
|
||||
it("should set the state to MEDIA_WAIT if media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, true);
|
||||
|
||||
store.joinRoom();
|
||||
|
||||
expect(store.getStoreState().roomState).eql(ROOM_STATES.MEDIA_WAIT);
|
||||
});
|
||||
|
||||
it("should not set the state to MEDIA_WAIT if no media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, false);
|
||||
|
||||
store.joinRoom();
|
||||
|
||||
expect(store.getStoreState().roomState).eql(ROOM_STATES.READY);
|
||||
});
|
||||
|
||||
it("should dispatch `ConnectionFailure` if no media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, false);
|
||||
|
||||
store.joinRoom();
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ConnectionFailure({
|
||||
reason: FAILURE_DETAILS.NO_MEDIA
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should not set the state to MEDIA_WAIT if no media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, false);
|
||||
describe("Firefox Handles Room", function() {
|
||||
var channelListener;
|
||||
|
||||
store.joinRoom();
|
||||
beforeEach(function() {
|
||||
store.setStoreState({
|
||||
userAgentHandlesRoom: true,
|
||||
roomToken: "fakeToken",
|
||||
standalone: true
|
||||
});
|
||||
|
||||
expect(store.getStoreState().roomState).eql(ROOM_STATES.READY);
|
||||
});
|
||||
sandbox.stub(window, "addEventListener", function(eventName, listener) {
|
||||
if (eventName === "WebChannelMessageToContent") {
|
||||
channelListener = listener;
|
||||
}
|
||||
});
|
||||
sandbox.stub(window, "removeEventListener", function(eventName, listener) {
|
||||
if (eventName === "WebChannelMessageToContent" &&
|
||||
listener === channelListener) {
|
||||
channelListener = null;
|
||||
}
|
||||
});
|
||||
|
||||
it("should dispatch `ConnectionFailure` if no media devices are present", function() {
|
||||
sandbox.stub(loop.shared.utils, "hasAudioOrVideoDevices").callsArgWith(0, false);
|
||||
sandbox.stub(console, "error");
|
||||
});
|
||||
|
||||
store.joinRoom();
|
||||
it("should dispatch a MetricsLogJoinRoom action", function() {
|
||||
store.joinRoom();
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ConnectionFailure({
|
||||
reason: FAILURE_DETAILS.NO_MEDIA
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MetricsLogJoinRoom({
|
||||
userAgentHandledRoom: true,
|
||||
ownRoom: true
|
||||
}));
|
||||
});
|
||||
|
||||
it("should dispatch an event to Firefox", function() {
|
||||
sandbox.stub(window, "dispatchEvent");
|
||||
|
||||
store.joinRoom();
|
||||
|
||||
sinon.assert.calledOnce(window.dispatchEvent);
|
||||
sinon.assert.calledWithExactly(window.dispatchEvent, new window.CustomEvent(
|
||||
"WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
command: "openRoom",
|
||||
roomToken: "fakeToken"
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("should log an error if Firefox doesn't handle the room", function() {
|
||||
// Start the join.
|
||||
store.joinRoom();
|
||||
|
||||
// Pretend Firefox calls back.
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: null
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(console.error);
|
||||
});
|
||||
|
||||
it("should dispatch a JoinedRoom action if the room was successfully opened", function() {
|
||||
// Start the join.
|
||||
store.joinRoom();
|
||||
|
||||
// Pretend Firefox calls back.
|
||||
channelListener({
|
||||
detail: {
|
||||
id: "loop-link-clicker",
|
||||
message: {
|
||||
response: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.JoinedRoom({
|
||||
apiKey: "",
|
||||
sessionToken: "",
|
||||
sessionId: "",
|
||||
expires: 0
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -762,6 +1040,17 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
expect(store._storeState.roomState).eql(ROOM_STATES.JOINED);
|
||||
});
|
||||
|
||||
it("should set the state to `JOINED` when Firefox handles the room", function() {
|
||||
store.setStoreState({
|
||||
userAgentHandlesRoom: true,
|
||||
standalone: true
|
||||
});
|
||||
|
||||
store.joinedRoom(new sharedActions.JoinedRoom(fakeJoinedData));
|
||||
|
||||
expect(store._storeState.roomState).eql(ROOM_STATES.JOINED);
|
||||
});
|
||||
|
||||
it("should store the session and api values", function() {
|
||||
store.joinedRoom(new sharedActions.JoinedRoom(fakeJoinedData));
|
||||
|
||||
|
@ -771,6 +1060,20 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
expect(state.sessionId).eql(fakeJoinedData.sessionId);
|
||||
});
|
||||
|
||||
it("should not store the session and api values when Firefox handles the room", function() {
|
||||
store.setStoreState({
|
||||
userAgentHandlesRoom: true,
|
||||
standalone: true
|
||||
});
|
||||
|
||||
store.joinedRoom(new sharedActions.JoinedRoom(fakeJoinedData));
|
||||
|
||||
var state = store.getStoreState();
|
||||
expect(state.apiKey).eql(undefined);
|
||||
expect(state.sessionToken).eql(undefined);
|
||||
expect(state.sessionId).eql(undefined);
|
||||
});
|
||||
|
||||
it("should start the session connection with the sdk", function() {
|
||||
var actionData = new sharedActions.JoinedRoom(fakeJoinedData);
|
||||
|
||||
|
|
|
@ -86,15 +86,6 @@ describe("loop.store.StandaloneMetricsStore", function() {
|
|||
"Media granted");
|
||||
});
|
||||
|
||||
it("should log an event on JoinRoom", function() {
|
||||
store.joinRoom();
|
||||
|
||||
sinon.assert.calledOnce(window.ga);
|
||||
sinon.assert.calledWithExactly(window.ga,
|
||||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Join the conversation");
|
||||
});
|
||||
|
||||
it("should log an event on JoinedRoom", function() {
|
||||
store.joinedRoom();
|
||||
|
||||
|
@ -150,6 +141,43 @@ describe("loop.store.StandaloneMetricsStore", function() {
|
|||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Retry failed room");
|
||||
});
|
||||
|
||||
describe("MetricsLogJoinRoom", function() {
|
||||
it("should log a 'Join the conversation' event if not joined by Firefox", function() {
|
||||
store.metricsLogJoinRoom({
|
||||
userAgentHandledRoom: false
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(window.ga);
|
||||
sinon.assert.calledWithExactly(window.ga,
|
||||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Join the conversation");
|
||||
});
|
||||
|
||||
it("should log a 'Joined own room in Firefox' event if joining the own room in Firefox", function() {
|
||||
store.metricsLogJoinRoom({
|
||||
userAgentHandledRoom: true,
|
||||
ownRoom: true
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(window.ga);
|
||||
sinon.assert.calledWithExactly(window.ga,
|
||||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Joined own room in Firefox");
|
||||
});
|
||||
|
||||
it("should log a 'Joined in Firefox' event if joining a non-own room in Firefox", function() {
|
||||
store.metricsLogJoinRoom({
|
||||
userAgentHandledRoom: true,
|
||||
ownRoom: false
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(window.ga);
|
||||
sinon.assert.calledWithExactly(window.ga,
|
||||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.button,
|
||||
"Joined in Firefox");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Store Change Handlers", function() {
|
||||
|
|
|
@ -128,6 +128,63 @@ describe("loop.standaloneRoomViews", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("StandaloneHandleUserAgentView", function() {
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(
|
||||
loop.standaloneRoomViews.StandaloneHandleUserAgentView, {
|
||||
dispatcher: dispatcher
|
||||
}));
|
||||
}
|
||||
|
||||
it("should display a join room button if the state is not ROOM_JOINED", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
roomState: ROOM_STATES.READY
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
var button = view.getDOMNode().querySelector(".info-panel > button");
|
||||
|
||||
expect(button.textContent).eql("rooms_room_join_label");
|
||||
});
|
||||
|
||||
it("should dispatch a JoinRoom action when the join room button is clicked", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
roomState: ROOM_STATES.READY
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
var button = view.getDOMNode().querySelector(".info-panel > button");
|
||||
|
||||
TestUtils.Simulate.click(button);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch, new sharedActions.JoinRoom());
|
||||
});
|
||||
|
||||
it("should display a enjoy your conversation button if the state is ROOM_JOINED", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
roomState: ROOM_STATES.JOINED
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
var button = view.getDOMNode().querySelector(".info-panel > button");
|
||||
|
||||
expect(button.textContent).eql("rooms_room_joined_own_conversation_label");
|
||||
});
|
||||
|
||||
it("should disable the enjoy your conversation button if the state is ROOM_JOINED", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
roomState: ROOM_STATES.JOINED
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
var button = view.getDOMNode().querySelector(".info-panel > button");
|
||||
|
||||
expect(button.classList.contains("disabled")).eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("StandaloneRoomHeader", function() {
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
|
@ -866,4 +923,47 @@ describe("loop.standaloneRoomViews", function() {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("StandaloneRoomControllerView", function() {
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(
|
||||
loop.standaloneRoomViews.StandaloneRoomControllerView, {
|
||||
dispatcher: dispatcher,
|
||||
isFirefox: true
|
||||
}));
|
||||
}
|
||||
|
||||
it("should not display anything if it is not known if Firefox can handle the room", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
firefoxHandlesRoom: undefined
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
expect(view.getDOMNode()).eql(null);
|
||||
});
|
||||
|
||||
it("should render StandaloneHandleUserAgentView if Firefox can handle the room", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
firefoxHandlesRoom: true
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(view,
|
||||
loop.standaloneRoomViews.StandaloneHandleUserAgentView);
|
||||
});
|
||||
|
||||
it("should render StandaloneRoomView if Firefox cannot handle the room", function() {
|
||||
activeRoomStore.setStoreState({
|
||||
firefoxHandlesRoom: false
|
||||
});
|
||||
|
||||
view = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(view,
|
||||
loop.standaloneRoomViews.StandaloneRoomView);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -119,14 +119,14 @@ describe("loop.webapp", function() {
|
|||
loop.webapp.UnsupportedBrowserView);
|
||||
});
|
||||
|
||||
it("should display the StandaloneRoomView for `room` window type",
|
||||
it("should display the StandaloneRoomControllerView for `room` window type",
|
||||
function() {
|
||||
standaloneAppStore.setStoreState({windowType: "room", isFirefox: true});
|
||||
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(webappRootView,
|
||||
loop.standaloneRoomViews.StandaloneRoomView);
|
||||
loop.standaloneRoomViews.StandaloneRoomControllerView);
|
||||
});
|
||||
|
||||
it("should display the HomeView for `home` window type", function() {
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
var UnsupportedBrowserView = loop.webapp.UnsupportedBrowserView;
|
||||
var UnsupportedDeviceView = loop.webapp.UnsupportedDeviceView;
|
||||
var StandaloneRoomView = loop.standaloneRoomViews.StandaloneRoomView;
|
||||
var StandaloneHandleUserAgentView = loop.standaloneRoomViews.StandaloneHandleUserAgentView;
|
||||
|
||||
// 3. Shared components
|
||||
var ConversationToolbar = loop.shared.views.ConversationToolbar;
|
||||
|
@ -1515,6 +1516,21 @@
|
|||
)
|
||||
),
|
||||
|
||||
React.createElement(Section, {name: "StandaloneHandleUserAgentView"},
|
||||
React.createElement(FramedExample, {
|
||||
cssClass: "standalone",
|
||||
dashed: true,
|
||||
height: 483,
|
||||
summary: "Standalone Room Handle Join in Firefox",
|
||||
width: 644},
|
||||
React.createElement("div", {className: "standalone"},
|
||||
React.createElement(StandaloneHandleUserAgentView, {
|
||||
activeRoomStore: readyRoomStore,
|
||||
dispatcher: dispatcher})
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(Section, {name: "StandaloneRoomView"},
|
||||
React.createElement(FramedExample, {cssClass: "standalone",
|
||||
dashed: true,
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
var UnsupportedBrowserView = loop.webapp.UnsupportedBrowserView;
|
||||
var UnsupportedDeviceView = loop.webapp.UnsupportedDeviceView;
|
||||
var StandaloneRoomView = loop.standaloneRoomViews.StandaloneRoomView;
|
||||
var StandaloneHandleUserAgentView = loop.standaloneRoomViews.StandaloneHandleUserAgentView;
|
||||
|
||||
// 3. Shared components
|
||||
var ConversationToolbar = loop.shared.views.ConversationToolbar;
|
||||
|
@ -1515,6 +1516,21 @@
|
|||
</FramedExample>
|
||||
</Section>
|
||||
|
||||
<Section name="StandaloneHandleUserAgentView">
|
||||
<FramedExample
|
||||
cssClass="standalone"
|
||||
dashed={true}
|
||||
height={483}
|
||||
summary="Standalone Room Handle Join in Firefox"
|
||||
width={644} >
|
||||
<div className="standalone">
|
||||
<StandaloneHandleUserAgentView
|
||||
activeRoomStore={readyRoomStore}
|
||||
dispatcher={dispatcher} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
</Section>
|
||||
|
||||
<Section name="StandaloneRoomView">
|
||||
<FramedExample cssClass="standalone"
|
||||
dashed={true}
|
||||
|
|
Загрузка…
Ссылка в новой задаче