author | Nicolas Perriault <nperriault@mozilla.com> |
Thu, 22 Jan 2015 17:39:07 +0100 | |
changeset 225265 | ef61f646f36107432d5087395d1de3a08630ac15 |
parent 225264 | 609564eb346d35864c46a6d68b3086ca47609266 |
child 225266 | 9145bbf29f05df54135a52e932a04bc556be059a |
push id | 28158 |
push user | ryanvm@gmail.com |
push date | Fri, 23 Jan 2015 17:20:14 +0000 |
treeherder | mozilla-central@a1348d5a02b2 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Standard8 |
bugs | 1106852 |
milestone | 38.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/loop/content/js/conversation.js +++ b/browser/components/loop/content/js/conversation.js @@ -37,19 +37,17 @@ loop.conversation = (function(mozL10n) { sdk: React.PropTypes.object.isRequired, // XXX New types for flux style conversationAppStore: React.PropTypes.instanceOf( loop.store.ConversationAppStore).isRequired, conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore) .isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - roomStore: React.PropTypes.instanceOf(loop.store.RoomStore), - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + roomStore: React.PropTypes.instanceOf(loop.store.RoomStore) }, getInitialState: function() { return this.props.conversationAppStore.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.conversationAppStore, "change", function() { @@ -63,32 +61,29 @@ loop.conversation = (function(mozL10n) { render: function() { switch(this.state.windowType) { case "incoming": { return (React.createElement(IncomingConversationView, { client: this.props.client, conversation: this.props.conversation, sdk: this.props.sdk, - conversationAppStore: this.props.conversationAppStore, - feedbackStore: this.props.feedbackStore} + conversationAppStore: this.props.conversationAppStore} )); } case "outgoing": { return (React.createElement(OutgoingConversationView, { store: this.props.conversationStore, - dispatcher: this.props.dispatcher, - feedbackStore: this.props.feedbackStore} + dispatcher: this.props.dispatcher} )); } case "room": { return (React.createElement(DesktopRoomConversationView, { dispatcher: this.props.dispatcher, - roomStore: this.props.roomStore, - feedbackStore: this.props.feedbackStore} + roomStore: this.props.roomStore} )); } case "failed": { return React.createElement(GenericFailureView, {cancelCall: this.closeWindow}); } default: { // If we don't have a windowType, we don't know what we are yet, // so don't display anything. @@ -150,16 +145,18 @@ loop.conversation = (function(mozL10n) { var roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop, activeRoomStore: activeRoomStore }); var feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: feedbackClient }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + // XXX Old class creation for the incoming conversation view, whilst // we transition across (bug 1072323). var conversation = new sharedModels.ConversationModel({}, { sdk: window.OT, mozLoop: navigator.mozLoop }); // Obtain the windowId and pass it through @@ -181,17 +178,16 @@ loop.conversation = (function(mozL10n) { navigator.mozLoop.calls.clearCallInProgress(windowId); dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(React.createElement(AppControllerView, { conversationAppStore: conversationAppStore, roomStore: roomStore, - feedbackStore: feedbackStore, conversationStore: conversationStore, client: client, conversation: conversation, dispatcher: dispatcher, sdk: window.OT} ), document.querySelector('#main')); dispatcher.dispatch(new sharedActions.GetWindowData({
--- a/browser/components/loop/content/js/conversation.jsx +++ b/browser/components/loop/content/js/conversation.jsx @@ -37,19 +37,17 @@ loop.conversation = (function(mozL10n) { sdk: React.PropTypes.object.isRequired, // XXX New types for flux style conversationAppStore: React.PropTypes.instanceOf( loop.store.ConversationAppStore).isRequired, conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore) .isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - roomStore: React.PropTypes.instanceOf(loop.store.RoomStore), - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + roomStore: React.PropTypes.instanceOf(loop.store.RoomStore) }, getInitialState: function() { return this.props.conversationAppStore.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.conversationAppStore, "change", function() { @@ -64,31 +62,28 @@ loop.conversation = (function(mozL10n) { render: function() { switch(this.state.windowType) { case "incoming": { return (<IncomingConversationView client={this.props.client} conversation={this.props.conversation} sdk={this.props.sdk} conversationAppStore={this.props.conversationAppStore} - feedbackStore={this.props.feedbackStore} />); } case "outgoing": { return (<OutgoingConversationView store={this.props.conversationStore} dispatcher={this.props.dispatcher} - feedbackStore={this.props.feedbackStore} />); } case "room": { return (<DesktopRoomConversationView dispatcher={this.props.dispatcher} roomStore={this.props.roomStore} - feedbackStore={this.props.feedbackStore} />); } case "failed": { return <GenericFailureView cancelCall={this.closeWindow} />; } default: { // If we don't have a windowType, we don't know what we are yet, // so don't display anything. @@ -150,16 +145,18 @@ loop.conversation = (function(mozL10n) { var roomStore = new loop.store.RoomStore(dispatcher, { mozLoop: navigator.mozLoop, activeRoomStore: activeRoomStore }); var feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: feedbackClient }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + // XXX Old class creation for the incoming conversation view, whilst // we transition across (bug 1072323). var conversation = new sharedModels.ConversationModel({}, { sdk: window.OT, mozLoop: navigator.mozLoop }); // Obtain the windowId and pass it through @@ -181,17 +178,16 @@ loop.conversation = (function(mozL10n) { navigator.mozLoop.calls.clearCallInProgress(windowId); dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(<AppControllerView conversationAppStore={conversationAppStore} roomStore={roomStore} - feedbackStore={feedbackStore} conversationStore={conversationStore} client={client} conversation={conversation} dispatcher={dispatcher} sdk={window.OT} />, document.querySelector('#main')); dispatcher.dispatch(new sharedActions.GetWindowData({
--- a/browser/components/loop/content/js/conversationViews.js +++ b/browser/components/loop/content/js/conversationViews.js @@ -343,19 +343,17 @@ loop.conversationViews = (function(mozL1 mixins: [sharedMixins.AudioMixin, sharedMixins.WindowCloseMixin], propTypes: { client: React.PropTypes.instanceOf(loop.Client).isRequired, conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, conversationAppStore: React.PropTypes.instanceOf( - loop.store.ConversationAppStore).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + loop.store.ConversationAppStore).isRequired }, getInitialState: function() { return { callFailed: false, // XXX this should be removed when bug 1047410 lands. callStatus: "start" }; }, @@ -421,17 +419,16 @@ loop.conversationViews = (function(mozL1 } document.title = mozL10n.get("conversation_has_ended"); this.play("terminated"); return ( React.createElement(sharedViews.FeedbackView, { - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.closeWindow.bind(this)} ) ); } case "close": { this.closeWindow(); return (React.createElement("div", null)); } @@ -924,18 +921,17 @@ loop.conversationViews = (function(mozL1 mixins: [ sharedMixins.AudioMixin, Backbone.Events ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, store: React.PropTypes.instanceOf( - loop.store.ConversationStore).isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + loop.store.ConversationStore).isRequired }, getInitialState: function() { return this.props.store.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.store, "change", function() { @@ -964,17 +960,16 @@ loop.conversationViews = (function(mozL1 /** * Used to setup and render the feedback view. */ _renderFeedbackView: function() { document.title = mozL10n.get("conversation_has_ended"); return ( React.createElement(sharedViews.FeedbackView, { - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this._closeWindow.bind(this)} ) ); }, render: function() { switch (this.state.callState) { case CALL_STATES.CLOSE: {
--- a/browser/components/loop/content/js/conversationViews.jsx +++ b/browser/components/loop/content/js/conversationViews.jsx @@ -343,19 +343,17 @@ loop.conversationViews = (function(mozL1 mixins: [sharedMixins.AudioMixin, sharedMixins.WindowCloseMixin], propTypes: { client: React.PropTypes.instanceOf(loop.Client).isRequired, conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, conversationAppStore: React.PropTypes.instanceOf( - loop.store.ConversationAppStore).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + loop.store.ConversationAppStore).isRequired }, getInitialState: function() { return { callFailed: false, // XXX this should be removed when bug 1047410 lands. callStatus: "start" }; }, @@ -421,17 +419,16 @@ loop.conversationViews = (function(mozL1 } document.title = mozL10n.get("conversation_has_ended"); this.play("terminated"); return ( <sharedViews.FeedbackView - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this.closeWindow.bind(this)} /> ); } case "close": { this.closeWindow(); return (<div/>); } @@ -924,18 +921,17 @@ loop.conversationViews = (function(mozL1 mixins: [ sharedMixins.AudioMixin, Backbone.Events ], propTypes: { dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, store: React.PropTypes.instanceOf( - loop.store.ConversationStore).isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + loop.store.ConversationStore).isRequired }, getInitialState: function() { return this.props.store.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.store, "change", function() { @@ -964,17 +960,16 @@ loop.conversationViews = (function(mozL1 /** * Used to setup and render the feedback view. */ _renderFeedbackView: function() { document.title = mozL10n.get("conversation_has_ended"); return ( <sharedViews.FeedbackView - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this._closeWindow.bind(this)} /> ); }, render: function() { switch (this.state.callState) { case CALL_STATES.CLOSE: {
--- a/browser/components/loop/content/js/roomViews.js +++ b/browser/components/loop/content/js/roomViews.js @@ -164,19 +164,17 @@ loop.roomViews = (function(mozL10n) { mixins: [ ActiveRoomStoreMixin, sharedMixins.DocumentTitleMixin, sharedMixins.MediaSetupMixin, sharedMixins.RoomsAudioMixin ], propTypes: { - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired, + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired }, _renderInvitationOverlay: function() { if (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS) { return React.createElement(DesktopRoomInvitationView, { roomStore: this.props.roomStore, dispatcher: this.props.dispatcher} ); @@ -247,17 +245,16 @@ loop.roomViews = (function(mozL10n) { // FULL case should never happen on desktop. return React.createElement(loop.conversationViews.GenericFailureView, { cancelCall: this.closeWindow} ); } case ROOM_STATES.ENDED: { if (this.state.used) return React.createElement(sharedViews.FeedbackView, { - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.closeWindow} ); // In case the room was not used (no one was here), we // bypass the feedback form. this.closeWindow(); return null; }
--- a/browser/components/loop/content/js/roomViews.jsx +++ b/browser/components/loop/content/js/roomViews.jsx @@ -164,19 +164,17 @@ loop.roomViews = (function(mozL10n) { mixins: [ ActiveRoomStoreMixin, sharedMixins.DocumentTitleMixin, sharedMixins.MediaSetupMixin, sharedMixins.RoomsAudioMixin ], propTypes: { - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired, + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired }, _renderInvitationOverlay: function() { if (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS) { return <DesktopRoomInvitationView roomStore={this.props.roomStore} dispatcher={this.props.dispatcher} />; @@ -247,17 +245,16 @@ loop.roomViews = (function(mozL10n) { // FULL case should never happen on desktop. return <loop.conversationViews.GenericFailureView cancelCall={this.closeWindow} />; } case ROOM_STATES.ENDED: { if (this.state.used) return <sharedViews.FeedbackView - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this.closeWindow} />; // In case the room was not used (no one was here), we // bypass the feedback form. this.closeWindow(); return null; }
--- a/browser/components/loop/content/shared/js/feedbackViews.js +++ b/browser/components/loop/content/shared/js/feedbackViews.js @@ -211,60 +211,50 @@ loop.shared.views.FeedbackView = (functi ); } }); /** * Feedback view. */ var FeedbackView = React.createClass({displayName: "FeedbackView", - mixins: [Backbone.Events], + mixins: [ + Backbone.Events, + loop.store.StoreMixin("feedbackStore") + ], propTypes: { - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func, // Used by the UI showcase. feedbackState: React.PropTypes.string }, getInitialState: function() { - var storeState = this.props.feedbackStore.getStoreState(); + var storeState = this.getStoreState(); return _.extend({}, storeState, { feedbackState: this.props.feedbackState || storeState.feedbackState }); }, - componentWillMount: function() { - this.listenTo(this.props.feedbackStore, "change", this._onStoreStateChanged); - }, - - componentWillUnmount: function() { - this.stopListening(this.props.feedbackStore); - }, - - _onStoreStateChanged: function() { - this.setState(this.props.feedbackStore.getStoreState()); - }, - reset: function() { - this.setState(this.props.feedbackStore.getInitialStoreState()); + this.setState(this.getStore().getInitialStoreState()); }, handleHappyClick: function() { // XXX: If the user is happy, we directly send this information to the // feedback API; this is a behavior we might want to revisit later. - this.props.feedbackStore.dispatchAction(new sharedActions.SendFeedback({ + this.getStore().dispatchAction(new sharedActions.SendFeedback({ happy: true, category: "", description: "" })); }, handleSadClick: function() { - this.props.feedbackStore.dispatchAction( + this.getStore().dispatchAction( new sharedActions.RequireFeedbackDetails()); }, _onFeedbackSent: function(err) { if (err) { // XXX better end user error reporting, see bug 1046738 console.error("Unable to send user feedback", err); } @@ -285,17 +275,17 @@ loop.shared.views.FeedbackView = (functi onClick: this.handleSadClick}) ) ) ); } case FEEDBACK_STATES.DETAILS: { return ( React.createElement(FeedbackForm, { - feedbackStore: this.props.feedbackStore, + feedbackStore: this.getStore(), reset: this.reset, pending: this.state.feedbackState === FEEDBACK_STATES.PENDING}) ); } case FEEDBACK_STATES.PENDING: case FEEDBACK_STATES.SENT: case FEEDBACK_STATES.FAILED: { if (this.state.error) {
--- a/browser/components/loop/content/shared/js/feedbackViews.jsx +++ b/browser/components/loop/content/shared/js/feedbackViews.jsx @@ -211,60 +211,50 @@ loop.shared.views.FeedbackView = (functi ); } }); /** * Feedback view. */ var FeedbackView = React.createClass({ - mixins: [Backbone.Events], + mixins: [ + Backbone.Events, + loop.store.StoreMixin("feedbackStore") + ], propTypes: { - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func, // Used by the UI showcase. feedbackState: React.PropTypes.string }, getInitialState: function() { - var storeState = this.props.feedbackStore.getStoreState(); + var storeState = this.getStoreState(); return _.extend({}, storeState, { feedbackState: this.props.feedbackState || storeState.feedbackState }); }, - componentWillMount: function() { - this.listenTo(this.props.feedbackStore, "change", this._onStoreStateChanged); - }, - - componentWillUnmount: function() { - this.stopListening(this.props.feedbackStore); - }, - - _onStoreStateChanged: function() { - this.setState(this.props.feedbackStore.getStoreState()); - }, - reset: function() { - this.setState(this.props.feedbackStore.getInitialStoreState()); + this.setState(this.getStore().getInitialStoreState()); }, handleHappyClick: function() { // XXX: If the user is happy, we directly send this information to the // feedback API; this is a behavior we might want to revisit later. - this.props.feedbackStore.dispatchAction(new sharedActions.SendFeedback({ + this.getStore().dispatchAction(new sharedActions.SendFeedback({ happy: true, category: "", description: "" })); }, handleSadClick: function() { - this.props.feedbackStore.dispatchAction( + this.getStore().dispatchAction( new sharedActions.RequireFeedbackDetails()); }, _onFeedbackSent: function(err) { if (err) { // XXX better end user error reporting, see bug 1046738 console.error("Unable to send user feedback", err); } @@ -285,17 +275,17 @@ loop.shared.views.FeedbackView = (functi onClick={this.handleSadClick}></button> </div> </FeedbackLayout> ); } case FEEDBACK_STATES.DETAILS: { return ( <FeedbackForm - feedbackStore={this.props.feedbackStore} + feedbackStore={this.getStore()} reset={this.reset} pending={this.state.feedbackState === FEEDBACK_STATES.PENDING} /> ); } case FEEDBACK_STATES.PENDING: case FEEDBACK_STATES.SENT: case FEEDBACK_STATES.FAILED: { if (this.state.error) {
--- a/browser/components/loop/content/shared/js/store.js +++ b/browser/components/loop/content/shared/js/store.js @@ -100,8 +100,48 @@ loop.store.createStore = (function() { Backbone.Events, baseStorePrototype, storeProto); return BaseStore; } return createStore; })(); + +/** + * Store mixin generator. Usage: + * + * StoreMixin.register({roomStore: new RoomStore(…)}); + * var Comp = React.createClass({ + * mixins: [StoreMixin("roomStore")] + * }); + */ +loop.store.StoreMixin = (function() { + var _stores = {}; + function StoreMixin(id) { + function _getStore() { + if (!_stores[id]) { + throw new Error("Unavailable store " + id); + } + return _stores[id]; + } + return { + getStore: function() { + return _getStore(); + }, + getStoreState: function() { + return this.getStore().getStoreState(); + }, + componentWillMount: function() { + this.getStore().on("change", function() { + this.setState(this.getStoreState()); + }, this); + }, + componentWillUnmount: function() { + this.getStore().off("change"); + } + }; + } + StoreMixin.register = function(stores) { + _.extend(_stores, stores); + }; + return StoreMixin; +})();
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js @@ -18,19 +18,17 @@ loop.standaloneRoomViews = (function(moz var sharedViews = loop.shared.views; var StandaloneRoomInfoArea = React.createClass({displayName: "StandaloneRoomInfoArea", propTypes: { helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired, activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) - ]).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + ]).isRequired }, onFeedbackSent: function() { // We pass a tick to prevent React warnings regarding nested updates. setTimeout(function() { this.props.activeRoomStore.dispatchAction(new sharedActions.FeedbackComplete()); }.bind(this)); }, @@ -115,17 +113,16 @@ loop.standaloneRoomViews = (function(moz ) ); } case ROOM_STATES.ENDED: { if (this.props.roomUsed) return ( React.createElement("div", {className: "ended-conversation"}, React.createElement(sharedViews.FeedbackView, { - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.onFeedbackSent} ) ) ); // In case the room was not used (no one was here), we // bypass the feedback form. this.onFeedbackSent(); @@ -198,18 +195,16 @@ loop.standaloneRoomViews = (function(moz sharedMixins.RoomsAudioMixin ], propTypes: { activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired }, getInitialState: function() { var storeState = this.props.activeRoomStore.getStoreState(); return _.extend({}, storeState, { // Used by the UI showcase. @@ -311,17 +306,16 @@ loop.standaloneRoomViews = (function(moz React.createElement("div", {className: "room-conversation-wrapper"}, React.createElement("div", {className: "beta-logo"}), React.createElement(StandaloneRoomHeader, null), React.createElement(StandaloneRoomInfoArea, {roomState: this.state.roomState, failureReason: this.state.failureReason, joinRoom: this.joinRoom, helper: this.props.helper, activeRoomStore: this.props.activeRoomStore, - feedbackStore: this.props.feedbackStore, roomUsed: this.state.used}), React.createElement("div", {className: "video-layout-wrapper"}, React.createElement("div", {className: "conversation room-conversation"}, React.createElement("h2", {className: "room-name"}, this.state.roomName), React.createElement("div", {className: "media nested"}, React.createElement("span", {className: "self-view-hidden-message"}, mozL10n.get("self_view_hidden_message") ),
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx +++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx @@ -18,19 +18,17 @@ loop.standaloneRoomViews = (function(moz var sharedViews = loop.shared.views; var StandaloneRoomInfoArea = React.createClass({ propTypes: { helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired, activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) - ]).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired + ]).isRequired }, onFeedbackSent: function() { // We pass a tick to prevent React warnings regarding nested updates. setTimeout(function() { this.props.activeRoomStore.dispatchAction(new sharedActions.FeedbackComplete()); }.bind(this)); }, @@ -115,17 +113,16 @@ loop.standaloneRoomViews = (function(moz </div> ); } case ROOM_STATES.ENDED: { if (this.props.roomUsed) return ( <div className="ended-conversation"> <sharedViews.FeedbackView - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this.onFeedbackSent} /> </div> ); // In case the room was not used (no one was here), we // bypass the feedback form. this.onFeedbackSent(); @@ -198,18 +195,16 @@ loop.standaloneRoomViews = (function(moz sharedMixins.RoomsAudioMixin ], propTypes: { activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, - feedbackStore: - React.PropTypes.instanceOf(loop.store.FeedbackStore).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, helper: React.PropTypes.instanceOf(loop.shared.utils.Helper).isRequired }, getInitialState: function() { var storeState = this.props.activeRoomStore.getStoreState(); return _.extend({}, storeState, { // Used by the UI showcase. @@ -311,17 +306,16 @@ loop.standaloneRoomViews = (function(moz <div className="room-conversation-wrapper"> <div className="beta-logo" /> <StandaloneRoomHeader /> <StandaloneRoomInfoArea roomState={this.state.roomState} failureReason={this.state.failureReason} joinRoom={this.joinRoom} helper={this.props.helper} activeRoomStore={this.props.activeRoomStore} - feedbackStore={this.props.feedbackStore} roomUsed={this.state.used} /> <div className="video-layout-wrapper"> <div className="conversation room-conversation"> <h2 className="room-name">{this.state.roomName}</h2> <div className="media nested"> <span className="self-view-hidden-message"> {mozL10n.get("self_view_hidden_message")} </span>
--- a/browser/components/loop/standalone/content/js/webapp.js +++ b/browser/components/loop/standalone/content/js/webapp.js @@ -558,28 +558,26 @@ loop.webapp = (function($, _, OT, mozL10 /** * Ended conversation view. */ var EndedConversationView = React.createClass({displayName: "EndedConversationView", propTypes: { conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func.isRequired }, render: function() { document.title = mozL10n.get("standalone_title_with_status", {clientShortname: mozL10n.get("clientShortname2"), currentStatus: mozL10n.get("status_conversation_ended")}); return ( React.createElement("div", {className: "ended-conversation"}, React.createElement(sharedViews.FeedbackView, { - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.props.onAfterFeedbackReceived} ), React.createElement(sharedViews.ConversationView, { initiate: false, sdk: this.props.sdk, model: this.props.conversation, audio: {enabled: false, visible: false}, video: {enabled: false, visible: false}} @@ -626,21 +624,21 @@ loop.webapp = (function($, _, OT, mozL10 */ var OutgoingConversationView = React.createClass({displayName: "OutgoingConversationView", propTypes: { client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired, conversation: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(sharedModels.ConversationModel), React.PropTypes.instanceOf(FxOSConversationModel) ]).isRequired, + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired, notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection) .isRequired, - sdk: React.PropTypes.object.isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + sdk: React.PropTypes.object.isRequired }, getInitialState: function() { return { callStatus: "start" }; }, @@ -661,17 +659,17 @@ loop.webapp = (function($, _, OT, mozL10 }, shouldComponentUpdate: function(nextProps, nextState) { // Only rerender if current state has actually changed return nextState.callStatus !== this.state.callStatus; }, resetCallStatus: function() { - this.props.feedbackStore.dispatchAction(new sharedActions.FeedbackComplete()); + this.props.dispatcher.dispatch(new sharedActions.FeedbackComplete()); return function() { this.setState({callStatus: "start"}); }.bind(this); }, /** * Renders the conversation views. */ @@ -714,17 +712,16 @@ loop.webapp = (function($, _, OT, mozL10 ) ); } case "end": { return ( React.createElement(EndedConversationView, { sdk: this.props.sdk, conversation: this.props.conversation, - feedbackStore: this.props.feedbackStore, onAfterFeedbackReceived: this.resetCallStatus()} ) ); } case "expired": { return ( React.createElement(CallUrlExpiredView, {helper: this.props.helper}) ); @@ -937,18 +934,17 @@ loop.webapp = (function($, _, OT, mozL10 // XXX New types for flux style standaloneAppStore: React.PropTypes.instanceOf( loop.store.StandaloneAppStore).isRequired, activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired }, getInitialState: function() { return this.props.standaloneAppStore.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.standaloneAppStore, "change", function() { @@ -971,29 +967,28 @@ loop.webapp = (function($, _, OT, mozL10 } case "unsupportedBrowser": { return React.createElement(UnsupportedBrowserView, {helper: this.props.helper}); } case "outgoing": { return ( React.createElement(OutgoingConversationView, { client: this.props.client, + dispatcher: this.props.dispatcher, conversation: this.props.conversation, helper: this.props.helper, notifications: this.props.notifications, - sdk: this.props.sdk, - feedbackStore: this.props.feedbackStore} + sdk: this.props.sdk} ) ); } case "room": { return ( React.createElement(loop.standaloneRoomViews.StandaloneRoomView, { activeRoomStore: this.props.activeRoomStore, - feedbackStore: this.props.feedbackStore, dispatcher: this.props.dispatcher, helper: this.props.helper} ) ); } case "home": { return React.createElement(HomeView, null); } @@ -1070,27 +1065,28 @@ loop.webapp = (function($, _, OT, mozL10 dispatcher: dispatcher, helper: helper, sdk: OT }); var feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: feedbackClient }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + window.addEventListener("unload", function() { dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(React.createElement(WebappRootView, { client: client, conversation: conversation, helper: helper, notifications: notifications, sdk: OT, - feedbackStore: feedbackStore, standaloneAppStore: standaloneAppStore, activeRoomStore: activeRoomStore, dispatcher: dispatcher} ), document.querySelector("#main")); // Set the 'lang' and 'dir' attributes to <html> when the page is translated document.documentElement.lang = mozL10n.language.code; document.documentElement.dir = mozL10n.language.direction;
--- a/browser/components/loop/standalone/content/js/webapp.jsx +++ b/browser/components/loop/standalone/content/js/webapp.jsx @@ -558,28 +558,26 @@ loop.webapp = (function($, _, OT, mozL10 /** * Ended conversation view. */ var EndedConversationView = React.createClass({ propTypes: { conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel) .isRequired, sdk: React.PropTypes.object.isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore), onAfterFeedbackReceived: React.PropTypes.func.isRequired }, render: function() { document.title = mozL10n.get("standalone_title_with_status", {clientShortname: mozL10n.get("clientShortname2"), currentStatus: mozL10n.get("status_conversation_ended")}); return ( <div className="ended-conversation"> <sharedViews.FeedbackView - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this.props.onAfterFeedbackReceived} /> <sharedViews.ConversationView initiate={false} sdk={this.props.sdk} model={this.props.conversation} audio={{enabled: false, visible: false}} video={{enabled: false, visible: false}} @@ -626,21 +624,21 @@ loop.webapp = (function($, _, OT, mozL10 */ var OutgoingConversationView = React.createClass({ propTypes: { client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired, conversation: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(sharedModels.ConversationModel), React.PropTypes.instanceOf(FxOSConversationModel) ]).isRequired, + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, helper: React.PropTypes.instanceOf(sharedUtils.Helper).isRequired, notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection) .isRequired, - sdk: React.PropTypes.object.isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + sdk: React.PropTypes.object.isRequired }, getInitialState: function() { return { callStatus: "start" }; }, @@ -661,17 +659,17 @@ loop.webapp = (function($, _, OT, mozL10 }, shouldComponentUpdate: function(nextProps, nextState) { // Only rerender if current state has actually changed return nextState.callStatus !== this.state.callStatus; }, resetCallStatus: function() { - this.props.feedbackStore.dispatchAction(new sharedActions.FeedbackComplete()); + this.props.dispatcher.dispatch(new sharedActions.FeedbackComplete()); return function() { this.setState({callStatus: "start"}); }.bind(this); }, /** * Renders the conversation views. */ @@ -714,17 +712,16 @@ loop.webapp = (function($, _, OT, mozL10 /> ); } case "end": { return ( <EndedConversationView sdk={this.props.sdk} conversation={this.props.conversation} - feedbackStore={this.props.feedbackStore} onAfterFeedbackReceived={this.resetCallStatus()} /> ); } case "expired": { return ( <CallUrlExpiredView helper={this.props.helper} /> ); @@ -937,18 +934,17 @@ loop.webapp = (function($, _, OT, mozL10 // XXX New types for flux style standaloneAppStore: React.PropTypes.instanceOf( loop.store.StandaloneAppStore).isRequired, activeRoomStore: React.PropTypes.oneOfType([ React.PropTypes.instanceOf(loop.store.ActiveRoomStore), React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore) ]).isRequired, - dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, - feedbackStore: React.PropTypes.instanceOf(loop.store.FeedbackStore) + dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired }, getInitialState: function() { return this.props.standaloneAppStore.getStoreState(); }, componentWillMount: function() { this.listenTo(this.props.standaloneAppStore, "change", function() { @@ -971,29 +967,28 @@ loop.webapp = (function($, _, OT, mozL10 } case "unsupportedBrowser": { return <UnsupportedBrowserView helper={this.props.helper}/>; } case "outgoing": { return ( <OutgoingConversationView client={this.props.client} + dispatcher={this.props.dispatcher} conversation={this.props.conversation} helper={this.props.helper} notifications={this.props.notifications} sdk={this.props.sdk} - feedbackStore={this.props.feedbackStore} /> ); } case "room": { return ( <loop.standaloneRoomViews.StandaloneRoomView activeRoomStore={this.props.activeRoomStore} - feedbackStore={this.props.feedbackStore} dispatcher={this.props.dispatcher} helper={this.props.helper} /> ); } case "home": { return <HomeView />; } @@ -1070,27 +1065,28 @@ loop.webapp = (function($, _, OT, mozL10 dispatcher: dispatcher, helper: helper, sdk: OT }); var feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: feedbackClient }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + window.addEventListener("unload", function() { dispatcher.dispatch(new sharedActions.WindowUnload()); }); React.render(<WebappRootView client={client} conversation={conversation} helper={helper} notifications={notifications} sdk={OT} - feedbackStore={feedbackStore} standaloneAppStore={standaloneAppStore} activeRoomStore={activeRoomStore} dispatcher={dispatcher} />, document.querySelector("#main")); // Set the 'lang' and 'dir' attributes to <html> when the page is translated document.documentElement.lang = mozL10n.language.code; document.documentElement.dir = mozL10n.language.direction;
--- a/browser/components/loop/test/desktop-local/conversationViews_test.js +++ b/browser/components/loop/test/desktop-local/conversationViews_test.js @@ -577,18 +577,17 @@ describe("loop.conversationViews", funct describe("OutgoingConversationView", function() { var store, feedbackStore; function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.OutgoingConversationView, { dispatcher: dispatcher, - store: store, - feedbackStore: feedbackStore + store: store })); } beforeEach(function() { store = new loop.store.ConversationStore(dispatcher, { client: {}, mozLoop: fakeMozLoop, sdkDriver: {} @@ -684,18 +683,17 @@ describe("loop.conversationViews", funct feedbackStore; function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement(loop.conversationViews.IncomingConversationView, { client: client, conversation: conversation, sdk: {}, - conversationAppStore: conversationAppStore, - feedbackStore: feedbackStore + conversationAppStore: conversationAppStore })); } beforeEach(function() { oldTitle = document.title; client = new loop.Client(); conversation = new loop.shared.models.ConversationModel({}, { sdk: {}
--- a/browser/components/loop/test/desktop-local/roomViews_test.js +++ b/browser/components/loop/test/desktop-local/roomViews_test.js @@ -197,27 +197,29 @@ describe("loop.roomViews", function () { }); }); }); describe("DesktopRoomConversationView", function() { var view; beforeEach(function() { + loop.store.StoreMixin.register({ + feedbackStore: new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }) + }); sandbox.stub(dispatcher, "dispatch"); }); function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement(loop.roomViews.DesktopRoomConversationView, { dispatcher: dispatcher, - roomStore: roomStore, - feedbackStore: new loop.store.FeedbackStore(dispatcher, { - feedbackClient: {} - }) + roomStore: roomStore })); } it("should dispatch a setMute action when the audio mute button is pressed", function() { view = mountTestComponent(); view.setState({audioMuted: true});
--- a/browser/components/loop/test/shared/feedbackViews_test.js +++ b/browser/components/loop/test/shared/feedbackViews_test.js @@ -20,20 +20,19 @@ describe("loop.shared.views.FeedbackView beforeEach(function() { sandbox = sinon.sandbox.create(); dispatcher = new loop.Dispatcher(); fakeFeedbackClient = {send: sandbox.stub()}; feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: fakeFeedbackClient }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); comp = TestUtils.renderIntoDocument( - React.createElement(sharedViews.FeedbackView, { - feedbackStore: feedbackStore - })); + React.createElement(sharedViews.FeedbackView)); }); afterEach(function() { sandbox.restore(); }); // local test helpers function clickHappyFace(comp) {
--- a/browser/components/loop/test/standalone/standaloneRoomViews_test.js +++ b/browser/components/loop/test/standalone/standaloneRoomViews_test.js @@ -21,16 +21,17 @@ describe("loop.standaloneRoomViews", fun dispatch = sandbox.stub(dispatcher, "dispatch"); activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, { mozLoop: {}, sdkDriver: {} }); feedbackStore = new loop.store.FeedbackStore(dispatcher, { feedbackClient: {} }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); sandbox.useFakeTimers(); // Prevents audio request errors in the test console. sandbox.useFakeXMLHttpRequest(); }); afterEach(function() { @@ -39,17 +40,16 @@ describe("loop.standaloneRoomViews", fun describe("StandaloneRoomView", function() { function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement( loop.standaloneRoomViews.StandaloneRoomView, { dispatcher: dispatcher, activeRoomStore: activeRoomStore, - feedbackStore: feedbackStore, helper: new loop.shared.utils.Helper() })); } function expectActionDispatched(view) { sinon.assert.calledOnce(dispatch); sinon.assert.calledWithExactly(dispatch, sinon.match.instanceOf(sharedActions.SetupStreamElements));
--- a/browser/components/loop/test/standalone/webapp_test.js +++ b/browser/components/loop/test/standalone/webapp_test.js @@ -15,25 +15,26 @@ describe("loop.webapp", function() { sharedViews = loop.shared.views, sharedUtils = loop.shared.utils, standaloneMedia = loop.standaloneMedia, sandbox, notifications, stubGetPermsAndCacheMedia, fakeAudioXHR, dispatcher, - feedbackStore, WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS; beforeEach(function() { sandbox = sinon.sandbox.create(); dispatcher = new loop.Dispatcher(); notifications = new sharedModels.NotificationCollection(); - feedbackStore = new loop.store.FeedbackStore(dispatcher, { - feedbackClient: {} + loop.store.StoreMixin.register({ + feedbackStore: new loop.store.FeedbackStore(dispatcher, { + feedbackClient: {} + }) }); stubGetPermsAndCacheMedia = sandbox.stub( loop.standaloneMedia._MultiplexGum.prototype, "getPermsAndCacheMedia"); fakeAudioXHR = { open: sinon.spy(), send: function() {}, @@ -122,17 +123,17 @@ describe("loop.webapp", function() { }); conversation.set("loopToken", "fakeToken"); ocView = mountTestComponent({ helper: new sharedUtils.Helper(), client: client, conversation: conversation, notifications: notifications, sdk: {}, - feedbackStore: feedbackStore + dispatcher: dispatcher }); }); describe("start", function() { it("should display the StartConversationView", function() { TestUtils.findRenderedComponentWithType(ocView, loop.webapp.StartConversationView); }); @@ -647,22 +648,22 @@ describe("loop.webapp", function() { var activeRoomStore; function mountTestComponent() { return TestUtils.renderIntoDocument( React.createElement( loop.webapp.WebappRootView, { client: client, helper: helper, + dispatcher: dispatcher, notifications: notifications, sdk: sdk, conversation: conversationModel, standaloneAppStore: standaloneAppStore, - activeRoomStore: activeRoomStore, - feedbackStore: feedbackStore + activeRoomStore: activeRoomStore })); } beforeEach(function() { helper = new sharedUtils.Helper(); sdk = { checkSystemRequirements: function() { return true; } }; @@ -1080,17 +1081,16 @@ describe("loop.webapp", function() { sdk: {} }); sandbox.stub(window, "XMLHttpRequest").returns(fakeAudioXHR); view = React.addons.TestUtils.renderIntoDocument( React.createElement( loop.webapp.EndedConversationView, { conversation: conversation, sdk: {}, - feedbackStore: feedbackStore, onAfterFeedbackReceived: function(){} })); }); it("should render a ConversationView", function() { TestUtils.findRenderedComponentWithType(view, sharedViews.ConversationView); });
--- a/browser/components/loop/ui/ui-showcase.js +++ b/browser/components/loop/ui/ui-showcase.js @@ -75,16 +75,18 @@ feedbackClient: stageFeedbackApiClient }); var conversationStore = new loop.store.ConversationStore(dispatcher, { client: {}, mozLoop: navigator.mozLoop, sdkDriver: {} }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + // Local mocks var mockMozLoopRooms = _.extend({}, navigator.mozLoop); var mockContact = { name: ["Mr Smith"], email: [{ value: "smith@invalid.com"
--- a/browser/components/loop/ui/ui-showcase.jsx +++ b/browser/components/loop/ui/ui-showcase.jsx @@ -75,16 +75,18 @@ feedbackClient: stageFeedbackApiClient }); var conversationStore = new loop.store.ConversationStore(dispatcher, { client: {}, mozLoop: navigator.mozLoop, sdkDriver: {} }); + loop.store.StoreMixin.register({feedbackStore: feedbackStore}); + // Local mocks var mockMozLoopRooms = _.extend({}, navigator.mozLoop); var mockContact = { name: ["Mr Smith"], email: [{ value: "smith@invalid.com"