Bug 1074686 - Part 3 Revamped view architecture for Desktop Loop rooms. r=Standard8

This commit is contained in:
Nicolas Perriault 2014-11-11 09:33:05 +00:00
Родитель 3baff77d36
Коммит d384c380c8
8 изменённых файлов: 165 добавлений и 211 удалений

Просмотреть файл

@ -18,7 +18,7 @@ loop.conversation = (function(mozL10n) {
var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
var CallIdentifierView = loop.conversationViews.CallIdentifierView;
var DesktopRoomControllerView = loop.roomViews.DesktopRoomControllerView;
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
var IncomingCallView = React.createClass({displayName: 'IncomingCallView',
mixins: [sharedMixins.DropdownMenuMixin, sharedMixins.AudioMixin],
@ -584,8 +584,7 @@ loop.conversation = (function(mozL10n) {
));
}
case "room": {
return (DesktopRoomControllerView({
mozLoop: navigator.mozLoop,
return (DesktopRoomConversationView({
dispatcher: this.props.dispatcher,
roomStore: this.props.roomStore}
));

Просмотреть файл

@ -18,7 +18,7 @@ loop.conversation = (function(mozL10n) {
var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
var CallIdentifierView = loop.conversationViews.CallIdentifierView;
var DesktopRoomControllerView = loop.roomViews.DesktopRoomControllerView;
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
var IncomingCallView = React.createClass({
mixins: [sharedMixins.DropdownMenuMixin, sharedMixins.AudioMixin],
@ -584,8 +584,7 @@ loop.conversation = (function(mozL10n) {
/>);
}
case "room": {
return (<DesktopRoomControllerView
mozLoop={navigator.mozLoop}
return (<DesktopRoomConversationView
dispatcher={this.props.dispatcher}
roomStore={this.props.roomStore}
/>);

Просмотреть файл

@ -41,7 +41,11 @@ loop.roomViews = (function(mozL10n) {
},
getInitialState: function() {
return this.props.roomStore.getStoreState("activeRoom");
var storeState = this.props.roomStore.getStoreState("activeRoom");
return _.extend(storeState, {
// Used by the UI showcase.
roomState: this.props.roomState || storeState.roomState
});
}
};
@ -72,25 +76,22 @@ loop.roomViews = (function(mozL10n) {
render: function() {
return (
React.DOM.div({className: "room-conversation-wrapper"},
React.DOM.div({className: "room-invitation-overlay"},
React.DOM.form({onSubmit: this.handleFormSubmit},
React.DOM.input({type: "text", ref: "roomName",
placeholder: mozL10n.get("rooms_name_this_room_label")})
),
React.DOM.p(null, mozL10n.get("invite_header_text")),
React.DOM.div({className: "btn-group call-action-group"},
React.DOM.button({className: "btn btn-info btn-email",
onClick: this.handleEmailButtonClick},
mozL10n.get("share_button2")
),
React.DOM.button({className: "btn btn-info btn-copy",
onClick: this.handleCopyButtonClick},
mozL10n.get("copy_url_button2")
)
)
React.DOM.div({className: "room-invitation-overlay"},
React.DOM.form({onSubmit: this.handleFormSubmit},
React.DOM.input({type: "text", ref: "roomName",
placeholder: mozL10n.get("rooms_name_this_room_label")})
),
DesktopRoomConversationView({roomStore: this.props.roomStore})
React.DOM.p(null, mozL10n.get("invite_header_text")),
React.DOM.div({className: "btn-group call-action-group"},
React.DOM.button({className: "btn btn-info btn-email",
onClick: this.handleEmailButtonClick},
mozL10n.get("share_button2")
),
React.DOM.button({className: "btn btn-info btn-copy",
onClick: this.handleCopyButtonClick},
mozL10n.get("copy_url_button2")
)
)
)
);
}
@ -100,13 +101,12 @@ loop.roomViews = (function(mozL10n) {
* Desktop room conversation view.
*/
var DesktopRoomConversationView = React.createClass({displayName: 'DesktopRoomConversationView',
mixins: [ActiveRoomStoreMixin],
mixins: [ActiveRoomStoreMixin, loop.shared.mixins.DocumentTitleMixin],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
video: React.PropTypes.object,
audio: React.PropTypes.object,
displayInvitation: React.PropTypes.bool
audio: React.PropTypes.object
},
getDefaultProps: function() {
@ -116,89 +116,61 @@ loop.roomViews = (function(mozL10n) {
};
},
render: function() {
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.props.video.enabled
});
return (
React.DOM.div({className: "room-conversation-wrapper"},
React.DOM.div({className: "video-layout-wrapper"},
React.DOM.div({className: "conversation room-conversation"},
React.DOM.div({className: "media nested"},
React.DOM.div({className: "video_wrapper remote_wrapper"},
React.DOM.div({className: "video_inner remote"})
),
React.DOM.div({className: localStreamClasses})
),
sharedViews.ConversationToolbar({
video: this.props.video,
audio: this.props.audio,
publishStream: noop,
hangup: noop})
)
)
)
);
}
});
/**
* Desktop room controller view.
*/
var DesktopRoomControllerView = React.createClass({displayName: 'DesktopRoomControllerView',
mixins: [ActiveRoomStoreMixin, loop.shared.mixins.DocumentTitleMixin],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
},
closeWindow: function() {
window.close();
},
_renderRoomView: function(roomState) {
switch (roomState) {
case ROOM_STATES.FAILED: {
return loop.conversation.GenericFailureView({
cancelCall: this.closeWindow}
);
}
case ROOM_STATES.INIT:
case ROOM_STATES.GATHER:
case ROOM_STATES.READY:
case ROOM_STATES.JOINED: {
return DesktopRoomInvitationView({
dispatcher: this.props.dispatcher,
roomStore: this.props.roomStore}
);
}
// XXX needs bug 1074686/1074702
case ROOM_STATES.HAS_PARTICIPANTS: {
return DesktopRoomConversationView({
dispatcher: this.props.dispatcher,
roomStore: this.props.roomStore}
);
}
_renderInvitationOverlay: function() {
if (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS) {
return DesktopRoomInvitationView({
roomStore: this.props.roomStore,
dispatcher: this.props.dispatcher}
);
}
return null;
},
render: function() {
if (this.state.roomName) {
this.setTitle(this.state.roomName);
}
return (
React.DOM.div({className: "room-conversation-wrapper"},
this._renderRoomView(this.state.roomState)
)
);
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.props.video.enabled
});
switch(this.state.roomState) {
case ROOM_STATES.FAILED: {
return loop.conversation.GenericFailureView({
cancelCall: this.closeWindow}
);
}
default: {
return (
React.DOM.div({className: "room-conversation-wrapper"},
this._renderInvitationOverlay(),
React.DOM.div({className: "video-layout-wrapper"},
React.DOM.div({className: "conversation room-conversation"},
React.DOM.div({className: "media nested"},
React.DOM.div({className: "video_wrapper remote_wrapper"},
React.DOM.div({className: "video_inner remote"})
),
React.DOM.div({className: localStreamClasses})
),
sharedViews.ConversationToolbar({
video: this.props.video,
audio: this.props.audio,
publishStream: noop,
hangup: noop})
)
)
)
);
}
}
}
});
return {
ActiveRoomStoreMixin: ActiveRoomStoreMixin,
DesktopRoomControllerView: DesktopRoomControllerView,
DesktopRoomConversationView: DesktopRoomConversationView,
DesktopRoomInvitationView: DesktopRoomInvitationView
};

Просмотреть файл

@ -41,7 +41,11 @@ loop.roomViews = (function(mozL10n) {
},
getInitialState: function() {
return this.props.roomStore.getStoreState("activeRoom");
var storeState = this.props.roomStore.getStoreState("activeRoom");
return _.extend(storeState, {
// Used by the UI showcase.
roomState: this.props.roomState || storeState.roomState
});
}
};
@ -72,25 +76,22 @@ loop.roomViews = (function(mozL10n) {
render: function() {
return (
<div className="room-conversation-wrapper">
<div className="room-invitation-overlay">
<form onSubmit={this.handleFormSubmit}>
<input type="text" ref="roomName"
placeholder={mozL10n.get("rooms_name_this_room_label")} />
</form>
<p>{mozL10n.get("invite_header_text")}</p>
<div className="btn-group call-action-group">
<button className="btn btn-info btn-email"
onClick={this.handleEmailButtonClick}>
{mozL10n.get("share_button2")}
</button>
<button className="btn btn-info btn-copy"
onClick={this.handleCopyButtonClick}>
{mozL10n.get("copy_url_button2")}
</button>
</div>
<div className="room-invitation-overlay">
<form onSubmit={this.handleFormSubmit}>
<input type="text" ref="roomName"
placeholder={mozL10n.get("rooms_name_this_room_label")} />
</form>
<p>{mozL10n.get("invite_header_text")}</p>
<div className="btn-group call-action-group">
<button className="btn btn-info btn-email"
onClick={this.handleEmailButtonClick}>
{mozL10n.get("share_button2")}
</button>
<button className="btn btn-info btn-copy"
onClick={this.handleCopyButtonClick}>
{mozL10n.get("copy_url_button2")}
</button>
</div>
<DesktopRoomConversationView roomStore={this.props.roomStore} />
</div>
);
}
@ -100,13 +101,12 @@ loop.roomViews = (function(mozL10n) {
* Desktop room conversation view.
*/
var DesktopRoomConversationView = React.createClass({
mixins: [ActiveRoomStoreMixin],
mixins: [ActiveRoomStoreMixin, loop.shared.mixins.DocumentTitleMixin],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
video: React.PropTypes.object,
audio: React.PropTypes.object,
displayInvitation: React.PropTypes.bool
audio: React.PropTypes.object
},
getDefaultProps: function() {
@ -116,89 +116,61 @@ loop.roomViews = (function(mozL10n) {
};
},
render: function() {
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.props.video.enabled
});
return (
<div className="room-conversation-wrapper">
<div className="video-layout-wrapper">
<div className="conversation room-conversation">
<div className="media nested">
<div className="video_wrapper remote_wrapper">
<div className="video_inner remote"></div>
</div>
<div className={localStreamClasses}></div>
</div>
<sharedViews.ConversationToolbar
video={this.props.video}
audio={this.props.audio}
publishStream={noop}
hangup={noop} />
</div>
</div>
</div>
);
}
});
/**
* Desktop room controller view.
*/
var DesktopRoomControllerView = React.createClass({
mixins: [ActiveRoomStoreMixin, loop.shared.mixins.DocumentTitleMixin],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
},
closeWindow: function() {
window.close();
},
_renderRoomView: function(roomState) {
switch (roomState) {
case ROOM_STATES.FAILED: {
return <loop.conversation.GenericFailureView
cancelCall={this.closeWindow}
/>;
}
case ROOM_STATES.INIT:
case ROOM_STATES.GATHER:
case ROOM_STATES.READY:
case ROOM_STATES.JOINED: {
return <DesktopRoomInvitationView
dispatcher={this.props.dispatcher}
roomStore={this.props.roomStore}
/>;
}
// XXX needs bug 1074686/1074702
case ROOM_STATES.HAS_PARTICIPANTS: {
return <DesktopRoomConversationView
dispatcher={this.props.dispatcher}
roomStore={this.props.roomStore}
/>;
}
_renderInvitationOverlay: function() {
if (this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS) {
return <DesktopRoomInvitationView
roomStore={this.props.roomStore}
dispatcher={this.props.dispatcher}
/>;
}
return null;
},
render: function() {
if (this.state.roomName) {
this.setTitle(this.state.roomName);
}
return (
<div className="room-conversation-wrapper">{
this._renderRoomView(this.state.roomState)
}</div>
);
var localStreamClasses = React.addons.classSet({
local: true,
"local-stream": true,
"local-stream-audio": !this.props.video.enabled
});
switch(this.state.roomState) {
case ROOM_STATES.FAILED: {
return <loop.conversation.GenericFailureView
cancelCall={this.closeWindow}
/>;
}
default: {
return (
<div className="room-conversation-wrapper">
{this._renderInvitationOverlay()}
<div className="video-layout-wrapper">
<div className="conversation room-conversation">
<div className="media nested">
<div className="video_wrapper remote_wrapper">
<div className="video_inner remote"></div>
</div>
<div className={localStreamClasses}></div>
</div>
<sharedViews.ConversationToolbar
video={this.props.video}
audio={this.props.audio}
publishStream={noop}
hangup={noop} />
</div>
</div>
</div>
);
}
}
}
});
return {
ActiveRoomStoreMixin: ActiveRoomStoreMixin,
DesktopRoomControllerView: DesktopRoomControllerView,
DesktopRoomConversationView: DesktopRoomConversationView,
DesktopRoomInvitationView: DesktopRoomInvitationView
};

Просмотреть файл

@ -214,7 +214,7 @@ describe("loop.conversation", function() {
ccView = mountTestComponent();
TestUtils.findRenderedComponentWithType(ccView,
loop.roomViews.DesktopRoomControllerView);
loop.roomViews.DesktopRoomConversationView);
});
it("should display the GenericFailureView for failures", function() {

Просмотреть файл

@ -81,13 +81,13 @@ describe("loop.roomViews", function () {
});
});
describe("DesktopRoomControllerView", function() {
describe("DesktopRoomConversationView", function() {
var view;
function mountTestComponent() {
return TestUtils.renderIntoDocument(
new loop.roomViews.DesktopRoomControllerView({
mozLoop: {},
new loop.roomViews.DesktopRoomConversationView({
dispatcher: dispatcher,
roomStore: roomStore
}));
}

Просмотреть файл

@ -22,7 +22,6 @@
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
var CallFailedView = loop.conversationViews.CallFailedView;
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
var DesktopRoomInvitationView = loop.roomViews.DesktopRoomInvitationView;
// 2. Standalone webapp
var HomeView = loop.webapp.HomeView;
@ -39,6 +38,9 @@
var ConversationView = loop.shared.views.ConversationView;
var FeedbackView = loop.shared.views.FeedbackView;
// Room constants
var ROOM_STATES = loop.store.ROOM_STATES;
// Local helpers
function returnTrue() {
return true;
@ -533,20 +535,24 @@
)
),
Section({name: "DesktopRoomInvitationView"},
Example({summary: "Desktop room invitation", dashed: "true",
Section({name: "DesktopRoomConversationView"},
Example({summary: "Desktop room conversation (invitation)", dashed: "true",
style: {width: "260px", height: "265px"}},
React.DOM.div({className: "fx-embedded"},
DesktopRoomInvitationView({roomStore: roomStore})
DesktopRoomConversationView({
roomStore: roomStore,
dispatcher: dispatcher,
roomState: ROOM_STATES.INIT})
)
)
),
),
Section({name: "DesktopRoomConversationView"},
Example({summary: "Desktop room conversation", dashed: "true",
style: {width: "260px", height: "265px"}},
React.DOM.div({className: "fx-embedded"},
DesktopRoomConversationView({roomStore: roomStore})
DesktopRoomConversationView({
roomStore: roomStore,
dispatcher: dispatcher,
roomState: ROOM_STATES.HAS_PARTICIPANTS})
)
)
),

Просмотреть файл

@ -22,7 +22,6 @@
var DesktopPendingConversationView = loop.conversationViews.PendingConversationView;
var CallFailedView = loop.conversationViews.CallFailedView;
var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
var DesktopRoomInvitationView = loop.roomViews.DesktopRoomInvitationView;
// 2. Standalone webapp
var HomeView = loop.webapp.HomeView;
@ -39,6 +38,9 @@
var ConversationView = loop.shared.views.ConversationView;
var FeedbackView = loop.shared.views.FeedbackView;
// Room constants
var ROOM_STATES = loop.store.ROOM_STATES;
// Local helpers
function returnTrue() {
return true;
@ -533,20 +535,24 @@
</Example>
</Section>
<Section name="DesktopRoomInvitationView">
<Example summary="Desktop room invitation" dashed="true"
<Section name="DesktopRoomConversationView">
<Example summary="Desktop room conversation (invitation)" dashed="true"
style={{width: "260px", height: "265px"}}>
<div className="fx-embedded">
<DesktopRoomInvitationView roomStore={roomStore} />
<DesktopRoomConversationView
roomStore={roomStore}
dispatcher={dispatcher}
roomState={ROOM_STATES.INIT} />
</div>
</Example>
</Section>
<Section name="DesktopRoomConversationView">
<Example summary="Desktop room conversation" dashed="true"
style={{width: "260px", height: "265px"}}>
<div className="fx-embedded">
<DesktopRoomConversationView roomStore={roomStore} />
<DesktopRoomConversationView
roomStore={roomStore}
dispatcher={dispatcher}
roomState={ROOM_STATES.HAS_PARTICIPANTS} />
</div>
</Example>
</Section>