Bug 1074696 - Allow the user to copy and email Loop room urls from the room preview. r=nperriault

This commit is contained in:
Mark Banner 2014-11-11 22:15:44 +00:00
parent 40ef701a45
commit ce7e3147b5
6 changed files with 136 additions and 13 deletions

View File

@ -48,10 +48,10 @@ loop.roomViews = (function(mozL10n) {
getInitialState: function() { getInitialState: function() {
var storeState = this.props.roomStore.getStoreState("activeRoom"); var storeState = this.props.roomStore.getStoreState("activeRoom");
return _.extend(storeState, { return _.extend({
// Used by the UI showcase. // Used by the UI showcase.
roomState: this.props.roomState || storeState.roomState roomState: this.props.roomState || storeState.roomState
}); }, storeState);
} }
}; };
@ -65,6 +65,12 @@ loop.roomViews = (function(mozL10n) {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
}, },
getInitialState: function() {
return {
copiedUrl: false
}
},
handleFormSubmit: function(event) { handleFormSubmit: function(event) {
event.preventDefault(); event.preventDefault();
// XXX // XXX
@ -72,12 +78,18 @@ loop.roomViews = (function(mozL10n) {
handleEmailButtonClick: function(event) { handleEmailButtonClick: function(event) {
event.preventDefault(); event.preventDefault();
// XXX
this.props.dispatcher.dispatch(
new sharedActions.EmailRoomUrl({roomUrl: this.state.roomUrl}));
}, },
handleCopyButtonClick: function(event) { handleCopyButtonClick: function(event) {
event.preventDefault(); event.preventDefault();
// XXX
this.props.dispatcher.dispatch(
new sharedActions.CopyRoomUrl({roomUrl: this.state.roomUrl}));
this.setState({copiedUrl: true});
}, },
render: function() { render: function() {
@ -95,7 +107,8 @@ loop.roomViews = (function(mozL10n) {
), ),
React.DOM.button({className: "btn btn-info btn-copy", React.DOM.button({className: "btn btn-info btn-copy",
onClick: this.handleCopyButtonClick}, onClick: this.handleCopyButtonClick},
mozL10n.get("copy_url_button2") this.state.copiedUrl ? mozL10n.get("copied_url_button") :
mozL10n.get("copy_url_button2")
) )
) )
) )

View File

@ -48,10 +48,10 @@ loop.roomViews = (function(mozL10n) {
getInitialState: function() { getInitialState: function() {
var storeState = this.props.roomStore.getStoreState("activeRoom"); var storeState = this.props.roomStore.getStoreState("activeRoom");
return _.extend(storeState, { return _.extend({
// Used by the UI showcase. // Used by the UI showcase.
roomState: this.props.roomState || storeState.roomState roomState: this.props.roomState || storeState.roomState
}); }, storeState);
} }
}; };
@ -65,6 +65,12 @@ loop.roomViews = (function(mozL10n) {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
}, },
getInitialState: function() {
return {
copiedUrl: false
}
},
handleFormSubmit: function(event) { handleFormSubmit: function(event) {
event.preventDefault(); event.preventDefault();
// XXX // XXX
@ -72,12 +78,18 @@ loop.roomViews = (function(mozL10n) {
handleEmailButtonClick: function(event) { handleEmailButtonClick: function(event) {
event.preventDefault(); event.preventDefault();
// XXX
this.props.dispatcher.dispatch(
new sharedActions.EmailRoomUrl({roomUrl: this.state.roomUrl}));
}, },
handleCopyButtonClick: function(event) { handleCopyButtonClick: function(event) {
event.preventDefault(); event.preventDefault();
// XXX
this.props.dispatcher.dispatch(
new sharedActions.CopyRoomUrl({roomUrl: this.state.roomUrl}));
this.setState({copiedUrl: true});
}, },
render: function() { render: function() {
@ -95,7 +107,8 @@ loop.roomViews = (function(mozL10n) {
</button> </button>
<button className="btn btn-info btn-copy" <button className="btn btn-info btn-copy"
onClick={this.handleCopyButtonClick}> onClick={this.handleCopyButtonClick}>
{mozL10n.get("copy_url_button2")} {this.state.copiedUrl ? mozL10n.get("copied_url_button") :
mozL10n.get("copy_url_button2")}
</button> </button>
</div> </div>
</div> </div>

View File

@ -243,13 +243,21 @@ loop.shared.actions = (function() {
}), }),
/** /**
* Copy a room url in the user's clipboard. * Copy a room url into the user's clipboard.
* XXX: should move to some roomActions module - refs bug 1079284 * XXX: should move to some roomActions module - refs bug 1079284
*/ */
CopyRoomUrl: Action.define("copyRoomUrl", { CopyRoomUrl: Action.define("copyRoomUrl", {
roomUrl: String roomUrl: String
}), }),
/**
* Email a room url.
* XXX: should move to some roomActions module - refs bug 1079284
*/
EmailRoomUrl: Action.define("emailRoomUrl", {
roomUrl: String
}),
/** /**
* XXX: should move to some roomActions module - refs bug 1079284 * XXX: should move to some roomActions module - refs bug 1079284
*/ */

View File

@ -72,6 +72,7 @@ loop.store = loop.store || {};
if (options.activeRoomStore) { if (options.activeRoomStore) {
this.activeRoomStore = options.activeRoomStore; this.activeRoomStore = options.activeRoomStore;
this.setStoreState({activeRoom: this.activeRoomStore.getStoreState()});
this.activeRoomStore.on("change", this.activeRoomStore.on("change",
this._onActiveRoomStoreChange.bind(this)); this._onActiveRoomStoreChange.bind(this));
} }
@ -82,6 +83,7 @@ loop.store = loop.store || {};
"copyRoomUrl", "copyRoomUrl",
"deleteRoom", "deleteRoom",
"deleteRoomError", "deleteRoomError",
"emailRoomUrl",
"getAllRooms", "getAllRooms",
"getAllRoomsError", "getAllRoomsError",
"openRoom", "openRoom",
@ -326,6 +328,15 @@ loop.store = loop.store || {};
this._mozLoop.copyString(actionData.roomUrl); this._mozLoop.copyString(actionData.roomUrl);
}, },
/**
* Emails a room url.
*
* @param {sharedActions.EmailRoomUrl} actionData The action data.
*/
emailRoomUrl: function(actionData) {
loop.shared.utils.composeCallUrlEmail(actionData.roomUrl);
},
/** /**
* Creates a new room. * Creates a new room.
* *

View File

@ -58,7 +58,7 @@ describe("loop.roomViews", function () {
}); });
var testView = TestUtils.renderIntoDocument(TestView({ var testView = TestUtils.renderIntoDocument(TestView({
roomStore: activeRoomStore roomStore: roomStore
})); }));
expect(testView.state).eql({ expect(testView.state).eql({
@ -75,7 +75,7 @@ describe("loop.roomViews", function () {
render: function() { return React.DOM.div(); } render: function() { return React.DOM.div(); }
}); });
var testView = TestUtils.renderIntoDocument(TestView({ var testView = TestUtils.renderIntoDocument(TestView({
roomStore: activeRoomStore roomStore: roomStore
})); }));
activeRoomStore.setStoreState({roomState: ROOM_STATES.READY}); activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
@ -84,6 +84,69 @@ describe("loop.roomViews", function () {
}); });
}); });
describe("DesktopRoomInvitationView", function() {
var view;
beforeEach(function() {
sandbox.stub(dispatcher, "dispatch");
});
afterEach(function() {
view = null;
});
function mountTestComponent() {
return TestUtils.renderIntoDocument(
new loop.roomViews.DesktopRoomInvitationView({
dispatcher: dispatcher,
roomStore: roomStore
}));
}
it("should dispatch an EmailRoomUrl action when the email button is " +
"pressed", function() {
view = mountTestComponent();
view.setState({roomUrl: "http://invalid"});
var emailBtn = view.getDOMNode().querySelector('.btn-email');
React.addons.TestUtils.Simulate.click(emailBtn);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.EmailRoomUrl({roomUrl: "http://invalid"}));
});
describe("Copy Button", function() {
beforeEach(function() {
view = mountTestComponent();
view.setState({roomUrl: "http://invalid"});
});
it("should dispatch a CopyRoomUrl action when the copy button is " +
"pressed", function() {
var copyBtn = view.getDOMNode().querySelector('.btn-copy');
React.addons.TestUtils.Simulate.click(copyBtn);
sinon.assert.calledOnce(dispatcher.dispatch);
sinon.assert.calledWith(dispatcher.dispatch,
new sharedActions.CopyRoomUrl({roomUrl: "http://invalid"}));
});
it("should change the text when the url has been copied", function() {
var copyBtn = view.getDOMNode().querySelector('.btn-copy');
React.addons.TestUtils.Simulate.click(copyBtn);
// copied_url_button is the l10n string.
expect(copyBtn.textContent).eql("copied_url_button");
});
});
});
describe("DesktopRoomConversationView", function() { describe("DesktopRoomConversationView", function() {
var view; var view;

View File

@ -19,6 +19,7 @@ describe("loop.store.RoomStore", function () {
"use strict"; "use strict";
var sharedActions = loop.shared.actions; var sharedActions = loop.shared.actions;
var sharedUtils = loop.shared.utils;
var sandbox, dispatcher; var sandbox, dispatcher;
var fakeRoomList = [{ var fakeRoomList = [{
@ -273,6 +274,20 @@ describe("loop.store.RoomStore", function () {
}); });
}); });
describe("#emailRoomUrl", function() {
it("should call composeCallUrlEmail to email the url", function() {
sandbox.stub(sharedUtils, "composeCallUrlEmail");
store.emailRoomUrl(new sharedActions.EmailRoomUrl({
roomUrl: "http://invalid"
}));
sinon.assert.calledOnce(sharedUtils.composeCallUrlEmail);
sinon.assert.calledWithExactly(sharedUtils.composeCallUrlEmail,
"http://invalid");
});
});
describe("#setStoreState", function() { describe("#setStoreState", function() {
it("should update store state data", function() { it("should update store state data", function() {
store.setStoreState({pendingCreation: true}); store.setStoreState({pendingCreation: true});