Bug 1171940: move the context display into the chat area inside the Hello conversation window. r=Standard8

This commit is contained in:
Mike de Boer 2015-07-03 19:00:22 +02:00
parent 6c168f83cd
commit 06878cbdf4
11 changed files with 84 additions and 63 deletions

View File

@ -808,7 +808,8 @@ loop.roomViews = (function(mozL10n) {
React.createElement(sharedViews.chat.TextChatView, { React.createElement(sharedViews.chat.TextChatView, {
dispatcher: this.props.dispatcher, dispatcher: this.props.dispatcher,
showAlways: false, showAlways: false,
showRoomName: false}) showRoomName: false,
useDesktopPaths: true})
) )
); );
} }

View File

@ -808,7 +808,8 @@ loop.roomViews = (function(mozL10n) {
<sharedViews.chat.TextChatView <sharedViews.chat.TextChatView
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
showAlways={false} showAlways={false}
showRoomName={false} /> showRoomName={false}
useDesktopPaths={true} />
</div> </div>
); );
} }

View File

@ -100,12 +100,29 @@ loop.store.TextChatStore = (function() {
sentTimestamp: messageData.sentTimestamp, sentTimestamp: messageData.sentTimestamp,
receivedTimestamp: messageData.receivedTimestamp receivedTimestamp: messageData.receivedTimestamp
}; };
var newList = this._storeState.messageList.concat(message); var newList = [].concat(this._storeState.messageList);
var isContext = message.contentType === CHAT_CONTENT_TYPES.CONTEXT;
if (isContext) {
var contextUpdated = false;
for (var i = 0, l = newList.length; i < l; ++i) {
// Replace the current context message with the provided update.
if (newList[i].contentType === CHAT_CONTENT_TYPES.CONTEXT) {
newList[i] = message;
contextUpdated = true;
break;
}
}
if (!contextUpdated) {
newList.push(message);
}
} else {
newList.push(message);
}
this.setStoreState({ messageList: newList }); this.setStoreState({ messageList: newList });
// Notify MozLoopService if appropriate that a message has been appended // Notify MozLoopService if appropriate that a message has been appended
// and it should therefore check if we need a different sized window or not. // and it should therefore check if we need a different sized window or not.
if (type != CHAT_MESSAGE_TYPES.SPECIAL) { if (message.contentType != CHAT_CONTENT_TYPES.ROOM_NAME) {
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended")); window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
} }
}, },

View File

@ -68,7 +68,8 @@ loop.shared.views.chat = (function(mozL10n) {
mixins: [React.addons.PureRenderMixin], mixins: [React.addons.PureRenderMixin],
propTypes: { propTypes: {
message: React.PropTypes.string.isRequired message: React.PropTypes.string.isRequired,
useDesktopPaths: React.PropTypes.bool.isRequired
}, },
render: function() { render: function() {
@ -97,7 +98,8 @@ loop.shared.views.chat = (function(mozL10n) {
propTypes: { propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
useDesktopPaths: React.PropTypes.bool.isRequired
}, },
getInitialState: function() { getInitialState: function() {
@ -157,7 +159,12 @@ loop.shared.views.chat = (function(mozL10n) {
if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) { if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
switch (entry.contentType) { switch (entry.contentType) {
case CHAT_CONTENT_TYPES.ROOM_NAME: case CHAT_CONTENT_TYPES.ROOM_NAME:
return React.createElement(TextChatRoomName, {key: i, message: entry.message}); return (
React.createElement(TextChatRoomName, {
key: i,
message: entry.message,
useDesktopPaths: this.props.useDesktopPaths})
);
case CHAT_CONTENT_TYPES.CONTEXT: case CHAT_CONTENT_TYPES.CONTEXT:
return ( return (
React.createElement("div", {className: "context-url-view-wrapper", key: i}, React.createElement("div", {className: "context-url-view-wrapper", key: i},
@ -168,7 +175,7 @@ loop.shared.views.chat = (function(mozL10n) {
showContextTitle: true, showContextTitle: true,
thumbnail: entry.extraData.thumbnail, thumbnail: entry.extraData.thumbnail,
url: entry.extraData.location, url: entry.extraData.location,
useDesktopPaths: false}) useDesktopPaths: this.props.useDesktopPaths})
) )
); );
default: default:
@ -334,11 +341,8 @@ loop.shared.views.chat = (function(mozL10n) {
* as a field for entering new messages. * as a field for entering new messages.
* *
* @property {loop.Dispatcher} dispatcher * @property {loop.Dispatcher} dispatcher
* @property {Boolean} showAlways If false, the view will not be rendered * @property {Boolean} showRoomName Set to true to show the room name
* if text chat is not enabled and the * special list item.
* message list is empty.
* @property {Boolean} showRoomName Set to true to show the room name special
* list item.
*/ */
var TextChatView = React.createClass({displayName: "TextChatView", var TextChatView = React.createClass({displayName: "TextChatView",
mixins: [ mixins: [
@ -348,8 +352,8 @@ loop.shared.views.chat = (function(mozL10n) {
propTypes: { propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
showAlways: React.PropTypes.bool.isRequired, showRoomName: React.PropTypes.bool.isRequired,
showRoomName: React.PropTypes.bool.isRequired useDesktopPaths: React.PropTypes.bool.isRequired
}, },
getInitialState: function() { getInitialState: function() {
@ -366,14 +370,14 @@ loop.shared.views.chat = (function(mozL10n) {
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL; return item.type !== CHAT_MESSAGE_TYPES.SPECIAL;
}); });
} else { } else {
// XXX Desktop should be showing the initial context here (bug 1171940).
messageList = this.state.messageList.filter(function(item) { messageList = this.state.messageList.filter(function(item) {
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL; return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
}); });
hasNonSpecialMessages = !!messageList.length; hasNonSpecialMessages = !!messageList.length;
} }
if (!this.props.showAlways && !this.state.textChatEnabled && !messageList.length) { if (!this.state.textChatEnabled && !messageList.length) {
return null; return null;
} }
@ -386,7 +390,8 @@ loop.shared.views.chat = (function(mozL10n) {
React.createElement("div", {className: textChatViewClasses}, React.createElement("div", {className: textChatViewClasses},
React.createElement(TextChatEntriesView, { React.createElement(TextChatEntriesView, {
dispatcher: this.props.dispatcher, dispatcher: this.props.dispatcher,
messageList: messageList}), messageList: messageList,
useDesktopPaths: this.props.useDesktopPaths}),
React.createElement(TextChatInputView, { React.createElement(TextChatInputView, {
dispatcher: this.props.dispatcher, dispatcher: this.props.dispatcher,
showPlaceholder: !hasNonSpecialMessages, showPlaceholder: !hasNonSpecialMessages,

View File

@ -68,7 +68,8 @@ loop.shared.views.chat = (function(mozL10n) {
mixins: [React.addons.PureRenderMixin], mixins: [React.addons.PureRenderMixin],
propTypes: { propTypes: {
message: React.PropTypes.string.isRequired message: React.PropTypes.string.isRequired,
useDesktopPaths: React.PropTypes.bool.isRequired
}, },
render: function() { render: function() {
@ -97,7 +98,8 @@ loop.shared.views.chat = (function(mozL10n) {
propTypes: { propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
useDesktopPaths: React.PropTypes.bool.isRequired
}, },
getInitialState: function() { getInitialState: function() {
@ -157,7 +159,12 @@ loop.shared.views.chat = (function(mozL10n) {
if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) { if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
switch (entry.contentType) { switch (entry.contentType) {
case CHAT_CONTENT_TYPES.ROOM_NAME: case CHAT_CONTENT_TYPES.ROOM_NAME:
return <TextChatRoomName key={i} message={entry.message}/>; return (
<TextChatRoomName
key={i}
message={entry.message}
useDesktopPaths={this.props.useDesktopPaths} />
);
case CHAT_CONTENT_TYPES.CONTEXT: case CHAT_CONTENT_TYPES.CONTEXT:
return ( return (
<div className="context-url-view-wrapper" key={i}> <div className="context-url-view-wrapper" key={i}>
@ -168,7 +175,7 @@ loop.shared.views.chat = (function(mozL10n) {
showContextTitle={true} showContextTitle={true}
thumbnail={entry.extraData.thumbnail} thumbnail={entry.extraData.thumbnail}
url={entry.extraData.location} url={entry.extraData.location}
useDesktopPaths={false} /> useDesktopPaths={this.props.useDesktopPaths} />
</div> </div>
); );
default: default:
@ -334,11 +341,8 @@ loop.shared.views.chat = (function(mozL10n) {
* as a field for entering new messages. * as a field for entering new messages.
* *
* @property {loop.Dispatcher} dispatcher * @property {loop.Dispatcher} dispatcher
* @property {Boolean} showAlways If false, the view will not be rendered * @property {Boolean} showRoomName Set to true to show the room name
* if text chat is not enabled and the * special list item.
* message list is empty.
* @property {Boolean} showRoomName Set to true to show the room name special
* list item.
*/ */
var TextChatView = React.createClass({ var TextChatView = React.createClass({
mixins: [ mixins: [
@ -348,8 +352,8 @@ loop.shared.views.chat = (function(mozL10n) {
propTypes: { propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired, dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
showAlways: React.PropTypes.bool.isRequired, showRoomName: React.PropTypes.bool.isRequired,
showRoomName: React.PropTypes.bool.isRequired useDesktopPaths: React.PropTypes.bool.isRequired
}, },
getInitialState: function() { getInitialState: function() {
@ -366,14 +370,14 @@ loop.shared.views.chat = (function(mozL10n) {
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL; return item.type !== CHAT_MESSAGE_TYPES.SPECIAL;
}); });
} else { } else {
// XXX Desktop should be showing the initial context here (bug 1171940).
messageList = this.state.messageList.filter(function(item) { messageList = this.state.messageList.filter(function(item) {
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL; return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
}); });
hasNonSpecialMessages = !!messageList.length; hasNonSpecialMessages = !!messageList.length;
} }
if (!this.props.showAlways && !this.state.textChatEnabled && !messageList.length) { if (!this.state.textChatEnabled && !messageList.length) {
return null; return null;
} }
@ -386,7 +390,8 @@ loop.shared.views.chat = (function(mozL10n) {
<div className={textChatViewClasses}> <div className={textChatViewClasses}>
<TextChatEntriesView <TextChatEntriesView
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
messageList={messageList} /> messageList={messageList}
useDesktopPaths={this.props.useDesktopPaths} />
<TextChatInputView <TextChatInputView
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
showPlaceholder={!hasNonSpecialMessages} showPlaceholder={!hasNonSpecialMessages}

View File

@ -890,7 +890,10 @@ let MozLoopServiceInternal = {
// When the chat box or messages are shown, resize the panel or window // When the chat box or messages are shown, resize the panel or window
// to be slightly higher to accomodate them. // to be slightly higher to accomodate them.
let customSize = kSizeMap[ev.type]; let customSize = kSizeMap[ev.type];
if (customSize) { let currSize = chatbox.getAttribute("customSize");
// If the size is already at the requested one or at the maximum size
// already, don't do anything. Especially don't make it shrink.
if (customSize && currSize != customSize && currSize != "loopChatMessageAppended") {
chatbox.setAttribute("customSize", customSize); chatbox.setAttribute("customSize", customSize);
chatbox.parentNode.setAttribute("customSize", customSize); chatbox.parentNode.setAttribute("customSize", customSize);
} }

View File

@ -464,7 +464,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
React.createElement(sharedViews.chat.TextChatView, { React.createElement(sharedViews.chat.TextChatView, {
dispatcher: this.props.dispatcher, dispatcher: this.props.dispatcher,
showAlways: true, showAlways: true,
showRoomName: true}), showRoomName: true,
useDesktopPaths: false}),
React.createElement("div", {className: "local"}, React.createElement("div", {className: "local"},
React.createElement(sharedViews.MediaView, {displayAvatar: this.state.videoMuted, React.createElement(sharedViews.MediaView, {displayAvatar: this.state.videoMuted,
isLoading: this._shouldRenderLocalLoading(), isLoading: this._shouldRenderLocalLoading(),

View File

@ -464,7 +464,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
<sharedViews.chat.TextChatView <sharedViews.chat.TextChatView
dispatcher={this.props.dispatcher} dispatcher={this.props.dispatcher}
showAlways={true} showAlways={true}
showRoomName={true} /> showRoomName={true}
useDesktopPaths={false} />
<div className="local"> <div className="local">
<sharedViews.MediaView displayAvatar={this.state.videoMuted} <sharedViews.MediaView displayAvatar={this.state.videoMuted}
isLoading={this._shouldRenderLocalLoading()} isLoading={this._shouldRenderLocalLoading()}

View File

@ -249,7 +249,8 @@ describe("loop.shared.views.TextChatView", function () {
function mountTestComponent(extraProps) { function mountTestComponent(extraProps) {
var props = _.extend({ var props = _.extend({
dispatcher: dispatcher dispatcher: dispatcher,
useDesktopPaths: false
}, extraProps); }, extraProps);
return TestUtils.renderIntoDocument( return TestUtils.renderIntoDocument(
React.createElement(loop.shared.views.chat.TextChatView, props)); React.createElement(loop.shared.views.chat.TextChatView, props));
@ -288,30 +289,16 @@ describe("loop.shared.views.TextChatView", function () {
.to.eql(2); .to.eql(2);
}); });
it("should not display anything if no messages and text chat not enabled and showAlways is false", function() { it("should display the view if no messages and text chat not enabled", function() {
store.setStoreState({ textChatEnabled: false }); store.setStoreState({ textChatEnabled: false });
view = mountTestComponent({ view = mountTestComponent();
showAlways: false
});
expect(view.getDOMNode()).eql(null);
});
it("should display the view if no messages and text chat not enabled and showAlways is true", function() {
store.setStoreState({ textChatEnabled: false });
view = mountTestComponent({
showAlways: true
});
expect(view.getDOMNode()).not.eql(null); expect(view.getDOMNode()).not.eql(null);
}); });
it("should display the view if text chat is enabled", function() { it("should display the view if text chat is enabled", function() {
view = mountTestComponent({ view = mountTestComponent();
showAlways: true
});
expect(view.getDOMNode()).not.eql(null); expect(view.getDOMNode()).not.eql(null);
}); });

View File

@ -1243,8 +1243,8 @@
width: 298}, width: 298},
React.createElement("div", {className: "fx-embedded"}, React.createElement("div", {className: "fx-embedded"},
React.createElement(TextChatView, {dispatcher: dispatcher, React.createElement(TextChatView, {dispatcher: dispatcher,
showAlways: false, showRoomName: false,
showRoomName: false}) useDesktopPaths: false})
) )
), ),
@ -1257,8 +1257,8 @@
React.createElement("div", {className: "media-wrapper"}, React.createElement("div", {className: "media-wrapper"},
React.createElement(TextChatView, { React.createElement(TextChatView, {
dispatcher: dispatcher, dispatcher: dispatcher,
showAlways: true, showRoomName: true,
showRoomName: true}) useDesktopPaths: false})
) )
) )
) )

View File

@ -1243,8 +1243,8 @@
width={298}> width={298}>
<div className="fx-embedded"> <div className="fx-embedded">
<TextChatView dispatcher={dispatcher} <TextChatView dispatcher={dispatcher}
showAlways={false} showRoomName={false}
showRoomName={false} /> useDesktopPaths={false} />
</div> </div>
</FramedExample> </FramedExample>
@ -1257,8 +1257,8 @@
<div className="media-wrapper"> <div className="media-wrapper">
<TextChatView <TextChatView
dispatcher={dispatcher} dispatcher={dispatcher}
showAlways={true} showRoomName={true}
showRoomName={true} /> useDesktopPaths={false} />
</div> </div>
</div> </div>
</FramedExample> </FramedExample>