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

View File

@ -72,6 +72,7 @@ loop.store = loop.store || {};
if (options.activeRoomStore) {
this.activeRoomStore = options.activeRoomStore;
this.setStoreState({activeRoom: this.activeRoomStore.getStoreState()});
this.activeRoomStore.on("change",
this._onActiveRoomStoreChange.bind(this));
}
@ -82,6 +83,7 @@ loop.store = loop.store || {};
"copyRoomUrl",
"deleteRoom",
"deleteRoomError",
"emailRoomUrl",
"getAllRooms",
"getAllRoomsError",
"openRoom",
@ -326,6 +328,15 @@ loop.store = loop.store || {};
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.
*

View File

@ -58,7 +58,7 @@ describe("loop.roomViews", function () {
});
var testView = TestUtils.renderIntoDocument(TestView({
roomStore: activeRoomStore
roomStore: roomStore
}));
expect(testView.state).eql({
@ -75,7 +75,7 @@ describe("loop.roomViews", function () {
render: function() { return React.DOM.div(); }
});
var testView = TestUtils.renderIntoDocument(TestView({
roomStore: activeRoomStore
roomStore: roomStore
}));
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() {
var view;

View File

@ -19,6 +19,7 @@ describe("loop.store.RoomStore", function () {
"use strict";
var sharedActions = loop.shared.actions;
var sharedUtils = loop.shared.utils;
var sandbox, dispatcher;
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() {
it("should update store state data", function() {
store.setStoreState({pendingCreation: true});