зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1184917 - Implement the refreshed design for 'Edit' conversation toolbar button. r=mdeboer
This commit is contained in:
Родитель
b4d9e4c989
Коммит
67e57121a1
|
@ -583,6 +583,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
// This is used from the props rather than the state to make it easier for
|
||||
// the ui-showcase.
|
||||
mediaConnected: React.PropTypes.bool,
|
||||
mozLoop: React.PropTypes.object,
|
||||
remotePosterUrl: React.PropTypes.string,
|
||||
remoteVideoEnabled: React.PropTypes.bool,
|
||||
// local
|
||||
|
@ -680,6 +681,16 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
render: function() {
|
||||
// 'visible' and 'enabled' are true by default.
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
visible: false,
|
||||
enabled: false
|
||||
},
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
return (
|
||||
React.createElement("div", {className: "desktop-call-wrapper"},
|
||||
React.createElement(sharedViews.MediaLayoutView, {
|
||||
|
@ -702,9 +713,10 @@ loop.conversationViews = (function(mozL10n) {
|
|||
React.createElement(loop.shared.views.ConversationToolbar, {
|
||||
audio: this.props.audio,
|
||||
dispatcher: this.props.dispatcher,
|
||||
edit: { visible: false, enabled: false},
|
||||
hangup: this.hangup,
|
||||
mozLoop: this.props.mozLoop,
|
||||
publishStream: this.publishStream,
|
||||
settingsMenuItems: settingsMenuItems,
|
||||
video: this.props.video})
|
||||
)
|
||||
)
|
||||
|
@ -807,6 +819,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
conversationStore: this.getStore(),
|
||||
dispatcher: this.props.dispatcher,
|
||||
mediaConnected: this.state.mediaConnected,
|
||||
mozLoop: this.props.mozLoop,
|
||||
remoteSrcVideoObject: this.state.remoteSrcVideoObject,
|
||||
remoteVideoEnabled: this.state.remoteVideoEnabled,
|
||||
video: { enabled: !this.state.videoMuted, visible: true}})
|
||||
|
|
|
@ -583,6 +583,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
// This is used from the props rather than the state to make it easier for
|
||||
// the ui-showcase.
|
||||
mediaConnected: React.PropTypes.bool,
|
||||
mozLoop: React.PropTypes.object,
|
||||
remotePosterUrl: React.PropTypes.string,
|
||||
remoteVideoEnabled: React.PropTypes.bool,
|
||||
// local
|
||||
|
@ -680,6 +681,16 @@ loop.conversationViews = (function(mozL10n) {
|
|||
},
|
||||
|
||||
render: function() {
|
||||
// 'visible' and 'enabled' are true by default.
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
visible: false,
|
||||
enabled: false
|
||||
},
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
return (
|
||||
<div className="desktop-call-wrapper">
|
||||
<sharedViews.MediaLayoutView
|
||||
|
@ -702,9 +713,10 @@ loop.conversationViews = (function(mozL10n) {
|
|||
<loop.shared.views.ConversationToolbar
|
||||
audio={this.props.audio}
|
||||
dispatcher={this.props.dispatcher}
|
||||
edit={{ visible: false, enabled: false }}
|
||||
hangup={this.hangup}
|
||||
mozLoop={this.props.mozLoop}
|
||||
publishStream={this.publishStream}
|
||||
settingsMenuItems={settingsMenuItems}
|
||||
video={this.props.video} />
|
||||
</sharedViews.MediaLayoutView>
|
||||
</div>
|
||||
|
@ -807,6 +819,7 @@ loop.conversationViews = (function(mozL10n) {
|
|||
conversationStore={this.getStore()}
|
||||
dispatcher={this.props.dispatcher}
|
||||
mediaConnected={this.state.mediaConnected}
|
||||
mozLoop={this.props.mozLoop}
|
||||
remoteSrcVideoObject={this.state.remoteSrcVideoObject}
|
||||
remoteVideoEnabled={this.state.remoteVideoEnabled}
|
||||
video={{ enabled: !this.state.videoMuted, visible: true }} />
|
||||
|
|
|
@ -724,6 +724,16 @@ loop.roomViews = (function(mozL10n) {
|
|||
return null;
|
||||
}
|
||||
default: {
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
enabled: !this.state.showEditContext,
|
||||
visible: this.state.contextEnabled,
|
||||
onClick: this.handleEditContextClick
|
||||
},
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
return (
|
||||
React.createElement("div", {className: "room-conversation-wrapper desktop-room-wrapper"},
|
||||
React.createElement(sharedViews.MediaLayoutView, {
|
||||
|
@ -746,11 +756,11 @@ loop.roomViews = (function(mozL10n) {
|
|||
React.createElement(sharedViews.ConversationToolbar, {
|
||||
audio: {enabled: !this.state.audioMuted, visible: true},
|
||||
dispatcher: this.props.dispatcher,
|
||||
edit: { visible: this.state.contextEnabled, enabled: !this.state.showEditContext},
|
||||
hangup: this.leaveRoom,
|
||||
onEditClick: this.handleEditContextClick,
|
||||
mozLoop: this.props.mozLoop,
|
||||
publishStream: this.publishStream,
|
||||
screenShare: screenShareData,
|
||||
settingsMenuItems: settingsMenuItems,
|
||||
video: {enabled: !this.state.videoMuted, visible: true}}),
|
||||
React.createElement(DesktopRoomInvitationView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
|
|
|
@ -724,6 +724,16 @@ loop.roomViews = (function(mozL10n) {
|
|||
return null;
|
||||
}
|
||||
default: {
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
enabled: !this.state.showEditContext,
|
||||
visible: this.state.contextEnabled,
|
||||
onClick: this.handleEditContextClick
|
||||
},
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
return (
|
||||
<div className="room-conversation-wrapper desktop-room-wrapper">
|
||||
<sharedViews.MediaLayoutView
|
||||
|
@ -746,11 +756,11 @@ loop.roomViews = (function(mozL10n) {
|
|||
<sharedViews.ConversationToolbar
|
||||
audio={{enabled: !this.state.audioMuted, visible: true}}
|
||||
dispatcher={this.props.dispatcher}
|
||||
edit={{ visible: this.state.contextEnabled, enabled: !this.state.showEditContext }}
|
||||
hangup={this.leaveRoom}
|
||||
onEditClick={this.handleEditContextClick}
|
||||
mozLoop={this.props.mozLoop}
|
||||
publishStream={this.publishStream}
|
||||
screenShare={screenShareData}
|
||||
settingsMenuItems={settingsMenuItems}
|
||||
video={{enabled: !this.state.videoMuted, visible: true}} />
|
||||
<DesktopRoomInvitationView
|
||||
dispatcher={this.props.dispatcher}
|
||||
|
|
|
@ -203,15 +203,15 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
|
|||
content: url("../img/svg/video-mute-hover.svg");
|
||||
}
|
||||
|
||||
.btn-mute-edit {
|
||||
.btn-settings {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-size: 28px;
|
||||
background-image: url("../img/svg/settings.svg");
|
||||
}
|
||||
|
||||
.btn-mute-edit:hover,
|
||||
.btn-mute-edit:active {
|
||||
.btn-settings:hover,
|
||||
.btn-settings:active {
|
||||
background-image: url("../img/svg/settings-hover.svg");
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
|
|||
background-image: url("../img/svg/sharing-hover.svg");
|
||||
}
|
||||
|
||||
.btn-mute-edit.muted,
|
||||
.btn-settings.muted,
|
||||
.btn-screen-share.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -385,6 +385,17 @@ html[dir="rtl"] .conversation-toolbar-btn-box.btn-edit-entry {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.settings-menu.dropdown-menu {
|
||||
left: auto;
|
||||
bottom: 3.1rem;
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .settings-menu.dropdown-menu {
|
||||
left: 14px;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
/* Expired call url page */
|
||||
|
||||
.expired-url-info {
|
||||
|
@ -1228,6 +1239,12 @@ html[dir="rtl"] .room-context-btn-close {
|
|||
height: 30%;
|
||||
}
|
||||
|
||||
.media-wrapper.receiving-screen-share > .remote > .conversation-toolbar,
|
||||
.media-wrapper.showing-local-streams.receiving-screen-share > .remote > .conversation-toolbar {
|
||||
bottom: calc(30% + 1.5rem);
|
||||
}
|
||||
|
||||
|
||||
.desktop-call-wrapper > .media-layout > .media-wrapper > .text-chat-view,
|
||||
.desktop-room-wrapper > .media-layout > .media-wrapper > .text-chat-view {
|
||||
/* This is temp, to echo the .media-wrapper > .text-chat-view above */
|
||||
|
|
|
@ -180,6 +180,146 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Settings control button.
|
||||
*/
|
||||
var SettingsControlButton = React.createClass({displayName: "SettingsControlButton",
|
||||
propTypes: {
|
||||
menuItems: React.PropTypes.array,
|
||||
mozLoop: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [
|
||||
sharedMixins.DropdownMenuMixin(),
|
||||
React.addons.PureRenderMixin
|
||||
],
|
||||
|
||||
/**
|
||||
* Show or hide the settings menu
|
||||
*/
|
||||
handleClick: function(event) {
|
||||
event.preventDefault();
|
||||
this.toggleDropdownMenu();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the function that Show or hide the edit context edition form
|
||||
*/
|
||||
getHandleToggleEdit: function(editItem) {
|
||||
return function _handleToglleEdit(event) {
|
||||
event.preventDefault();
|
||||
if (editItem.onClick) {
|
||||
editItem.onClick(!editItem.enabled);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Load on the browser the help (support) url from prefs
|
||||
*/
|
||||
handleHelpEntry: function(event) {
|
||||
event.preventDefault();
|
||||
var helloSupportUrl = this.props.mozLoop.getLoopPref("support_url");
|
||||
this.props.mozLoop.openURL(helloSupportUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load on the browser the feedback url from prefs
|
||||
*/
|
||||
handleSubmitFeedback: function(event) {
|
||||
event.preventDefault();
|
||||
var helloFeedbackUrl = this.props.mozLoop.getLoopPref("feedback.formURL");
|
||||
this.props.mozLoop.openURL(helloFeedbackUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Recover the needed info for generating an specific menu Item
|
||||
*/
|
||||
getItemInfo: function(menuItem) {
|
||||
var cx = React.addons.classSet;
|
||||
switch (menuItem.id) {
|
||||
case "feedback":
|
||||
return {
|
||||
cssClasses: "dropdown-menu-item",
|
||||
handler: this.handleSubmitFeedback,
|
||||
label: mozL10n.get("feedback_request_button")
|
||||
};
|
||||
case "help":
|
||||
return {
|
||||
cssClasses: "dropdown-menu-item",
|
||||
handler: this.handleHelpEntry,
|
||||
label: mozL10n.get("help_label")
|
||||
};
|
||||
case "edit":
|
||||
return {
|
||||
cssClasses: cx({
|
||||
"dropdown-menu-item": true,
|
||||
"entry-settings-edit": true,
|
||||
"hide": !menuItem.visible
|
||||
}),
|
||||
handler: this.getHandleToggleEdit(menuItem),
|
||||
label: mozL10n.get(menuItem.enabled ?
|
||||
"conversation_settings_menu_edit_context" :
|
||||
"conversation_settings_menu_hide_context"),
|
||||
scope: "local",
|
||||
type: "edit"
|
||||
};
|
||||
default:
|
||||
console.error("Invalid menu item", menuItem);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a menu item after recover its info
|
||||
*/
|
||||
generateMenuItem: function(menuItem) {
|
||||
var itemInfo = this.getItemInfo(menuItem);
|
||||
if (!itemInfo) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
React.createElement("li", {className: itemInfo.cssClasses,
|
||||
key: menuItem.id,
|
||||
onClick: itemInfo.handler,
|
||||
scope: itemInfo.scope || "",
|
||||
type: itemInfo.type || ""},
|
||||
itemInfo.label
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (!this.props.menuItems || !this.props.menuItems.length) {
|
||||
return null;
|
||||
}
|
||||
var menuItemRows = this.props.menuItems.map(this.generateMenuItem)
|
||||
.filter(function(item) { return item; });
|
||||
|
||||
if (!menuItemRows || !menuItemRows.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var cx = React.addons.classSet;
|
||||
var settingsDropdownMenuClasses = cx({
|
||||
"settings-menu": true,
|
||||
"dropdown-menu": true,
|
||||
"hide": !this.state.showMenu
|
||||
});
|
||||
return (
|
||||
React.createElement("div", null,
|
||||
React.createElement("button", {className: "btn btn-settings transparent-button",
|
||||
onClick: this.toggleDropdownMenu,
|
||||
ref: "menu-button",
|
||||
title: mozL10n.get("settings_menu_button_tooltip")}),
|
||||
React.createElement("ul", {className: settingsDropdownMenuClasses, ref: "menu"},
|
||||
menuItemRows
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Conversation controls.
|
||||
*/
|
||||
|
@ -188,8 +328,8 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
return {
|
||||
video: {enabled: true, visible: true},
|
||||
audio: {enabled: true, visible: true},
|
||||
edit: {enabled: false, visible: false},
|
||||
screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
|
||||
settingsMenuItems: null,
|
||||
enableHangup: true
|
||||
};
|
||||
},
|
||||
|
@ -203,13 +343,13 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
propTypes: {
|
||||
audio: React.PropTypes.object.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
edit: React.PropTypes.object.isRequired,
|
||||
enableHangup: React.PropTypes.bool,
|
||||
hangup: React.PropTypes.func.isRequired,
|
||||
hangupButtonLabel: React.PropTypes.string,
|
||||
onEditClick: React.PropTypes.func,
|
||||
mozLoop: React.PropTypes.object,
|
||||
publishStream: React.PropTypes.func.isRequired,
|
||||
screenShare: React.PropTypes.object,
|
||||
settingsMenuItems: React.PropTypes.array,
|
||||
video: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
|
@ -225,12 +365,6 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
this.props.publishStream("audio", !this.props.audio.enabled);
|
||||
},
|
||||
|
||||
handleToggleEdit: function() {
|
||||
if (this.props.onEditClick) {
|
||||
this.props.onEditClick(!this.props.edit.enabled);
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.userActivity = false;
|
||||
this.startIdleCountDown();
|
||||
|
@ -326,7 +460,6 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
enabled: this.props.audio.enabled,
|
||||
scope: "local", type: "audio",
|
||||
visible: this.props.audio.visible})
|
||||
|
||||
)
|
||||
),
|
||||
React.createElement("li", {className: "conversation-toolbar-btn-box"},
|
||||
|
@ -335,13 +468,8 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
visible: this.props.screenShare.visible})
|
||||
),
|
||||
React.createElement("li", {className: "conversation-toolbar-btn-box btn-edit-entry"},
|
||||
React.createElement(MediaControlButton, {action: this.handleToggleEdit,
|
||||
enabled: this.props.edit.enabled,
|
||||
scope: "local",
|
||||
title: mozL10n.get(this.props.edit.enabled ?
|
||||
"context_edit_tooltip" : "context_hide_tooltip"),
|
||||
type: "edit",
|
||||
visible: this.props.edit.visible})
|
||||
React.createElement(SettingsControlButton, {menuItems: this.props.settingsMenuItems,
|
||||
mozLoop: this.props.mozLoop})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -364,6 +492,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
initiate: React.PropTypes.bool,
|
||||
isDesktop: React.PropTypes.bool,
|
||||
model: React.PropTypes.object.isRequired,
|
||||
mozLoop: React.PropTypes.object,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
video: React.PropTypes.object
|
||||
},
|
||||
|
@ -559,6 +688,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
audio: this.state.audio,
|
||||
dispatcher: this.props.dispatcher,
|
||||
hangup: this.hangup,
|
||||
mozLoop: this.props.mozLoop,
|
||||
publishStream: this.publishStream,
|
||||
video: this.state.video})
|
||||
)
|
||||
|
@ -1176,6 +1306,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
MediaLayoutView: MediaLayoutView,
|
||||
MediaView: MediaView,
|
||||
LoadingView: LoadingView,
|
||||
SettingsControlButton: SettingsControlButton,
|
||||
ScreenShareControlButton: ScreenShareControlButton,
|
||||
NotificationListView: NotificationListView
|
||||
};
|
||||
|
|
|
@ -180,6 +180,146 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Settings control button.
|
||||
*/
|
||||
var SettingsControlButton = React.createClass({
|
||||
propTypes: {
|
||||
menuItems: React.PropTypes.array,
|
||||
mozLoop: React.PropTypes.object
|
||||
},
|
||||
|
||||
mixins: [
|
||||
sharedMixins.DropdownMenuMixin(),
|
||||
React.addons.PureRenderMixin
|
||||
],
|
||||
|
||||
/**
|
||||
* Show or hide the settings menu
|
||||
*/
|
||||
handleClick: function(event) {
|
||||
event.preventDefault();
|
||||
this.toggleDropdownMenu();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the function that Show or hide the edit context edition form
|
||||
*/
|
||||
getHandleToggleEdit: function(editItem) {
|
||||
return function _handleToglleEdit(event) {
|
||||
event.preventDefault();
|
||||
if (editItem.onClick) {
|
||||
editItem.onClick(!editItem.enabled);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Load on the browser the help (support) url from prefs
|
||||
*/
|
||||
handleHelpEntry: function(event) {
|
||||
event.preventDefault();
|
||||
var helloSupportUrl = this.props.mozLoop.getLoopPref("support_url");
|
||||
this.props.mozLoop.openURL(helloSupportUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load on the browser the feedback url from prefs
|
||||
*/
|
||||
handleSubmitFeedback: function(event) {
|
||||
event.preventDefault();
|
||||
var helloFeedbackUrl = this.props.mozLoop.getLoopPref("feedback.formURL");
|
||||
this.props.mozLoop.openURL(helloFeedbackUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Recover the needed info for generating an specific menu Item
|
||||
*/
|
||||
getItemInfo: function(menuItem) {
|
||||
var cx = React.addons.classSet;
|
||||
switch (menuItem.id) {
|
||||
case "feedback":
|
||||
return {
|
||||
cssClasses: "dropdown-menu-item",
|
||||
handler: this.handleSubmitFeedback,
|
||||
label: mozL10n.get("feedback_request_button")
|
||||
};
|
||||
case "help":
|
||||
return {
|
||||
cssClasses: "dropdown-menu-item",
|
||||
handler: this.handleHelpEntry,
|
||||
label: mozL10n.get("help_label")
|
||||
};
|
||||
case "edit":
|
||||
return {
|
||||
cssClasses: cx({
|
||||
"dropdown-menu-item": true,
|
||||
"entry-settings-edit": true,
|
||||
"hide": !menuItem.visible
|
||||
}),
|
||||
handler: this.getHandleToggleEdit(menuItem),
|
||||
label: mozL10n.get(menuItem.enabled ?
|
||||
"conversation_settings_menu_edit_context" :
|
||||
"conversation_settings_menu_hide_context"),
|
||||
scope: "local",
|
||||
type: "edit"
|
||||
};
|
||||
default:
|
||||
console.error("Invalid menu item", menuItem);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate a menu item after recover its info
|
||||
*/
|
||||
generateMenuItem: function(menuItem) {
|
||||
var itemInfo = this.getItemInfo(menuItem);
|
||||
if (!itemInfo) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<li className={itemInfo.cssClasses}
|
||||
key={menuItem.id}
|
||||
onClick={itemInfo.handler}
|
||||
scope={itemInfo.scope || ""}
|
||||
type={itemInfo.type || ""} >
|
||||
{itemInfo.label}
|
||||
</li>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (!this.props.menuItems || !this.props.menuItems.length) {
|
||||
return null;
|
||||
}
|
||||
var menuItemRows = this.props.menuItems.map(this.generateMenuItem)
|
||||
.filter(function(item) { return item; });
|
||||
|
||||
if (!menuItemRows || !menuItemRows.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var cx = React.addons.classSet;
|
||||
var settingsDropdownMenuClasses = cx({
|
||||
"settings-menu": true,
|
||||
"dropdown-menu": true,
|
||||
"hide": !this.state.showMenu
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<button className="btn btn-settings transparent-button"
|
||||
onClick={this.toggleDropdownMenu}
|
||||
ref="menu-button"
|
||||
title={mozL10n.get("settings_menu_button_tooltip")} />
|
||||
<ul className={settingsDropdownMenuClasses} ref="menu">
|
||||
{menuItemRows}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Conversation controls.
|
||||
*/
|
||||
|
@ -188,8 +328,8 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
return {
|
||||
video: {enabled: true, visible: true},
|
||||
audio: {enabled: true, visible: true},
|
||||
edit: {enabled: false, visible: false},
|
||||
screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
|
||||
settingsMenuItems: null,
|
||||
enableHangup: true
|
||||
};
|
||||
},
|
||||
|
@ -203,13 +343,13 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
propTypes: {
|
||||
audio: React.PropTypes.object.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
edit: React.PropTypes.object.isRequired,
|
||||
enableHangup: React.PropTypes.bool,
|
||||
hangup: React.PropTypes.func.isRequired,
|
||||
hangupButtonLabel: React.PropTypes.string,
|
||||
onEditClick: React.PropTypes.func,
|
||||
mozLoop: React.PropTypes.object,
|
||||
publishStream: React.PropTypes.func.isRequired,
|
||||
screenShare: React.PropTypes.object,
|
||||
settingsMenuItems: React.PropTypes.array,
|
||||
video: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
|
@ -225,12 +365,6 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
this.props.publishStream("audio", !this.props.audio.enabled);
|
||||
},
|
||||
|
||||
handleToggleEdit: function() {
|
||||
if (this.props.onEditClick) {
|
||||
this.props.onEditClick(!this.props.edit.enabled);
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
this.userActivity = false;
|
||||
this.startIdleCountDown();
|
||||
|
@ -326,7 +460,6 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
enabled={this.props.audio.enabled}
|
||||
scope="local" type="audio"
|
||||
visible={this.props.audio.visible}/>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
<li className="conversation-toolbar-btn-box">
|
||||
|
@ -335,13 +468,8 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
visible={this.props.screenShare.visible} />
|
||||
</li>
|
||||
<li className="conversation-toolbar-btn-box btn-edit-entry">
|
||||
<MediaControlButton action={this.handleToggleEdit}
|
||||
enabled={this.props.edit.enabled}
|
||||
scope="local"
|
||||
title={mozL10n.get(this.props.edit.enabled ?
|
||||
"context_edit_tooltip" : "context_hide_tooltip")}
|
||||
type="edit"
|
||||
visible={this.props.edit.visible} />
|
||||
<SettingsControlButton menuItems={this.props.settingsMenuItems}
|
||||
mozLoop={this.props.mozLoop} />
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
|
@ -364,6 +492,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
initiate: React.PropTypes.bool,
|
||||
isDesktop: React.PropTypes.bool,
|
||||
model: React.PropTypes.object.isRequired,
|
||||
mozLoop: React.PropTypes.object,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
video: React.PropTypes.object
|
||||
},
|
||||
|
@ -559,6 +688,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
audio={this.state.audio}
|
||||
dispatcher={this.props.dispatcher}
|
||||
hangup={this.hangup}
|
||||
mozLoop={this.props.mozLoop}
|
||||
publishStream={this.publishStream}
|
||||
video={this.state.video} />
|
||||
</div>
|
||||
|
@ -1176,6 +1306,7 @@ loop.shared.views = (function(_, mozL10n) {
|
|||
MediaLayoutView: MediaLayoutView,
|
||||
MediaView: MediaView,
|
||||
LoadingView: LoadingView,
|
||||
SettingsControlButton: SettingsControlButton,
|
||||
ScreenShareControlButton: ScreenShareControlButton,
|
||||
NotificationListView: NotificationListView
|
||||
};
|
||||
|
|
|
@ -524,7 +524,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
audio: {enabled: !this.state.audioMuted,
|
||||
visible: this._roomIsActive()},
|
||||
dispatcher: this.props.dispatcher,
|
||||
edit: { visible: false, enabled: false},
|
||||
enableHangup: this._roomIsActive(),
|
||||
hangup: this.leaveRoom,
|
||||
hangupButtonLabel: mozL10n.get("rooms_leave_button_label"),
|
||||
|
|
|
@ -524,7 +524,6 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
audio={{enabled: !this.state.audioMuted,
|
||||
visible: this._roomIsActive()}}
|
||||
dispatcher={this.props.dispatcher}
|
||||
edit={{ visible: false, enabled: false }}
|
||||
enableHangup={this._roomIsActive()}
|
||||
hangup={this.leaveRoom}
|
||||
hangupButtonLabel={mozL10n.get("rooms_leave_button_label")}
|
||||
|
|
|
@ -479,6 +479,7 @@ describe("loop.conversationViews", function () {
|
|||
var props = _.extend({
|
||||
conversationStore: conversationStore,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: {},
|
||||
matchMedia: window.matchMedia
|
||||
}, extraProps);
|
||||
return TestUtils.renderIntoDocument(
|
||||
|
|
|
@ -605,7 +605,7 @@ describe("loop.roomViews", function () {
|
|||
|
||||
expect(node.querySelector(".room-context")).to.eql(null);
|
||||
|
||||
var editButton = node.querySelector(".btn-mute-edit");
|
||||
var editButton = node.querySelector(".settings-menu > li.entry-settings-edit");
|
||||
React.addons.TestUtils.Simulate.click(editButton);
|
||||
|
||||
expect(view.getDOMNode().querySelector(".room-context")).to.not.eql(null);
|
||||
|
@ -614,7 +614,7 @@ describe("loop.roomViews", function () {
|
|||
it("should hide the form when the edit button is clicked again", function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
var editButton = view.getDOMNode().querySelector(".btn-mute-edit");
|
||||
var editButton = view.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
|
||||
React.addons.TestUtils.Simulate.click(editButton);
|
||||
|
||||
// Click again.
|
||||
|
|
|
@ -252,12 +252,159 @@ describe("loop.shared.views", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("SettingsControlButton", function() {
|
||||
var fakeMozLoop;
|
||||
var support_url = "https://support.com";
|
||||
var feedback_url = "https://feedback.com";
|
||||
|
||||
beforeEach(function() {
|
||||
fakeMozLoop = {
|
||||
openURL: sandbox.stub(),
|
||||
setLoopPref: sandbox.stub(),
|
||||
getLoopPref: function (prefName) {
|
||||
switch (prefName) {
|
||||
case "support_url":
|
||||
return support_url;
|
||||
case "feedback.formURL":
|
||||
return feedback_url;
|
||||
default:
|
||||
return prefName;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
function mountTestComponent(props) {
|
||||
props = _.extend({
|
||||
mozLoop: fakeMozLoop
|
||||
}, props);
|
||||
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(sharedViews.SettingsControlButton, props));
|
||||
}
|
||||
|
||||
it("should render a visible button", function() {
|
||||
var settingsMenuItems = [{ id: "feedback" }];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
var node = comp.getDOMNode().querySelector(".btn-settings");
|
||||
expect(node.classList.contains("hide")).eql(false);
|
||||
});
|
||||
|
||||
it("should not render anything", function() {
|
||||
var comp = mountTestComponent();
|
||||
expect(comp.getDOMNode()).to.eql(null);
|
||||
});
|
||||
|
||||
it("should not show an indefined menu option", function() {
|
||||
var settingsMenuItems = [
|
||||
{ id: "not Defined" },
|
||||
{ id: "help" }
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
var menuItems = comp.getDOMNode().querySelectorAll(".settings-menu > li");
|
||||
expect(menuItems).to.have.length.of(1);
|
||||
});
|
||||
|
||||
it("should not render anythin if not exists any valid item to show", function() {
|
||||
var settingsMenuItems = [
|
||||
{ id: "not Defined" },
|
||||
{ id: "another wrong menu item" }
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
expect(comp.getDOMNode()).to.eql(null);
|
||||
});
|
||||
|
||||
it("should show the settings dropdown on click", function() {
|
||||
var settingsMenuItems = [{ id: "feedback" }];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
expect(comp.state.showMenu).eql(false);
|
||||
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".btn-settings"));
|
||||
|
||||
expect(comp.state.showMenu).eql(true);
|
||||
});
|
||||
|
||||
it("should show edit Context on menu when the option is enabled", function() {
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
enabled: true,
|
||||
visible: true,
|
||||
onClick: function() {}
|
||||
}
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
var node = comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
|
||||
expect(node.classList.contains("hide")).eql(false);
|
||||
});
|
||||
|
||||
it("should hide edit Context on menu when the option is not visible", function() {
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
enabled: false,
|
||||
visible: false,
|
||||
onClick: function() {}
|
||||
}
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
var node = comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit");
|
||||
expect(node.classList.contains("hide")).eql(true);
|
||||
});
|
||||
|
||||
it("should call onClick method when the edit context menu item is clicked", function() {
|
||||
var onClickCalled = false;
|
||||
var settingsMenuItems = [
|
||||
{
|
||||
id: "edit",
|
||||
enabled: true,
|
||||
visible: true,
|
||||
onClick: sandbox.stub()
|
||||
}
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li.entry-settings-edit"));
|
||||
sinon.assert.calledOnce(settingsMenuItems[0].onClick);
|
||||
});
|
||||
|
||||
it("should open a tab to the feedback url when the feedback menu item is clicked", function() {
|
||||
var settingsMenuItems = [
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li:first-child"));
|
||||
|
||||
sinon.assert.calledOnce(fakeMozLoop.openURL);
|
||||
sinon.assert.calledWithExactly(fakeMozLoop.openURL, feedback_url);
|
||||
});
|
||||
|
||||
it("should open a tab to the support url when the support menu item is clicked", function() {
|
||||
var settingsMenuItems = [
|
||||
{ id: "feedback" },
|
||||
{ id: "help" }
|
||||
];
|
||||
var comp = mountTestComponent({ menuItems: settingsMenuItems} );
|
||||
|
||||
TestUtils.Simulate.click(comp.getDOMNode().querySelector(".settings-menu > li:last-child"));
|
||||
|
||||
sinon.assert.calledOnce(fakeMozLoop.openURL);
|
||||
sinon.assert.calledWithExactly(fakeMozLoop.openURL, support_url);
|
||||
});
|
||||
});
|
||||
|
||||
describe("ConversationToolbar", function() {
|
||||
var clock, hangup, publishStream;
|
||||
|
||||
function mountTestComponent(props) {
|
||||
props = _.extend({
|
||||
dispatcher: dispatcher
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: {}
|
||||
}, props || {});
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(sharedViews.ConversationToolbar, props));
|
||||
|
@ -407,7 +554,8 @@ describe("loop.shared.views", function() {
|
|||
|
||||
function mountTestComponent(props) {
|
||||
props = _.extend({
|
||||
dispatcher: dispatcher
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: {}
|
||||
}, props || {});
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(sharedViews.ConversationView, props));
|
||||
|
|
|
@ -1028,6 +1028,7 @@
|
|||
React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true},
|
||||
hangup: noop,
|
||||
publishStream: noop,
|
||||
settingsMenuItems: [{ id: "feedback" }],
|
||||
video: { enabled: true, visible: true}})
|
||||
)
|
||||
),
|
||||
|
@ -1039,6 +1040,7 @@
|
|||
React.createElement(ConversationToolbar, {audio: { enabled: true, visible: true},
|
||||
hangup: noop,
|
||||
publishStream: noop,
|
||||
settingsMenuItems: [{ id: "feedback" }],
|
||||
video: { enabled: false, visible: true}})
|
||||
)
|
||||
),
|
||||
|
@ -1050,6 +1052,7 @@
|
|||
React.createElement(ConversationToolbar, {audio: { enabled: false, visible: true},
|
||||
hangup: noop,
|
||||
publishStream: noop,
|
||||
settingsMenuItems: [{ id: "feedback" }],
|
||||
video: { enabled: true, visible: true}})
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1028,6 +1028,7 @@
|
|||
<ConversationToolbar audio={{ enabled: true, visible: true }}
|
||||
hangup={noop}
|
||||
publishStream={noop}
|
||||
settingsMenuItems={[{ id: "feedback" }]}
|
||||
video={{ enabled: true, visible: true }} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
@ -1039,6 +1040,7 @@
|
|||
<ConversationToolbar audio={{ enabled: true, visible: true }}
|
||||
hangup={noop}
|
||||
publishStream={noop}
|
||||
settingsMenuItems={[{ id: "feedback" }]}
|
||||
video={{ enabled: false, visible: true }} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
@ -1050,6 +1052,7 @@
|
|||
<ConversationToolbar audio={{ enabled: false, visible: true }}
|
||||
hangup={noop}
|
||||
publishStream={noop}
|
||||
settingsMenuItems={[{ id: "feedback" }]}
|
||||
video={{ enabled: true, visible: true }} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
|
|
|
@ -357,12 +357,13 @@ context_edit_activate_label=Talk about "{{title}}"
|
|||
context_edit_name_placeholder=Conversation Name
|
||||
context_edit_comments_placeholder=Comments
|
||||
context_add_some_label=Add some context
|
||||
context_edit_tooltip=Edit Context
|
||||
context_hide_tooltip=Hide Context
|
||||
context_show_tooltip=Show Context
|
||||
context_save_label2=Save
|
||||
context_link_modified=This link was modified.
|
||||
context_learn_more_link_label=Learn more.
|
||||
conversation_settings_menu_edit_context=Edit Context
|
||||
conversation_settings_menu_hide_context=Hide Context
|
||||
|
||||
|
||||
# Text chat strings
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче