mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1213848 - Change the Loop panel display when a user enters their own room to stop them entering other rooms [r=mikedeboer]
This commit is contained in:
parent
3c0a8b29d1
commit
ae84db17ab
@ -209,6 +209,16 @@ body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.new-room-view > .stop-sharing-button {
|
||||
background-color: #d13f1a;
|
||||
border-color: #d13f1a;
|
||||
}
|
||||
|
||||
.new-room-view > .stop-sharing-button:hover {
|
||||
background-color: #ef6745;
|
||||
border-color: #ef6745;
|
||||
}
|
||||
|
||||
.room-list {
|
||||
/* xxx not sure why flex needs the 3 value setting
|
||||
but setting flex to just 1, the whole tab including the new room is scrollable.
|
||||
|
@ -691,6 +691,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
_renderNewRoomButton: function() {
|
||||
return (
|
||||
React.createElement(NewRoomView, {dispatcher: this.props.dispatcher,
|
||||
inRoom: this.state.openedRoom !== null,
|
||||
mozLoop: this.props.mozLoop,
|
||||
pendingOperation: this.state.pendingCreation ||
|
||||
this.state.pendingInitialRetrieval})
|
||||
@ -737,6 +738,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
var NewRoomView = React.createClass({displayName: "NewRoomView",
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
inRoom: React.PropTypes.bool.isRequired,
|
||||
mozLoop: React.PropTypes.object.isRequired,
|
||||
pendingOperation: React.PropTypes.bool.isRequired
|
||||
},
|
||||
@ -791,13 +793,23 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.props.dispatcher.dispatch(createRoomAction);
|
||||
},
|
||||
|
||||
handleStopSharingButtonClick: function() {
|
||||
this.props.mozLoop.hangupAllChatWindows();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
React.createElement("div", {className: "new-room-view"},
|
||||
this.props.inRoom ?
|
||||
React.createElement("button", {className: "btn btn-info stop-sharing-button",
|
||||
disabled: this.props.pendingOperation,
|
||||
onClick: this.handleStopSharingButtonClick},
|
||||
mozL10n.get("panel_stop_sharing_tabs_button")
|
||||
) :
|
||||
React.createElement("button", {className: "btn btn-info new-room-button",
|
||||
disabled: this.props.pendingOperation,
|
||||
onClick: this.handleCreateButtonClick},
|
||||
mozL10n.get("rooms_new_room_button_label")
|
||||
mozL10n.get("panel_browse_with_friend_button")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -691,6 +691,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
_renderNewRoomButton: function() {
|
||||
return (
|
||||
<NewRoomView dispatcher={this.props.dispatcher}
|
||||
inRoom={this.state.openedRoom !== null}
|
||||
mozLoop={this.props.mozLoop}
|
||||
pendingOperation={this.state.pendingCreation ||
|
||||
this.state.pendingInitialRetrieval} />
|
||||
@ -737,6 +738,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
var NewRoomView = React.createClass({
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
inRoom: React.PropTypes.bool.isRequired,
|
||||
mozLoop: React.PropTypes.object.isRequired,
|
||||
pendingOperation: React.PropTypes.bool.isRequired
|
||||
},
|
||||
@ -791,14 +793,24 @@ loop.panel = (function(_, mozL10n) {
|
||||
this.props.dispatcher.dispatch(createRoomAction);
|
||||
},
|
||||
|
||||
handleStopSharingButtonClick: function() {
|
||||
this.props.mozLoop.hangupAllChatWindows();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div className="new-room-view">
|
||||
{this.props.inRoom ?
|
||||
<button className="btn btn-info stop-sharing-button"
|
||||
disabled={this.props.pendingOperation}
|
||||
onClick={this.handleStopSharingButtonClick}>
|
||||
{mozL10n.get("panel_stop_sharing_tabs_button")}
|
||||
</button> :
|
||||
<button className="btn btn-info new-room-button"
|
||||
disabled={this.props.pendingOperation}
|
||||
onClick={this.handleCreateButtonClick}>
|
||||
{mozL10n.get("rooms_new_room_button_label")}
|
||||
</button>
|
||||
{mozL10n.get("panel_browse_with_friend_button")}
|
||||
</button>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ loop.store = loop.store || {};
|
||||
return {
|
||||
activeRoom: this.activeRoomStore ? this.activeRoomStore.getStoreState() : {},
|
||||
error: null,
|
||||
openedRoom: null,
|
||||
pendingCreation: false,
|
||||
pendingInitialRetrieval: true,
|
||||
rooms: [],
|
||||
@ -126,6 +127,8 @@ loop.store = loop.store || {};
|
||||
startListeningToRoomEvents: function() {
|
||||
// Rooms event registration
|
||||
this._mozLoop.rooms.on("add", this._onRoomAdded.bind(this));
|
||||
this._mozLoop.rooms.on("close", this._onRoomClose.bind(this));
|
||||
this._mozLoop.rooms.on("open", this._onRoomOpen.bind(this));
|
||||
this._mozLoop.rooms.on("update", this._onRoomUpdated.bind(this));
|
||||
this._mozLoop.rooms.on("delete", this._onRoomRemoved.bind(this));
|
||||
this._mozLoop.rooms.on("refresh", this._onRoomsRefresh.bind(this));
|
||||
@ -155,6 +158,27 @@ loop.store = loop.store || {};
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the current active room.
|
||||
*/
|
||||
_onRoomClose: function() {
|
||||
this.setStoreState({
|
||||
openedRoom: null
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the current active room.
|
||||
*
|
||||
* @param {String} eventName The event name (unused).
|
||||
* @param {String} roomToken Identifier of the room.
|
||||
*/
|
||||
_onRoomOpen: function(eventName, roomToken) {
|
||||
this.setStoreState({
|
||||
openedRoom: roomToken
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Executed when a room is updated.
|
||||
*
|
||||
|
@ -713,7 +713,11 @@ var LoopRoomsInternal = {
|
||||
type: "room"
|
||||
};
|
||||
|
||||
MozLoopService.openChatWindow(windowData);
|
||||
eventEmitter.emit("open", roomToken);
|
||||
|
||||
MozLoopService.openChatWindow(windowData, () => {
|
||||
eventEmitter.emit("close");
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -550,6 +550,17 @@ function injectLoopAPI(targetWindow) {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Hangup and close all chat windows that are open.
|
||||
*/
|
||||
hangupAllChatWindows: {
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value() {
|
||||
MozLoopService.hangupAllChatWindows();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts alerting the user about an incoming call
|
||||
*/
|
||||
|
@ -874,6 +874,17 @@ var MozLoopServiceInternal = {
|
||||
return "about:loopconversation#" + chatWindowId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hangup and close all chat windows that are open.
|
||||
*/
|
||||
hangupAllChatWindows() {
|
||||
let isLoopURL = ({ src }) => /^about:loopconversation#/.test(src);
|
||||
[...Chat.chatboxes].filter(isLoopURL).forEach(chatbox => {
|
||||
let window = chatbox.content.contentWindow;
|
||||
window.dispatchEvent(new window.CustomEvent("LoopHangupNow"));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if a chat window is already open for a given window id.
|
||||
*
|
||||
@ -895,10 +906,12 @@ var MozLoopServiceInternal = {
|
||||
*
|
||||
* @param {Object} conversationWindowData The data to be obtained by the
|
||||
* window when it opens.
|
||||
* @param {Function} windowCloseCallback Callback function that's invoked
|
||||
* when the window closes.
|
||||
* @returns {Number} The id of the window, null if a window could not
|
||||
* be opened.
|
||||
*/
|
||||
openChatWindow: function(conversationWindowData) {
|
||||
openChatWindow: function(conversationWindowData, windowCloseCallback) {
|
||||
// So I guess the origin is the loop server!?
|
||||
let origin = this.loopServerUri;
|
||||
let windowId = this.getChatWindowID(conversationWindowData);
|
||||
@ -937,6 +950,8 @@ var MozLoopServiceInternal = {
|
||||
// we can keep using it here.
|
||||
let ref = chatbar.chatboxForURL.get(chatbox.src);
|
||||
chatbox = ref && ref.get() || chatbox;
|
||||
} else if (eventName == "Loop:ChatWindowClosed") {
|
||||
windowCloseCallback();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1386,15 +1401,24 @@ this.MozLoopService = {
|
||||
yield completedPromise;
|
||||
}),
|
||||
|
||||
/**
|
||||
* Hangup and close all chat windows that are open.
|
||||
*/
|
||||
hangupAllChatWindows() {
|
||||
return MozLoopServiceInternal.hangupAllChatWindows();
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the chat window
|
||||
*
|
||||
* @param {Object} conversationWindowData The data to be obtained by the
|
||||
* window when it opens.
|
||||
* @param {Function} windowCloseCallback Callback for when the window closes.
|
||||
* @returns {Number} The id of the window.
|
||||
*/
|
||||
openChatWindow: function(conversationWindowData) {
|
||||
return MozLoopServiceInternal.openChatWindow(conversationWindowData);
|
||||
openChatWindow: function(conversationWindowData, windowCloseCallback) {
|
||||
return MozLoopServiceInternal.openChatWindow(conversationWindowData,
|
||||
windowCloseCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,6 @@ rooms_default_room_name_template=Conversation {{conversationLabel}}
|
||||
## by the user specified conversation name.
|
||||
rooms_welcome_title=Welcome to {{conversationName}}
|
||||
rooms_leave_button_label=Leave
|
||||
rooms_new_room_button_label=Start a conversation
|
||||
rooms_only_occupant_label2=You're the only one here.
|
||||
rooms_panel_title=Choose a conversation or start a new one
|
||||
rooms_room_full_label=There are already two people in this conversation.
|
||||
|
@ -64,6 +64,7 @@ describe("loop.panel", function() {
|
||||
},
|
||||
confirm: sandbox.stub(),
|
||||
hasEncryptionKey: true,
|
||||
hangupAllChatWindows: function() {},
|
||||
logInToFxA: sandbox.stub(),
|
||||
logOutFromFxA: sandbox.stub(),
|
||||
notifyUITour: sandbox.stub(),
|
||||
@ -853,14 +854,13 @@ describe("loop.panel", function() {
|
||||
dispatch = sandbox.stub(dispatcher, "dispatch");
|
||||
});
|
||||
|
||||
function createTestComponent(pendingOperation) {
|
||||
function createTestComponent(extraProps) {
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(loop.panel.NewRoomView, {
|
||||
React.createElement(loop.panel.NewRoomView, _.extend({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: fakeMozLoop,
|
||||
pendingOperation: pendingOperation,
|
||||
userDisplayName: fakeEmail
|
||||
}));
|
||||
}, extraProps)));
|
||||
}
|
||||
|
||||
it("should dispatch a CreateRoom action with context when clicking on the " +
|
||||
@ -876,7 +876,10 @@ describe("loop.panel", function() {
|
||||
});
|
||||
};
|
||||
|
||||
var view = createTestComponent(false);
|
||||
var view = createTestComponent({
|
||||
inRoom: false,
|
||||
pendingOperation: false
|
||||
});
|
||||
|
||||
// Simulate being visible
|
||||
view.onDocumentVisible();
|
||||
@ -897,11 +900,48 @@ describe("loop.panel", function() {
|
||||
|
||||
it("should disable the create button when pendingOperation is true",
|
||||
function() {
|
||||
var view = createTestComponent(true);
|
||||
var view = createTestComponent({
|
||||
inRoom: false,
|
||||
pendingOperation: true
|
||||
});
|
||||
|
||||
var buttonNode = view.getDOMNode().querySelector(".new-room-button[disabled]");
|
||||
expect(buttonNode).to.not.equal(null);
|
||||
});
|
||||
|
||||
it("should not have a create button when inRoom is true", function() {
|
||||
var view = createTestComponent({
|
||||
inRoom: true,
|
||||
pendingOperation: false
|
||||
});
|
||||
|
||||
var buttonNode = view.getDOMNode().querySelector(".new-room-button");
|
||||
expect(buttonNode).to.equal(null);
|
||||
});
|
||||
|
||||
it("should have a stop sharing button when inRoom is true", function() {
|
||||
var view = createTestComponent({
|
||||
inRoom: true,
|
||||
pendingOperation: false
|
||||
});
|
||||
|
||||
var buttonNode = view.getDOMNode().querySelector(".stop-sharing-button");
|
||||
expect(buttonNode).to.not.equal(null);
|
||||
});
|
||||
|
||||
it("should hangup any window when stop sharing is clicked", function() {
|
||||
var hangupAllChatWindows = sandbox.stub(fakeMozLoop, "hangupAllChatWindows");
|
||||
|
||||
var view = createTestComponent({
|
||||
inRoom: true,
|
||||
pendingOperation: false
|
||||
});
|
||||
|
||||
var node = view.getDOMNode();
|
||||
TestUtils.Simulate.click(node.querySelector(".stop-sharing-button"));
|
||||
|
||||
sinon.assert.calledOnce(hangupAllChatWindows);
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.SignInRequestView", function() {
|
||||
|
@ -157,6 +157,23 @@ describe("loop.store.RoomStore", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("close", function() {
|
||||
it("should update the openedRoom state to null", function() {
|
||||
store.setStoreState({ openedRoom: "fake1234" });
|
||||
fakeMozLoop.rooms.trigger("close", "close");
|
||||
|
||||
expect(store.getStoreState().openedRoom).to.eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("open", function() {
|
||||
it("should update the openedRoom state to the room token", function() {
|
||||
fakeMozLoop.rooms.trigger("open", "open", "fake1234");
|
||||
|
||||
expect(store.getStoreState().openedRoom).to.eql("fake1234");
|
||||
});
|
||||
});
|
||||
|
||||
describe("update", function() {
|
||||
it("should update a room entry", function() {
|
||||
fakeMozLoop.rooms.trigger("update", "update", {
|
||||
|
@ -17,6 +17,7 @@ skip-if = e10s
|
||||
[browser_loop_fxa_server.js]
|
||||
[browser_LoopRooms_channel.js]
|
||||
[browser_mozLoop_appVersionInfo.js]
|
||||
[browser_mozLoop_chat.js]
|
||||
[browser_mozLoop_context.js]
|
||||
[browser_mozLoop_prefs.js]
|
||||
[browser_mozLoop_doNotDisturb.js]
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* This file contains tests for various chat window helpers in MozLoopAPI.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const { Chat } = Cu.import("resource:///modules/Chat.jsm", {});
|
||||
function isAnyLoopChatOpen() {
|
||||
return [...Chat.chatboxes].some(({ src }) => /^about:loopconversation#/.test(src));
|
||||
}
|
||||
|
||||
add_task(loadLoopPanel);
|
||||
|
||||
add_task(function* test_mozLoop_nochat() {
|
||||
Assert.ok(!isAnyLoopChatOpen(), "there should be no chat windows yet");
|
||||
});
|
||||
|
||||
add_task(function* test_mozLoop_openchat() {
|
||||
let windowData = {
|
||||
roomToken: "fake1234",
|
||||
type: "room"
|
||||
};
|
||||
|
||||
LoopRooms.open(windowData);
|
||||
Assert.ok(isAnyLoopChatOpen(), "chat window should have been opened");
|
||||
});
|
||||
|
||||
add_task(function* test_mozLoop_hangupAllChatWindows() {
|
||||
let windowData = {
|
||||
roomToken: "fake2345",
|
||||
type: "room"
|
||||
};
|
||||
|
||||
LoopRooms.open(windowData);
|
||||
|
||||
yield promiseWaitForCondition(() => {
|
||||
gMozLoopAPI.hangupAllChatWindows();
|
||||
return !isAnyLoopChatOpen();
|
||||
});
|
||||
|
||||
Assert.ok(!isAnyLoopChatOpen(), "chat window should have been closed");
|
||||
});
|
@ -96,9 +96,9 @@ function waitForCondition(condition, nextTest, errorMsg) {
|
||||
}
|
||||
|
||||
function promiseWaitForCondition(aConditionFn) {
|
||||
let deferred = Promise.defer();
|
||||
waitForCondition(aConditionFn, deferred.resolve, "Condition didn't pass.");
|
||||
return deferred.promise;
|
||||
return new Promise((resolve, reject) => {
|
||||
waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,6 +397,17 @@
|
||||
callback(null, []);
|
||||
};
|
||||
|
||||
var roomStoreOpenedRoom = new loop.store.RoomStore(dispatcher, {
|
||||
mozLoop: navigator.mozLoop,
|
||||
activeRoomStore: makeActiveRoomStore({
|
||||
roomState: ROOM_STATES.HAS_PARTICIPANTS
|
||||
})
|
||||
});
|
||||
|
||||
roomStoreOpenedRoom.setStoreState({
|
||||
openedRoom: "3jKS_Els9IU"
|
||||
});
|
||||
|
||||
var roomStoreNoRooms = new loop.store.RoomStore(new loop.Dispatcher(), {
|
||||
mozLoop: mockMozLoopNoRooms,
|
||||
activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
|
||||
@ -690,6 +701,20 @@
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
summary: "Room list (active view)",
|
||||
width: 330},
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(PanelView, {client: mockClient,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop,
|
||||
notifications: notifications,
|
||||
roomStore: roomStoreOpenedRoom})
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement(FramedExample, {cssClass: "fx-embedded-panel",
|
||||
dashed: true,
|
||||
height: 410,
|
||||
|
@ -397,6 +397,17 @@
|
||||
callback(null, []);
|
||||
};
|
||||
|
||||
var roomStoreOpenedRoom = new loop.store.RoomStore(dispatcher, {
|
||||
mozLoop: navigator.mozLoop,
|
||||
activeRoomStore: makeActiveRoomStore({
|
||||
roomState: ROOM_STATES.HAS_PARTICIPANTS
|
||||
})
|
||||
});
|
||||
|
||||
roomStoreOpenedRoom.setStoreState({
|
||||
openedRoom: "3jKS_Els9IU"
|
||||
});
|
||||
|
||||
var roomStoreNoRooms = new loop.store.RoomStore(new loop.Dispatcher(), {
|
||||
mozLoop: mockMozLoopNoRooms,
|
||||
activeRoomStore: new loop.store.ActiveRoomStore(new loop.Dispatcher(), {
|
||||
@ -690,6 +701,20 @@
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
summary="Room list (active view)"
|
||||
width={330}>
|
||||
<div className="panel">
|
||||
<PanelView client={mockClient}
|
||||
dispatcher={dispatcher}
|
||||
mozLoop={navigator.mozLoop}
|
||||
notifications={notifications}
|
||||
roomStore={roomStoreOpenedRoom} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
||||
<FramedExample cssClass="fx-embedded-panel"
|
||||
dashed={true}
|
||||
height={410}
|
||||
|
@ -22,6 +22,9 @@ sign_in_again_button=Sign In
|
||||
## will be replaced by the super short brandname.
|
||||
sign_in_again_use_as_guest_button2=Use {{clientSuperShortname}} as a Guest
|
||||
|
||||
panel_browse_with_friend_button=Browse this page with a friend
|
||||
panel_stop_sharing_tabs_button=Stop sharing your tabs
|
||||
|
||||
first_time_experience_button_label=Get Started
|
||||
## LOCALIZATION_NOTE(first_time_experience_subheading): Message inviting the
|
||||
## user to create his or her first conversation.
|
||||
@ -184,7 +187,6 @@ rooms_leave_button_label=Leave
|
||||
## for emphasis reasons, it is a heading. Proceed as appropriate for locale.
|
||||
rooms_list_recent_conversations=RECENT CONVERSATIONS
|
||||
rooms_change_failed_label=Conversation cannot be updated
|
||||
rooms_new_room_button_label=Start a conversation
|
||||
rooms_panel_title=Choose a conversation or start a new one
|
||||
rooms_room_full_label=There are already two people in this conversation.
|
||||
rooms_room_full_call_to_action_nonFx_label=Download {{brandShortname}} to start your own
|
||||
|
Loading…
Reference in New Issue
Block a user