mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
29f415af35
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "2082894c8e974b0c371e4dec298e0ad0f3ac56b1",
|
||||
"git_revision": "4f22dfecdc046fe5223ee858dd06c11b75884740",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "0e712c8d330e10908f99194a9638e62a07c5c483",
|
||||
"revision": "0beec8dba282bfc00590a16ccf180c0988465316",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="2782648aabf0af464dd9c4202b367b408898546d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1f9532e4157df2dc8d3e9c8100120f80117dcd4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="2082894c8e974b0c371e4dec298e0ad0f3ac56b1"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f22dfecdc046fe5223ee858dd06c11b75884740"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -219,8 +219,8 @@ var wrapper = {
|
||||
// we need to tell the page we successfully received the message, but
|
||||
// then bail without telling fxAccounts
|
||||
this.injectData("message", { status: "login" });
|
||||
// and re-init the page by navigating to about:accounts
|
||||
window.location = "about:accounts";
|
||||
// after a successful login we return to preferences
|
||||
openPrefs();
|
||||
return;
|
||||
}
|
||||
delete accountData.verifiedCanLinkAccount;
|
||||
@ -333,7 +333,9 @@ function retry() {
|
||||
}
|
||||
|
||||
function openPrefs() {
|
||||
window.openPreferences("paneSync");
|
||||
// Bug 1199303 calls for this tab to always be replaced with Preferences
|
||||
// rather than it opening in a different tab.
|
||||
window.location = "about:preferences#sync";
|
||||
}
|
||||
|
||||
function init() {
|
||||
@ -511,8 +513,9 @@ function initObservers() {
|
||||
window.location = "about:accounts?action=signin";
|
||||
return;
|
||||
}
|
||||
// must be onverified - just about:accounts is loaded.
|
||||
window.location = "about:accounts";
|
||||
|
||||
// must be onverified - we want to open preferences.
|
||||
openPrefs();
|
||||
}
|
||||
|
||||
for (let topic of OBSERVER_TOPICS) {
|
||||
|
@ -136,7 +136,6 @@ html[dir="rtl"] .contact-filter {
|
||||
}
|
||||
|
||||
.contact {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
@ -157,54 +157,55 @@ loop.contacts = (function(_, mozL10n) {
|
||||
// If the contact is blocked or not.
|
||||
blocked: React.PropTypes.bool,
|
||||
canEdit: React.PropTypes.bool,
|
||||
// Position of mouse when opening menu
|
||||
eventPosY: React.PropTypes.number.isRequired,
|
||||
// callback function that provides height and top coordinate for contacts container
|
||||
getContainerCoordinates: React.PropTypes.func.isRequired,
|
||||
handleAction: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
getInitialState: function() {
|
||||
return {
|
||||
openDirUp: false
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
// This method is called once when the dropdown menu is added to the DOM
|
||||
// inside the contact item. If the menu extends outside of the visible
|
||||
// area of the scrollable list, it is re-rendered in different direction.
|
||||
|
||||
let menuNode = this.getDOMNode();
|
||||
let menuNodeRect = menuNode.getBoundingClientRect();
|
||||
|
||||
let listNode = document.getElementsByClassName("contact-list")[0];
|
||||
// XXX Workaround the contact-list element not being available in tests.
|
||||
// Assumptions about the embedded DOM are a bad idea, and this needs
|
||||
// reworking. For example, tests use a virtual DOM. Really we should
|
||||
// rework this view with the DropdownMenuMixin, which would save some of this pain.
|
||||
if (!listNode) {
|
||||
return;
|
||||
}
|
||||
let listNodeRect = listNode.getBoundingClientRect();
|
||||
|
||||
if (menuNodeRect.top + menuNodeRect.height >=
|
||||
listNodeRect.top + listNodeRect.height) {
|
||||
this.setState({
|
||||
openDirUp: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onItemClick: function(event) {
|
||||
this.props.handleAction(event.currentTarget.dataset.action);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var menuNode = this.getDOMNode();
|
||||
var menuNodeRect = menuNode.getBoundingClientRect();
|
||||
var listNodeCoords = this.props.getContainerCoordinates();
|
||||
|
||||
// Click offset to not display the menu right next to the area clicked.
|
||||
var offset = 10;
|
||||
|
||||
if (this.props.eventPosY + menuNodeRect.height >=
|
||||
listNodeCoords.top + listNodeCoords.height) {
|
||||
|
||||
// Position above click area.
|
||||
menuNode.style.top = this.props.eventPosY - menuNodeRect.height
|
||||
- offset + "px";
|
||||
} else {
|
||||
// Position below click area.
|
||||
menuNode.style.top = this.props.eventPosY + offset + "px";
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var cx = React.addons.classSet;
|
||||
var dropdownClasses = cx({
|
||||
"dropdown-menu": true,
|
||||
"dropdown-menu-up": this.state.openDirUp
|
||||
});
|
||||
let blockAction = this.props.blocked ? "unblock" : "block";
|
||||
let blockLabel = this.props.blocked ? "unblock_contact_menu_button"
|
||||
: "block_contact_menu_button";
|
||||
|
||||
return (
|
||||
React.createElement("ul", {className: cx({ "dropdown-menu": true,
|
||||
"dropdown-menu-up": this.state.openDirUp })},
|
||||
React.createElement("ul", {className: dropdownClasses},
|
||||
React.createElement("li", {className: cx({ "dropdown-menu-item": true,
|
||||
"disabled": this.props.blocked,
|
||||
"video-call-item": true }),
|
||||
@ -244,40 +245,41 @@ loop.contacts = (function(_, mozL10n) {
|
||||
});
|
||||
|
||||
const ContactDetail = React.createClass({displayName: "ContactDetail",
|
||||
getInitialState: function() {
|
||||
return {
|
||||
showMenu: false
|
||||
};
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
contact: React.PropTypes.object.isRequired,
|
||||
getContainerCoordinates: React.PropTypes.func.isRequired,
|
||||
handleContactAction: React.PropTypes.func
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
// Hide the menu after other click handlers have been invoked.
|
||||
setTimeout(this.hideDropdownMenu, 10);
|
||||
mixins: [
|
||||
sharedMixins.DropdownMenuMixin()
|
||||
],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
eventPosY: 0
|
||||
};
|
||||
},
|
||||
|
||||
showDropdownMenu: function() {
|
||||
document.body.addEventListener("click", this._onBodyClick);
|
||||
this.setState({showMenu: true});
|
||||
handleShowDropdownClick: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.setState({
|
||||
eventPosY: e.pageY
|
||||
});
|
||||
|
||||
this.toggleDropdownMenu();
|
||||
},
|
||||
|
||||
hideDropdownMenu: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
hideDropdownMenuHandler: function() {
|
||||
// Since this call may be deferred, we need to guard it, for example in
|
||||
// case the contact was removed in the meantime.
|
||||
if (this.isMounted()) {
|
||||
this.setState({showMenu: false});
|
||||
this.hideDropdownMenu();
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
let currContact = this.props.contact;
|
||||
let nextContact = nextProps.contact;
|
||||
@ -294,6 +296,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
handleAction: function(actionName) {
|
||||
if (this.props.handleContactAction) {
|
||||
this.props.handleContactAction(this.props.contact, actionName);
|
||||
this.hideDropdownMenuHandler();
|
||||
}
|
||||
},
|
||||
|
||||
@ -303,6 +306,16 @@ loop.contacts = (function(_, mozL10n) {
|
||||
return this.props.contact.category[0] !== "google";
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback called when moving cursor away from the conversation entry.
|
||||
* Will close the dropdown menu.
|
||||
*/
|
||||
_handleMouseOut: function() {
|
||||
if (this.state.showMenu) {
|
||||
this.toggleDropdownMenu();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let names = getContactNames(this.props.contact);
|
||||
let email = getPreferred(this.props.contact, "email");
|
||||
@ -316,9 +329,9 @@ loop.contacts = (function(_, mozL10n) {
|
||||
avatar: true,
|
||||
defaultAvatar: !avatarSrc
|
||||
});
|
||||
|
||||
return (
|
||||
React.createElement("li", {className: contactCSSClass, onMouseLeave: this.hideDropdownMenu},
|
||||
React.createElement("li", {className: contactCSSClass,
|
||||
onMouseLeave: this._handleMouseOut},
|
||||
React.createElement("div", {className: avatarCSSClass},
|
||||
avatarSrc ? React.createElement("img", {src: avatarSrc}) : null
|
||||
),
|
||||
@ -332,11 +345,13 @@ loop.contacts = (function(_, mozL10n) {
|
||||
React.createElement("i", {className: "icon icon-contact-video-call",
|
||||
onClick: this.handleAction.bind(null, "video-call")}),
|
||||
React.createElement("i", {className: "icon icon-vertical-ellipsis icon-contact-menu-button",
|
||||
onClick: this.showDropdownMenu})
|
||||
onClick: this.handleShowDropdownClick})
|
||||
),
|
||||
this.state.showMenu
|
||||
? React.createElement(ContactDropdown, {blocked: this.props.contact.blocked,
|
||||
canEdit: this.canEdit(),
|
||||
eventPosY: this.state.eventPosY,
|
||||
getContainerCoordinates: this.props.getContainerCoordinates,
|
||||
handleAction: this.handleAction})
|
||||
: null
|
||||
|
||||
@ -636,6 +651,17 @@ loop.contacts = (function(_, mozL10n) {
|
||||
return contact1._guid - contact2._guid;
|
||||
},
|
||||
|
||||
getCoordinates: function() {
|
||||
// Returns coordinates for use by child elements to place menus etc that are absolutely positioned
|
||||
var domNode = this.getDOMNode();
|
||||
var domNodeRect = domNode.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
"top": domNodeRect.top,
|
||||
"height": domNodeRect.height
|
||||
};
|
||||
},
|
||||
|
||||
_renderFilterClearButton: function() {
|
||||
if (this.state.filter) {
|
||||
return (
|
||||
@ -668,6 +694,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
let viewForItem = item => {
|
||||
return (
|
||||
React.createElement(ContactDetail, {contact: item,
|
||||
getContainerCoordinates: this.getCoordinates,
|
||||
handleContactAction: this.handleContactAction,
|
||||
key: item._guid})
|
||||
);
|
||||
|
@ -157,54 +157,55 @@ loop.contacts = (function(_, mozL10n) {
|
||||
// If the contact is blocked or not.
|
||||
blocked: React.PropTypes.bool,
|
||||
canEdit: React.PropTypes.bool,
|
||||
// Position of mouse when opening menu
|
||||
eventPosY: React.PropTypes.number.isRequired,
|
||||
// callback function that provides height and top coordinate for contacts container
|
||||
getContainerCoordinates: React.PropTypes.func.isRequired,
|
||||
handleAction: React.PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
getInitialState: function() {
|
||||
return {
|
||||
openDirUp: false
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount: function () {
|
||||
// This method is called once when the dropdown menu is added to the DOM
|
||||
// inside the contact item. If the menu extends outside of the visible
|
||||
// area of the scrollable list, it is re-rendered in different direction.
|
||||
|
||||
let menuNode = this.getDOMNode();
|
||||
let menuNodeRect = menuNode.getBoundingClientRect();
|
||||
|
||||
let listNode = document.getElementsByClassName("contact-list")[0];
|
||||
// XXX Workaround the contact-list element not being available in tests.
|
||||
// Assumptions about the embedded DOM are a bad idea, and this needs
|
||||
// reworking. For example, tests use a virtual DOM. Really we should
|
||||
// rework this view with the DropdownMenuMixin, which would save some of this pain.
|
||||
if (!listNode) {
|
||||
return;
|
||||
}
|
||||
let listNodeRect = listNode.getBoundingClientRect();
|
||||
|
||||
if (menuNodeRect.top + menuNodeRect.height >=
|
||||
listNodeRect.top + listNodeRect.height) {
|
||||
this.setState({
|
||||
openDirUp: true
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onItemClick: function(event) {
|
||||
this.props.handleAction(event.currentTarget.dataset.action);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var menuNode = this.getDOMNode();
|
||||
var menuNodeRect = menuNode.getBoundingClientRect();
|
||||
var listNodeCoords = this.props.getContainerCoordinates();
|
||||
|
||||
// Click offset to not display the menu right next to the area clicked.
|
||||
var offset = 10;
|
||||
|
||||
if (this.props.eventPosY + menuNodeRect.height >=
|
||||
listNodeCoords.top + listNodeCoords.height) {
|
||||
|
||||
// Position above click area.
|
||||
menuNode.style.top = this.props.eventPosY - menuNodeRect.height
|
||||
- offset + "px";
|
||||
} else {
|
||||
// Position below click area.
|
||||
menuNode.style.top = this.props.eventPosY + offset + "px";
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var cx = React.addons.classSet;
|
||||
var dropdownClasses = cx({
|
||||
"dropdown-menu": true,
|
||||
"dropdown-menu-up": this.state.openDirUp
|
||||
});
|
||||
let blockAction = this.props.blocked ? "unblock" : "block";
|
||||
let blockLabel = this.props.blocked ? "unblock_contact_menu_button"
|
||||
: "block_contact_menu_button";
|
||||
|
||||
return (
|
||||
<ul className={cx({ "dropdown-menu": true,
|
||||
"dropdown-menu-up": this.state.openDirUp })}>
|
||||
<ul className={dropdownClasses}>
|
||||
<li className={cx({ "dropdown-menu-item": true,
|
||||
"disabled": this.props.blocked,
|
||||
"video-call-item": true })}
|
||||
@ -244,40 +245,41 @@ loop.contacts = (function(_, mozL10n) {
|
||||
});
|
||||
|
||||
const ContactDetail = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
showMenu: false
|
||||
};
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
contact: React.PropTypes.object.isRequired,
|
||||
getContainerCoordinates: React.PropTypes.func.isRequired,
|
||||
handleContactAction: React.PropTypes.func
|
||||
},
|
||||
|
||||
_onBodyClick: function() {
|
||||
// Hide the menu after other click handlers have been invoked.
|
||||
setTimeout(this.hideDropdownMenu, 10);
|
||||
mixins: [
|
||||
sharedMixins.DropdownMenuMixin()
|
||||
],
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
eventPosY: 0
|
||||
};
|
||||
},
|
||||
|
||||
showDropdownMenu: function() {
|
||||
document.body.addEventListener("click", this._onBodyClick);
|
||||
this.setState({showMenu: true});
|
||||
handleShowDropdownClick: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.setState({
|
||||
eventPosY: e.pageY
|
||||
});
|
||||
|
||||
this.toggleDropdownMenu();
|
||||
},
|
||||
|
||||
hideDropdownMenu: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
hideDropdownMenuHandler: function() {
|
||||
// Since this call may be deferred, we need to guard it, for example in
|
||||
// case the contact was removed in the meantime.
|
||||
if (this.isMounted()) {
|
||||
this.setState({showMenu: false});
|
||||
this.hideDropdownMenu();
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
document.body.removeEventListener("click", this._onBodyClick);
|
||||
},
|
||||
|
||||
shouldComponentUpdate: function(nextProps, nextState) {
|
||||
let currContact = this.props.contact;
|
||||
let nextContact = nextProps.contact;
|
||||
@ -294,6 +296,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
handleAction: function(actionName) {
|
||||
if (this.props.handleContactAction) {
|
||||
this.props.handleContactAction(this.props.contact, actionName);
|
||||
this.hideDropdownMenuHandler();
|
||||
}
|
||||
},
|
||||
|
||||
@ -303,6 +306,16 @@ loop.contacts = (function(_, mozL10n) {
|
||||
return this.props.contact.category[0] !== "google";
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback called when moving cursor away from the conversation entry.
|
||||
* Will close the dropdown menu.
|
||||
*/
|
||||
_handleMouseOut: function() {
|
||||
if (this.state.showMenu) {
|
||||
this.toggleDropdownMenu();
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
let names = getContactNames(this.props.contact);
|
||||
let email = getPreferred(this.props.contact, "email");
|
||||
@ -316,9 +329,9 @@ loop.contacts = (function(_, mozL10n) {
|
||||
avatar: true,
|
||||
defaultAvatar: !avatarSrc
|
||||
});
|
||||
|
||||
return (
|
||||
<li className={contactCSSClass} onMouseLeave={this.hideDropdownMenu}>
|
||||
<li className={contactCSSClass}
|
||||
onMouseLeave={this._handleMouseOut}>
|
||||
<div className={avatarCSSClass}>
|
||||
{avatarSrc ? <img src={avatarSrc} /> : null}
|
||||
</div>
|
||||
@ -332,11 +345,13 @@ loop.contacts = (function(_, mozL10n) {
|
||||
<i className="icon icon-contact-video-call"
|
||||
onClick={this.handleAction.bind(null, "video-call")} />
|
||||
<i className="icon icon-vertical-ellipsis icon-contact-menu-button"
|
||||
onClick={this.showDropdownMenu} />
|
||||
onClick={this.handleShowDropdownClick} />
|
||||
</div>
|
||||
{this.state.showMenu
|
||||
? <ContactDropdown blocked={this.props.contact.blocked}
|
||||
canEdit={this.canEdit()}
|
||||
eventPosY={this.state.eventPosY}
|
||||
getContainerCoordinates={this.props.getContainerCoordinates}
|
||||
handleAction={this.handleAction} />
|
||||
: null
|
||||
}
|
||||
@ -636,6 +651,17 @@ loop.contacts = (function(_, mozL10n) {
|
||||
return contact1._guid - contact2._guid;
|
||||
},
|
||||
|
||||
getCoordinates: function() {
|
||||
// Returns coordinates for use by child elements to place menus etc that are absolutely positioned
|
||||
var domNode = this.getDOMNode();
|
||||
var domNodeRect = domNode.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
"top": domNodeRect.top,
|
||||
"height": domNodeRect.height
|
||||
};
|
||||
},
|
||||
|
||||
_renderFilterClearButton: function() {
|
||||
if (this.state.filter) {
|
||||
return (
|
||||
@ -668,6 +694,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
let viewForItem = item => {
|
||||
return (
|
||||
<ContactDetail contact={item}
|
||||
getContainerCoordinates={this.getCoordinates}
|
||||
handleContactAction={this.handleContactAction}
|
||||
key={item._guid} />
|
||||
);
|
||||
|
@ -174,7 +174,9 @@ describe("loop.contacts", function() {
|
||||
};
|
||||
|
||||
fakeWindow = {
|
||||
close: sandbox.stub()
|
||||
close: sandbox.stub(),
|
||||
addEventListener: function() {},
|
||||
removeEventListener: function() {}
|
||||
};
|
||||
loop.shared.mixins.setRootObject(fakeWindow);
|
||||
|
||||
@ -676,7 +678,8 @@ describe("loop.contacts", function() {
|
||||
|
||||
// Open the menu
|
||||
var menuButton = node.querySelector(".icon-contact-menu-button");
|
||||
TestUtils.Simulate.click(menuButton);
|
||||
var eventStub = {"pageY": 20};
|
||||
TestUtils.Simulate.click(menuButton, eventStub);
|
||||
|
||||
// Get the menu for use in the tests.
|
||||
contactMenu = node.querySelector(".contact > .dropdown-menu");
|
||||
|
@ -1029,6 +1029,7 @@
|
||||
width: 334},
|
||||
React.createElement("div", {className: "panel force-menu-show"},
|
||||
React.createElement(ContactDetail, {contact: fakeManyContacts[0],
|
||||
getContainerCoordinates: function() { return {"top": 0, "height": 0 }; },
|
||||
handleContactAction: function() {}})
|
||||
)
|
||||
)
|
||||
@ -1043,6 +1044,8 @@
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(ContactDropdown, {blocked: false,
|
||||
canEdit: true,
|
||||
eventPosY: 0,
|
||||
getContainerCoordinates: function() { return {"top": 0, "height": 0 }; },
|
||||
handleAction: function () {}})
|
||||
)
|
||||
),
|
||||
@ -1053,8 +1056,10 @@
|
||||
width: 300},
|
||||
React.createElement("div", {className: "panel"},
|
||||
React.createElement(ContactDropdown, {blocked: true,
|
||||
canEdit: false,
|
||||
handleAction: function () {}})
|
||||
canEdit: false,
|
||||
eventPosY: 0,
|
||||
getContainerCoordinates: function() { return {"top": 0, "height": 0 }; },
|
||||
handleAction: function () {}})
|
||||
)
|
||||
)
|
||||
),
|
||||
|
@ -1029,6 +1029,7 @@
|
||||
width={334}>
|
||||
<div className="panel force-menu-show">
|
||||
<ContactDetail contact={fakeManyContacts[0]}
|
||||
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
|
||||
handleContactAction={function() {}} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
@ -1043,6 +1044,8 @@
|
||||
<div className="panel">
|
||||
<ContactDropdown blocked={false}
|
||||
canEdit={true}
|
||||
eventPosY={0}
|
||||
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
|
||||
handleAction={function () {}} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
@ -1053,8 +1056,10 @@
|
||||
width={300}>
|
||||
<div className="panel">
|
||||
<ContactDropdown blocked={true}
|
||||
canEdit={false}
|
||||
handleAction={function () {}} />
|
||||
canEdit={false}
|
||||
eventPosY={0}
|
||||
getContainerCoordinates={function() { return {"top": 0, "height": 0 }; }}
|
||||
handleAction={function () {}} />
|
||||
</div>
|
||||
</FramedExample>
|
||||
</Section>
|
||||
|
@ -607,10 +607,7 @@ var gSyncPane = {
|
||||
}
|
||||
params.set("entrypoint", entryPoint);
|
||||
|
||||
this.openContentInBrowser("about:accounts?" + params, {
|
||||
replaceQueryString: true
|
||||
});
|
||||
|
||||
this.replaceTabWithUrl("about:accounts?" + params);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -653,6 +650,17 @@ var gSyncPane = {
|
||||
win.switchToTabHavingURI(url, true, options);
|
||||
},
|
||||
|
||||
// Replace the current tab with the specified URL.
|
||||
replaceTabWithUrl(url) {
|
||||
// Get the <browser> element hosting us.
|
||||
let browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
// And tell it to load our URL.
|
||||
browser.loadURI(url);
|
||||
},
|
||||
|
||||
openPrivacyPolicy: function(aEvent) {
|
||||
aEvent.stopPropagation();
|
||||
gSyncUtils.openPrivacyPolicy();
|
||||
|
@ -120,8 +120,8 @@ Events
|
||||
event is fired with the previous locale as the extra. If the previous locale
|
||||
could not be determined, "unknown" is provided.
|
||||
|
||||
``setdefault.1``
|
||||
Set default home panel.
|
||||
``neterror.1``
|
||||
When the user performs actions on the in-content network error page. This should probably be a ``Session``, but it's difficult to start and stop the session reliably.
|
||||
|
||||
``pin.1``, ``unpin.1``
|
||||
Sent when the user pinned or unpinned a top site.
|
||||
@ -140,20 +140,112 @@ Events
|
||||
``search.1``
|
||||
Sent when the user performs a search. Currently used in the search activity.
|
||||
|
||||
``search.remove.1``
|
||||
Sent when the user removes a search engine.
|
||||
|
||||
``search.restore.1``
|
||||
Sent when the user restores the search engine configuration back to the built-in configuration.
|
||||
|
||||
``search.setdefault.1``
|
||||
Sent when the user sets a search engine to be the default.
|
||||
|
||||
``setdefault.1``
|
||||
Set default home panel.
|
||||
|
||||
``share.1``
|
||||
Sharing content.
|
||||
|
||||
``show.1``
|
||||
Sent when a contextual UI element is shown to the user.
|
||||
|
||||
``undo.1``
|
||||
Sent when performing an undo-style action, like undoing a closed tab.
|
||||
|
||||
Methods
|
||||
-------
|
||||
``actionbar``
|
||||
Action triggered from an ActionBar UI.
|
||||
|
||||
``back``
|
||||
Action triggered from the back button.
|
||||
|
||||
``banner``
|
||||
Action triggered from a banner (such as HomeBanner).
|
||||
|
||||
``button``
|
||||
Action triggered from a button.
|
||||
Note: Only used in JavaScript for now.
|
||||
|
||||
``content``
|
||||
Action triggered from a content page.
|
||||
|
||||
``contextmenu``
|
||||
Action triggered from a contextmenu. Could be from chrome or content.
|
||||
|
||||
``dialog``
|
||||
Action triggered from a dialog.
|
||||
|
||||
``griditem``
|
||||
Action triggered from a griditem, such as those used in Top Sites panel.
|
||||
|
||||
``homescreen``
|
||||
Action triggered from a homescreen shortcut icon.
|
||||
|
||||
``intent``
|
||||
Action triggered from a system Intent, usually sent from the OS.
|
||||
|
||||
``list``
|
||||
Action triggered from an unmanaged list of items, usually provided by the OS.
|
||||
|
||||
``listitem``
|
||||
Action triggered from a listitem.
|
||||
|
||||
``menu``
|
||||
Action triggered from the main menu.
|
||||
|
||||
``notification``
|
||||
Action triggered from a system notification.
|
||||
|
||||
``pageaction``
|
||||
Action triggered from a pageaction, displayed in the URL bar.
|
||||
|
||||
``settings``
|
||||
Action triggered from a content page.
|
||||
|
||||
``shareoverlay``
|
||||
Action triggered from a content page.
|
||||
|
||||
``suggestion``
|
||||
Action triggered from a suggested result, like those from search engines or default tiles.
|
||||
|
||||
``toast``
|
||||
Action triggered from an unobtrusive, temporary notification.
|
||||
|
||||
``widget``
|
||||
Action triggered from a widget placed on the homescreen.
|
||||
|
||||
Sessions
|
||||
--------
|
||||
``awesomescreen.1``
|
||||
Awesomescreen (including frecency search) is active.
|
||||
|
||||
``firstrun.1``
|
||||
Started the very first time we believe the application has been launched.
|
||||
|
||||
``frecency.1``
|
||||
Awesomescreen frecency search is active.
|
||||
|
||||
``homepanel.1``
|
||||
Started when a user enters a given home panel.
|
||||
Session name is dynamic, encoded as "homepanel.1:<panel_id>"
|
||||
Built-in home panels have fixed IDs
|
||||
|
||||
``reader.1``
|
||||
Reader viewer becomes active in the foreground.
|
||||
|
||||
``searchactivity.1``
|
||||
Started when the user launches the search activity (onStart) and stopped
|
||||
when they leave the search activity.
|
||||
|
||||
``settings.1``
|
||||
Settings activity is active.
|
||||
|
@ -1,3 +1,5 @@
|
||||
import java.util.regex.Pattern
|
||||
|
||||
allprojects {
|
||||
// Expose the per-object-directory configuration to all projects.
|
||||
ext {
|
||||
@ -62,10 +64,15 @@ task generateCodeAndResources(type:Exec) {
|
||||
// Skip unit test for all build variants, unless if it was specifically requested by user.
|
||||
// The enabled property for the unit test tasks is reset based on the command line task names just before the task execution.
|
||||
// I bet there is a easier/cleaner way to do this, but this gets the job done for now.
|
||||
Pattern pattern = Pattern.compile('.*test(.+UnitTest)?.*')
|
||||
boolean startTasksIncludeTest = gradle.startParameter.taskNames.any {
|
||||
taskName ->
|
||||
taskName.matches(pattern)
|
||||
}
|
||||
gradle.taskGraph.beforeTask {
|
||||
Task task ->
|
||||
if (task.name.startsWith('test') && task.name.endsWith('UnitTest')) {
|
||||
task.enabled = gradle.startParameter.taskNames.contains('test')
|
||||
if (task.name.matches(pattern)) {
|
||||
task.enabled = startTasksIncludeTest
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4767,16 +4767,16 @@ pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,tes
|
||||
pref("urlclassifier.phishTable", "goog-phish-shavar,test-phish-simple");
|
||||
pref("urlclassifier.downloadBlockTable", "");
|
||||
pref("urlclassifier.downloadAllowTable", "");
|
||||
pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,goog-downloadwhite-digest256,mozpub-track-digest256,mozpub-trackwhite-digest256");
|
||||
pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,goog-downloadwhite-digest256,mozstd-track-digest256,mozstd-trackwhite-digest256");
|
||||
|
||||
// The table and update/gethash URLs for Safebrowsing phishing and malware
|
||||
// checks.
|
||||
pref("urlclassifier.trackingTable", "test-track-simple,mozpub-track-digest256");
|
||||
pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozpub-trackwhite-digest256");
|
||||
pref("urlclassifier.trackingTable", "test-track-simple,mozstd-track-digest256");
|
||||
pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
|
||||
|
||||
pref("browser.safebrowsing.provider.mozilla.lists", "mozpub-track-digest256,mozpub-trackwhite-digest256");
|
||||
pref("browser.safebrowsing.provider.mozilla.updateURL", "https://tracking.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.provider.mozilla.gethashURL", "https://tracking.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.provider.mozilla.lists", "mozstd-track-digest256,mozstd-trackwhite-digest256");
|
||||
pref("browser.safebrowsing.provider.mozilla.updateURL", "https://shavar.services.mozilla.com/downloads?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
pref("browser.safebrowsing.provider.mozilla.gethashURL", "https://shavar.services.mozilla.com/gethash?client=SAFEBROWSING_ID&appver=%VERSION%&pver=2.2");
|
||||
|
||||
// Turn off Spatial navigation by default.
|
||||
pref("snav.enabled", false);
|
||||
|
@ -366,10 +366,12 @@ class B2GBuildBaseScript(BuildbotMixin, MockMixin,
|
||||
dirs = self.query_abs_dirs()
|
||||
gecko_config = self.load_gecko_config()
|
||||
b2g_manifest_intree = gecko_config.get('b2g_manifest_intree')
|
||||
b2g_repo = gecko_config.get('b2g_repo','https://git.mozilla.org/b2g/B2G.git')
|
||||
b2g_branch = gecko_config.get('b2g_branch','master')
|
||||
|
||||
if gecko_config.get('config_version') >= 2:
|
||||
repos = [
|
||||
{'vcs': 'gittool', 'repo': 'https://git.mozilla.org/b2g/B2G.git', 'dest': dirs['work_dir']},
|
||||
{'vcs': 'gittool', 'repo': b2g_repo, 'branch': b2g_branch, 'dest': dirs['work_dir']},
|
||||
]
|
||||
|
||||
if b2g_manifest_intree:
|
||||
|
@ -40,22 +40,28 @@ function *getSystemInfo() {
|
||||
let appInfo = Services.appinfo;
|
||||
let win = Services.wm.getMostRecentWindow(DebuggerServer.chromeWindowType);
|
||||
let [processor, compiler] = appInfo.XPCOMABI.split("-");
|
||||
let dpi, useragent, width, height, os, hardware, version, brandName;
|
||||
let dpi, useragent, width, height, os, brandName;
|
||||
let appid = appInfo.ID;
|
||||
let apptype = APP_MAP[appid];
|
||||
let geckoVersion = appInfo.platformVersion;
|
||||
let hardware = "unknown";
|
||||
let version = "unknown";
|
||||
|
||||
// B2G specific
|
||||
if (apptype === "b2g") {
|
||||
os = "B2G";
|
||||
hardware = yield exports.getSetting("deviceinfo.hardware");
|
||||
version = yield exports.getSetting("deviceinfo.os");
|
||||
// `getSetting` does not work in child processes on b2g.
|
||||
// TODO bug 1205797, make this work in child processes.
|
||||
try {
|
||||
hardware = yield exports.getSetting("deviceinfo.hardware");
|
||||
version = yield exports.getSetting("deviceinfo.os");
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
// Not B2G
|
||||
else {
|
||||
os = appInfo.OS;
|
||||
version = appInfo.version;
|
||||
hardware = "unknown";
|
||||
}
|
||||
|
||||
let bundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
@ -293,7 +299,16 @@ function getSetting(name) {
|
||||
let deferred = promise.defer();
|
||||
|
||||
if ("@mozilla.org/settingsService;1" in Cc) {
|
||||
let settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
|
||||
let settingsService;
|
||||
|
||||
// settingsService fails in b2g child processes
|
||||
// TODO bug 1205797, make this work in child processes.
|
||||
try {
|
||||
settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
|
||||
} catch (e) {
|
||||
return promise.reject(e);
|
||||
}
|
||||
|
||||
let req = settingsService.createLock().get(name, {
|
||||
handle: (name, value) => deferred.resolve(value),
|
||||
handleError: (error) => deferred.reject(error),
|
||||
|
Loading…
Reference in New Issue
Block a user