Merge fx-team to m-c. a=merge
@ -1601,11 +1601,12 @@ pref("devtools.webconsole.persistlog", false);
|
||||
pref("devtools.webconsole.timestampMessages", false);
|
||||
|
||||
// The number of lines that are displayed in the web console for the Net,
|
||||
// CSS, JS and Web Developer categories.
|
||||
pref("devtools.hud.loglimit.network", 200);
|
||||
pref("devtools.hud.loglimit.cssparser", 200);
|
||||
pref("devtools.hud.loglimit.exception", 200);
|
||||
pref("devtools.hud.loglimit.console", 200);
|
||||
// CSS, JS and Web Developer categories. These defaults should be kept in sync
|
||||
// with DEFAULT_LOG_LIMIT in the webconsole frontend.
|
||||
pref("devtools.hud.loglimit.network", 1000);
|
||||
pref("devtools.hud.loglimit.cssparser", 1000);
|
||||
pref("devtools.hud.loglimit.exception", 1000);
|
||||
pref("devtools.hud.loglimit.console", 1000);
|
||||
|
||||
// By how many times eyedropper will magnify pixels
|
||||
pref("devtools.eyedropper.zoom", 6);
|
||||
|
@ -19,10 +19,22 @@
|
||||
}
|
||||
|
||||
.tab-close-button[pinned],
|
||||
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([visuallyselected="true"]) {
|
||||
.tabbrowser-tabs[closebuttons="activetab"] > * > * > * > .tab-close-button:not([visuallyselected="true"]),
|
||||
.tab-icon-image:not([src]):not([pinned]):not([crashed]),
|
||||
.tab-icon-image[busy],
|
||||
.tab-throbber:not([busy]),
|
||||
.tab-icon-sound:not([soundplaying]):not([muted]),
|
||||
.tab-icon-sound[pinned],
|
||||
.tab-icon-overlay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned],
|
||||
.tab-icon-overlay[muted][pinned],
|
||||
.tab-icon-overlay[crashed] {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
.tab-label[pinned] {
|
||||
width: 0;
|
||||
margin-left: 0 !important;
|
||||
@ -51,13 +63,6 @@ tabpanels {
|
||||
}
|
||||
}
|
||||
|
||||
.tab-icon-image:not([src]):not([pinned]):not([crashed]),
|
||||
.tab-throbber:not([busy]),
|
||||
.tab-icon-image[busy],
|
||||
.tab-icon-overlay[busy] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.closing-tabs-spacer {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
"curly": [2, "all"],
|
||||
"dot-location": [2, "property"],
|
||||
"eol-last": 2,
|
||||
"eqeqeq": 0, // TBD. Might need to be separate for content & chrome
|
||||
"eqeqeq": [2, "smart"],
|
||||
"key-spacing": [2, {"beforeColon": false, "afterColon": true }],
|
||||
"linebreak-style": [2, "unix"],
|
||||
"new-cap": 0, // TODO: set to 2
|
||||
|
@ -58,6 +58,7 @@
|
||||
"rules": {
|
||||
"arrow-parens": 0, // TBD
|
||||
"arrow-spacing": 2,
|
||||
"eqeqeq": 0, // TBD
|
||||
"generator-star-spacing": [2, "after"],
|
||||
// We should fix the errors and enable this (set to 2)
|
||||
"no-var": 0,
|
||||
|
@ -53,7 +53,7 @@ loop.Client = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
if (properties.length == 1) {
|
||||
if (properties.length === 1) {
|
||||
return data[properties[0]];
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
canEdit: function() {
|
||||
// We cannot modify imported contacts. For the moment, the check for
|
||||
// determining whether the contact is imported is based on its category.
|
||||
return this.props.contact.category[0] != "google";
|
||||
return this.props.contact.category[0] !== "google";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -417,7 +417,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
let profile = this.props.mozLoop.userProfile;
|
||||
let currUid = this._userProfile ? this._userProfile.uid : null;
|
||||
let newUid = profile ? profile.uid : null;
|
||||
if (currUid != newUid) {
|
||||
if (currUid !== newUid) {
|
||||
// On profile change (login, logout), reload all contacts.
|
||||
this._userProfile = profile;
|
||||
// The following will do a forceUpdate() for us.
|
||||
@ -750,7 +750,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: contentAreaClasses},
|
||||
React.createElement("header", null, this.props.mode == "add"
|
||||
React.createElement("header", null, this.props.mode === "add"
|
||||
? mozL10n.get("add_contact_title")
|
||||
: mozL10n.get("edit_contact_title")),
|
||||
React.createElement("div", {className: cx({"form-content-container": true})},
|
||||
@ -779,7 +779,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
caption: mozL10n.get("cancel_button"),
|
||||
onClick: this.handleCancelButtonClick}),
|
||||
React.createElement(Button, {additionalClass: "button-accept",
|
||||
caption: this.props.mode == "add"
|
||||
caption: this.props.mode === "add"
|
||||
? mozL10n.get("add_contact_button")
|
||||
: mozL10n.get("edit_contact_done_button"),
|
||||
onClick: this.handleAcceptButtonClick})
|
||||
|
@ -271,7 +271,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
canEdit: function() {
|
||||
// We cannot modify imported contacts. For the moment, the check for
|
||||
// determining whether the contact is imported is based on its category.
|
||||
return this.props.contact.category[0] != "google";
|
||||
return this.props.contact.category[0] !== "google";
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -417,7 +417,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
let profile = this.props.mozLoop.userProfile;
|
||||
let currUid = this._userProfile ? this._userProfile.uid : null;
|
||||
let newUid = profile ? profile.uid : null;
|
||||
if (currUid != newUid) {
|
||||
if (currUid !== newUid) {
|
||||
// On profile change (login, logout), reload all contacts.
|
||||
this._userProfile = profile;
|
||||
// The following will do a forceUpdate() for us.
|
||||
@ -750,7 +750,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
|
||||
return (
|
||||
<div className={contentAreaClasses}>
|
||||
<header>{this.props.mode == "add"
|
||||
<header>{this.props.mode === "add"
|
||||
? mozL10n.get("add_contact_title")
|
||||
: mozL10n.get("edit_contact_title")}</header>
|
||||
<div className={cx({"form-content-container": true})}>
|
||||
@ -779,7 +779,7 @@ loop.contacts = (function(_, mozL10n) {
|
||||
caption={mozL10n.get("cancel_button")}
|
||||
onClick={this.handleCancelButtonClick} />
|
||||
<Button additionalClass="button-accept"
|
||||
caption={this.props.mode == "add"
|
||||
caption={this.props.mode === "add"
|
||||
? mozL10n.get("add_contact_button")
|
||||
: mozL10n.get("edit_contact_done_button")}
|
||||
onClick={this.handleAcceptButtonClick} />
|
||||
|
@ -79,7 +79,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
if (this.props.buttonsHidden.indexOf(tabName) > -1) {
|
||||
return;
|
||||
}
|
||||
var isSelected = (this.state.selectedTab == tabName);
|
||||
var isSelected = (this.state.selectedTab === tabName);
|
||||
if (!tab.props.hidden) {
|
||||
var label = mozL10n.get(tabName + "_tab_button");
|
||||
tabButtons.push(
|
||||
@ -861,7 +861,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
var profile = this.props.mozLoop.userProfile;
|
||||
var currUid = this.state.userProfile ? this.state.userProfile.uid : null;
|
||||
var newUid = profile ? profile.uid : null;
|
||||
if (currUid == newUid) {
|
||||
if (currUid === newUid) {
|
||||
// Update the state of hasEncryptionKey as this might have changed now.
|
||||
this.setState({hasEncryptionKey: this.props.mozLoop.hasEncryptionKey});
|
||||
} else {
|
||||
|
@ -79,7 +79,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
if (this.props.buttonsHidden.indexOf(tabName) > -1) {
|
||||
return;
|
||||
}
|
||||
var isSelected = (this.state.selectedTab == tabName);
|
||||
var isSelected = (this.state.selectedTab === tabName);
|
||||
if (!tab.props.hidden) {
|
||||
var label = mozL10n.get(tabName + "_tab_button");
|
||||
tabButtons.push(
|
||||
@ -861,7 +861,7 @@ loop.panel = (function(_, mozL10n) {
|
||||
var profile = this.props.mozLoop.userProfile;
|
||||
var currUid = this.state.userProfile ? this.state.userProfile.uid : null;
|
||||
var newUid = profile ? profile.uid : null;
|
||||
if (currUid == newUid) {
|
||||
if (currUid === newUid) {
|
||||
// Update the state of hasEncryptionKey as this might have changed now.
|
||||
this.setState({hasEncryptionKey: this.props.mozLoop.hasEncryptionKey});
|
||||
} else {
|
||||
|
@ -496,7 +496,7 @@ loop.store = loop.store || {};
|
||||
var context = room.decryptedContext;
|
||||
var oldRoomName = context.roomName;
|
||||
var newRoomName = actionData.newRoomName.trim();
|
||||
if (newRoomName && oldRoomName != newRoomName) {
|
||||
if (newRoomName && oldRoomName !== newRoomName) {
|
||||
roomData.roomName = newRoomName;
|
||||
}
|
||||
var oldRoomURLs = context.urls;
|
||||
|
@ -94,7 +94,7 @@ loop.roomViews = (function(mozL10n) {
|
||||
var origin = event.currentTarget.dataset.provider;
|
||||
var provider = this.props.socialShareProviders
|
||||
.filter(function(socialProvider) {
|
||||
return socialProvider.origin == origin;
|
||||
return socialProvider.origin === origin;
|
||||
})[0];
|
||||
|
||||
this.props.dispatcher.dispatch(new sharedActions.ShareRoomUrl({
|
||||
|
@ -94,7 +94,7 @@ loop.roomViews = (function(mozL10n) {
|
||||
var origin = event.currentTarget.dataset.provider;
|
||||
var provider = this.props.socialShareProviders
|
||||
.filter(function(socialProvider) {
|
||||
return socialProvider.origin == origin;
|
||||
return socialProvider.origin === origin;
|
||||
})[0];
|
||||
|
||||
this.props.dispatcher.dispatch(new sharedActions.ShareRoomUrl({
|
||||
|
@ -550,10 +550,8 @@ html[dir="rtl"] .context-content {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
line-height: 1.1em;
|
||||
}
|
||||
|
||||
.context-wrapper:hover {
|
||||
background-color: #dbf7ff;
|
||||
/* No underline for the text in the context view. */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.context-wrapper > .context-preview {
|
||||
@ -571,7 +569,7 @@ html[dir="rtl"] .context-wrapper > .context-preview {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.context-wrapper > .context-description {
|
||||
.context-wrapper > .context-info {
|
||||
flex: 0 1 auto;
|
||||
display: block;
|
||||
color: black;
|
||||
@ -580,9 +578,18 @@ html[dir="rtl"] .context-wrapper > .context-preview {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.context-wrapper > .context-description > .context-url {
|
||||
.context-wrapper > .context-info > .context-url {
|
||||
display: block;
|
||||
color: #00a9dc;
|
||||
font-weight: 700;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clicks-allowed.context-wrapper:hover {
|
||||
background-color: #dbf7ff;
|
||||
}
|
||||
|
||||
/* Only underline the url, not the associated text */
|
||||
.clicks-allowed.context-wrapper:hover > .context-info > .context-url {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
@ -899,9 +899,9 @@ body[platform="win"] .share-service-dropdown.overflow > .dropdown-menu-item {
|
||||
}
|
||||
|
||||
.context-url-view-wrapper {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
padding-bottom: 0.5em;
|
||||
/* 18px for indent of .text-chat-arrow, 1px for border of .text-chat-entry > p,
|
||||
0.5rem for padding of .text-chat-entry > p */
|
||||
padding: calc(18px - 1px - 0.5rem);
|
||||
margin-bottom: 0.5em;
|
||||
background-color: #E8F6FE;
|
||||
}
|
||||
@ -1401,28 +1401,6 @@ html[dir="rtl"] .room-context-btn-close {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.standalone-context-url {
|
||||
color: #fff;
|
||||
/* Try and keep clear of local video */
|
||||
height: 40%;
|
||||
}
|
||||
|
||||
.standalone-context-url.screen-share-active {
|
||||
/* Try and keep clear of remote video when screensharing */
|
||||
height: 15%;
|
||||
}
|
||||
|
||||
.standalone-context-url > img {
|
||||
margin: 1em auto;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.standalone-context-url-description-wrapper {
|
||||
/* So that we can use max-height for the image */
|
||||
height: 20%;
|
||||
}
|
||||
|
||||
.standalone .room-conversation .media {
|
||||
background: #000;
|
||||
}
|
||||
@ -1480,12 +1458,14 @@ html[dir="rtl"] .text-chat-entry {
|
||||
margin-left: .2em;
|
||||
}
|
||||
|
||||
/* If you change this entry, check it doesn't affect the "special" text
|
||||
chat entries as well (.speical, .room-name, .context-url-view-wrapper */
|
||||
.text-chat-entry > p {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
/* Drop the default margins from the 'p' element. */
|
||||
margin: 0;
|
||||
padding: .7em;
|
||||
padding: .5rem;
|
||||
/* leave some room for the chat bubble arrow */
|
||||
max-width: 80%;
|
||||
border-width: 1px;
|
||||
@ -1647,12 +1627,17 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
font-weight: bold;
|
||||
text-align: start;
|
||||
background-color: #E8F6FE;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.text-chat-entry.special.room-name p {
|
||||
background: #E8F6FE;
|
||||
max-width: 100%;
|
||||
/* 18px for indent of .text-chat-arrow, 1px for border of .text-chat-entry > p,
|
||||
0.5rem for padding of .text-chat-entry > p */
|
||||
padding: calc(18px - 1px - 0.5rem);
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.text-chat-entry.special > p {
|
||||
@ -1666,7 +1651,7 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
.text-chat-box > form > input {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0 .5em .5em;
|
||||
padding: 0 .4rem .4rem;
|
||||
font-size: 1.1em;
|
||||
border: 0;
|
||||
border-top: 1px solid #d8d8d8;
|
||||
@ -1703,12 +1688,6 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
}
|
||||
|
||||
@media screen and (max-width:640px) {
|
||||
.standalone-context-url {
|
||||
/* XXX We haven't got UX for standalone yet, so temporarily not displaying
|
||||
on narrow window widths. See bug 1153827. */
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Rooms specific responsive styling */
|
||||
.standalone .room-conversation {
|
||||
background: #000;
|
||||
@ -1749,7 +1728,6 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
/* e.g. very narrow widths similar to conversation window */
|
||||
@media screen and (max-width:300px) {
|
||||
.text-chat-view {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
/* 120px max-height of .text-chat-entries plus 40px of .text-chat-box */
|
||||
@ -1758,8 +1736,11 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
min-height: 100px;
|
||||
/* The !important is to override the values defined above which have more
|
||||
specificity when we fix bug 1184559, we should be able to remove it,
|
||||
but this should be tests first. */
|
||||
but this should be tested first. */
|
||||
height: auto !important;
|
||||
/* Let the view be the minimum size it needs to be - don't flex to take up
|
||||
more. */
|
||||
flex: 0 0 auto !important;
|
||||
}
|
||||
|
||||
.text-chat-entries {
|
||||
@ -1771,6 +1752,12 @@ html[dir="rtl"] .text-chat-entry.received .text-chat-arrow {
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.text-chat-view.text-chat-disabled {
|
||||
/* When we don't have text chat enabled, limit the view to the same height
|
||||
as the entries, to avoid unnecessary whitespace */
|
||||
max-height: 120px;
|
||||
}
|
||||
|
||||
.text-chat-entries-empty.text-chat-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ loop.store = loop.store || {};
|
||||
if (err) {
|
||||
console.error("Failed to get outgoing call data", err);
|
||||
var failureReason = "setup";
|
||||
if (err.errno == REST_ERRNOS.USER_UNAVAILABLE) {
|
||||
if (err.errno === REST_ERRNOS.USER_UNAVAILABLE) {
|
||||
failureReason = REST_ERRNOS.USER_UNAVAILABLE;
|
||||
}
|
||||
this.dispatcher.dispatch(
|
||||
|
@ -923,9 +923,9 @@ loop.OTSdkDriver = (function() {
|
||||
* Handles publishing of property changes to a stream.
|
||||
*/
|
||||
_onStreamPropertyChanged: function(event) {
|
||||
if (event.changedProperty == STREAM_PROPERTIES.VIDEO_DIMENSIONS) {
|
||||
if (event.changedProperty === STREAM_PROPERTIES.VIDEO_DIMENSIONS) {
|
||||
this.dispatcher.dispatch(new sharedActions.VideoDimensionsChanged({
|
||||
isLocal: event.stream.connection.id == this.session.connection.id,
|
||||
isLocal: event.stream.connection.id === this.session.connection.id,
|
||||
videoType: event.stream.videoType,
|
||||
dimensions: event.stream[STREAM_PROPERTIES.VIDEO_DIMENSIONS]
|
||||
}));
|
||||
@ -1084,8 +1084,8 @@ loop.OTSdkDriver = (function() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (startTime == this.CONNECTION_START_TIME_ALREADY_NOTED ||
|
||||
startTime == this.CONNECTION_START_TIME_UNINITIALIZED ||
|
||||
if (startTime === this.CONNECTION_START_TIME_ALREADY_NOTED ||
|
||||
startTime === this.CONNECTION_START_TIME_UNINITIALIZED ||
|
||||
startTime > endTime) {
|
||||
if (this._debugTwoWayMediaTelemetry) {
|
||||
console.log("_noteConnectionLengthIfNeeded called with " +
|
||||
|
@ -122,7 +122,7 @@ loop.store.TextChatStore = (function() {
|
||||
|
||||
// Notify MozLoopService if appropriate that a message has been appended
|
||||
// and it should therefore check if we need a different sized window or not.
|
||||
if (message.contentType != CHAT_CONTENT_TYPES.ROOM_NAME) {
|
||||
if (message.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME) {
|
||||
window.dispatchEvent(new CustomEvent("LoopChatMessageAppended"));
|
||||
}
|
||||
},
|
||||
@ -135,7 +135,7 @@ loop.store.TextChatStore = (function() {
|
||||
receivedTextChatMessage: function(actionData) {
|
||||
// If we don't know how to deal with this content, then skip it
|
||||
// as this version doesn't support it.
|
||||
if (actionData.contentType != CHAT_CONTENT_TYPES.TEXT) {
|
||||
if (actionData.contentType !== CHAT_CONTENT_TYPES.TEXT) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -116,13 +116,21 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
};
|
||||
},
|
||||
|
||||
_hasChatMessages: function() {
|
||||
return this.props.messageList.some(function(message) {
|
||||
return message.contentType === CHAT_CONTENT_TYPES.TEXT;
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUpdate: function() {
|
||||
var node = this.getDOMNode();
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
// Scroll only if we're right at the bottom of the display.
|
||||
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||
// Scroll only if we're right at the bottom of the display, or if we've
|
||||
// not had any chat messages so far.
|
||||
this.shouldScroll = !this._hasChatMessages() ||
|
||||
node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
@ -138,7 +146,9 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
if (this.shouldScroll) {
|
||||
// Don't scroll if we haven't got any chat messages yet - e.g. for context
|
||||
// display, we want to display starting at the top.
|
||||
if (this.shouldScroll && this._hasChatMessages()) {
|
||||
// This ensures the paint is complete.
|
||||
window.requestAnimationFrame(function() {
|
||||
try {
|
||||
@ -370,21 +380,21 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
|
||||
render: function() {
|
||||
var messageList;
|
||||
var hasNonSpecialMessages;
|
||||
|
||||
if (this.props.showRoomName) {
|
||||
messageList = this.state.messageList;
|
||||
hasNonSpecialMessages = messageList.some(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL;
|
||||
});
|
||||
} else {
|
||||
messageList = this.state.messageList.filter(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
|
||||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
});
|
||||
hasNonSpecialMessages = !!messageList.length;
|
||||
}
|
||||
|
||||
// Only show the placeholder if we've sent messages.
|
||||
var hasSentMessages = messageList.some(function(item) {
|
||||
return item.type === CHAT_MESSAGE_TYPES.SENT;
|
||||
});
|
||||
|
||||
var textChatViewClasses = React.addons.classSet({
|
||||
"text-chat-view": true,
|
||||
"text-chat-disabled": !this.state.textChatEnabled,
|
||||
@ -399,7 +409,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
useDesktopPaths: this.props.useDesktopPaths}),
|
||||
React.createElement(TextChatInputView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
showPlaceholder: !hasNonSpecialMessages,
|
||||
showPlaceholder: !hasSentMessages,
|
||||
textChatEnabled: this.state.textChatEnabled})
|
||||
)
|
||||
);
|
||||
|
@ -116,13 +116,21 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
};
|
||||
},
|
||||
|
||||
_hasChatMessages: function() {
|
||||
return this.props.messageList.some(function(message) {
|
||||
return message.contentType === CHAT_CONTENT_TYPES.TEXT;
|
||||
});
|
||||
},
|
||||
|
||||
componentWillUpdate: function() {
|
||||
var node = this.getDOMNode();
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
// Scroll only if we're right at the bottom of the display.
|
||||
this.shouldScroll = node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||
// Scroll only if we're right at the bottom of the display, or if we've
|
||||
// not had any chat messages so far.
|
||||
this.shouldScroll = !this._hasChatMessages() ||
|
||||
node.scrollHeight === node.scrollTop + node.clientHeight;
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
@ -138,7 +146,9 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
if (this.shouldScroll) {
|
||||
// Don't scroll if we haven't got any chat messages yet - e.g. for context
|
||||
// display, we want to display starting at the top.
|
||||
if (this.shouldScroll && this._hasChatMessages()) {
|
||||
// This ensures the paint is complete.
|
||||
window.requestAnimationFrame(function() {
|
||||
try {
|
||||
@ -370,21 +380,21 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
|
||||
render: function() {
|
||||
var messageList;
|
||||
var hasNonSpecialMessages;
|
||||
|
||||
if (this.props.showRoomName) {
|
||||
messageList = this.state.messageList;
|
||||
hasNonSpecialMessages = messageList.some(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL;
|
||||
});
|
||||
} else {
|
||||
messageList = this.state.messageList.filter(function(item) {
|
||||
return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
|
||||
item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME;
|
||||
});
|
||||
hasNonSpecialMessages = !!messageList.length;
|
||||
}
|
||||
|
||||
// Only show the placeholder if we've sent messages.
|
||||
var hasSentMessages = messageList.some(function(item) {
|
||||
return item.type === CHAT_MESSAGE_TYPES.SENT;
|
||||
});
|
||||
|
||||
var textChatViewClasses = React.addons.classSet({
|
||||
"text-chat-view": true,
|
||||
"text-chat-disabled": !this.state.textChatEnabled,
|
||||
@ -399,7 +409,7 @@ loop.shared.views.chat = (function(mozL10n) {
|
||||
useDesktopPaths={this.props.useDesktopPaths} />
|
||||
<TextChatInputView
|
||||
dispatcher={this.props.dispatcher}
|
||||
showPlaceholder={!hasNonSpecialMessages}
|
||||
showPlaceholder={!hasSentMessages}
|
||||
textChatEnabled={this.state.textChatEnabled} />
|
||||
</div>
|
||||
);
|
||||
|
@ -687,7 +687,7 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
|
||||
var prop;
|
||||
for (var i = 0, lA = propsA.length; i < lA; ++i) {
|
||||
prop = propsA[i];
|
||||
if (propsB.indexOf(prop) == -1) {
|
||||
if (propsB.indexOf(prop) === -1) {
|
||||
diff.removed.push(prop);
|
||||
} else if (a[prop] !== b[prop]) {
|
||||
diff.updated.push(prop);
|
||||
@ -696,7 +696,7 @@ var inChrome = typeof Components != "undefined" && "utils" in Components;
|
||||
|
||||
for (var j = 0, lB = propsB.length; j < lB; ++j) {
|
||||
prop = propsB[j];
|
||||
if (propsA.indexOf(prop) == -1) {
|
||||
if (propsA.indexOf(prop) === -1) {
|
||||
diff.added.push(prop);
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ loop.validate = (function() {
|
||||
try {
|
||||
return typeof Type === "undefined" || // skip checking
|
||||
Type === null && value === null || // null type
|
||||
value.constructor == Type || // native type
|
||||
value.constructor === Type || // native type
|
||||
Type.prototype.isPrototypeOf(value) || // custom type
|
||||
typeName(value) === typeName(Type); // type string eq.
|
||||
} catch (e) {
|
||||
|
@ -813,18 +813,25 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
"shared/img/icons-16x16.svg#globe";
|
||||
}
|
||||
|
||||
var wrapperClasses = React.addons.classSet({
|
||||
"context-wrapper": true,
|
||||
"clicks-allowed": this.props.allowClick
|
||||
});
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "context-content"},
|
||||
this.renderContextTitle(),
|
||||
React.createElement("div", {className: "context-wrapper"},
|
||||
React.createElement("img", {className: "context-preview", src: thumbnail}),
|
||||
React.createElement("span", {className: "context-description"},
|
||||
this.props.description,
|
||||
React.createElement("a", {className: "context-url",
|
||||
React.createElement("a", {className: wrapperClasses,
|
||||
href: this.props.allowClick ? this.props.url : null,
|
||||
onClick: this.handleLinkClick,
|
||||
rel: "noreferrer",
|
||||
target: "_blank"}, hostname)
|
||||
target: "_blank"},
|
||||
React.createElement("img", {className: "context-preview", src: thumbnail}),
|
||||
React.createElement("span", {className: "context-info"},
|
||||
this.props.description,
|
||||
React.createElement("span", {className: "context-url"},
|
||||
hostname
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -988,7 +995,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
// This is all for the ui-showcase's benefit.
|
||||
if (this.props.matchMedia != nextProps.matchMedia) {
|
||||
if (this.props.matchMedia !== nextProps.matchMedia) {
|
||||
this.updateLocalMediaState(null, nextProps.matchMedia);
|
||||
}
|
||||
},
|
||||
@ -1003,7 +1010,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
updateLocalMediaState: function(event, matchMedia) {
|
||||
var newState = this.isLocalMediaAbsolutelyPositioned(matchMedia);
|
||||
if (this.state.localMediaAboslutelyPositioned != newState) {
|
||||
if (this.state.localMediaAboslutelyPositioned !== newState) {
|
||||
this.setState({
|
||||
localMediaAboslutelyPositioned: newState
|
||||
});
|
||||
|
@ -813,20 +813,27 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
"shared/img/icons-16x16.svg#globe";
|
||||
}
|
||||
|
||||
var wrapperClasses = React.addons.classSet({
|
||||
"context-wrapper": true,
|
||||
"clicks-allowed": this.props.allowClick
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="context-content">
|
||||
{this.renderContextTitle()}
|
||||
<div className="context-wrapper">
|
||||
<img className="context-preview" src={thumbnail} />
|
||||
<span className="context-description">
|
||||
{this.props.description}
|
||||
<a className="context-url"
|
||||
<a className={wrapperClasses}
|
||||
href={this.props.allowClick ? this.props.url : null}
|
||||
onClick={this.handleLinkClick}
|
||||
rel="noreferrer"
|
||||
target="_blank">{hostname}</a>
|
||||
target="_blank">
|
||||
<img className="context-preview" src={thumbnail} />
|
||||
<span className="context-info">
|
||||
{this.props.description}
|
||||
<span className="context-url">
|
||||
{hostname}
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -988,7 +995,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
// This is all for the ui-showcase's benefit.
|
||||
if (this.props.matchMedia != nextProps.matchMedia) {
|
||||
if (this.props.matchMedia !== nextProps.matchMedia) {
|
||||
this.updateLocalMediaState(null, nextProps.matchMedia);
|
||||
}
|
||||
},
|
||||
@ -1003,7 +1010,7 @@ loop.shared.views = (function(_, mozL10n) {
|
||||
|
||||
updateLocalMediaState: function(event, matchMedia) {
|
||||
var newState = this.isLocalMediaAbsolutelyPositioned(matchMedia);
|
||||
if (this.state.localMediaAboslutelyPositioned != newState) {
|
||||
if (this.state.localMediaAboslutelyPositioned !== newState) {
|
||||
this.setState({
|
||||
localMediaAboslutelyPositioned: newState
|
||||
});
|
||||
|
@ -50,7 +50,8 @@ loop.store.StandaloneMetricsStore = (function() {
|
||||
"mediaConnected",
|
||||
"recordClick",
|
||||
"remotePeerConnected",
|
||||
"retryAfterRoomFailure"
|
||||
"retryAfterRoomFailure",
|
||||
"windowUnload"
|
||||
],
|
||||
|
||||
/**
|
||||
@ -257,6 +258,17 @@ loop.store.StandaloneMetricsStore = (function() {
|
||||
var muteState = muted ? "mute" : "unmute";
|
||||
|
||||
this._storeEvent(METRICS_GA_CATEGORY.general, muteType, muteState);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the window is unloaded, either by code, or by the user
|
||||
* explicitly closing it. Expected to do any necessary housekeeping, such
|
||||
* as shutting down the call cleanly and adding any relevant telemetry data.
|
||||
*/
|
||||
windowUnload: function() {
|
||||
if (this.activeRoomStore) {
|
||||
this.stopListening(this.activeRoomStore);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -90,6 +90,29 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
roomUsed: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// Watch for messages from the waiting-tile iframe
|
||||
window.addEventListener("message", this.recordTileClick);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
window.removeEventListener("message", this.recordTileClick);
|
||||
},
|
||||
|
||||
recordTileClick: function(event) {
|
||||
if (event.data === "tile-click") {
|
||||
this.props.dispatcher.dispatch(new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles iframe click"
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
recordTilesSupport: function() {
|
||||
this.props.dispatcher.dispatch(new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles support link click"
|
||||
}));
|
||||
},
|
||||
|
||||
_renderCallToActionLink: function() {
|
||||
if (this.props.isFirefox) {
|
||||
return (
|
||||
@ -155,7 +178,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
React.createElement("p", {className: "room-waiting-area"},
|
||||
mozL10n.get("rooms_read_while_wait_offer"),
|
||||
React.createElement("a", {href: loop.config.tilesSupportUrl,
|
||||
onClick: this.recordClick,
|
||||
onClick: this.recordTilesSupport,
|
||||
rel: "noreferrer",
|
||||
target: "_blank"},
|
||||
React.createElement("i", {className: "room-waiting-help"})
|
||||
@ -414,6 +437,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
|
||||
case ROOM_STATES.FAILED:
|
||||
case ROOM_STATES.CLOSING:
|
||||
case ROOM_STATES.FULL:
|
||||
case ROOM_STATES.ENDED:
|
||||
// the other person has shown up, so we don't want to show an avatar
|
||||
return true;
|
||||
|
||||
@ -519,6 +544,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
return {
|
||||
StandaloneRoomFooter: StandaloneRoomFooter,
|
||||
StandaloneRoomHeader: StandaloneRoomHeader,
|
||||
StandaloneRoomInfoArea: StandaloneRoomInfoArea,
|
||||
StandaloneRoomView: StandaloneRoomView
|
||||
};
|
||||
})(navigator.mozL10n);
|
||||
|
@ -90,6 +90,29 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
roomUsed: React.PropTypes.bool.isRequired
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// Watch for messages from the waiting-tile iframe
|
||||
window.addEventListener("message", this.recordTileClick);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
window.removeEventListener("message", this.recordTileClick);
|
||||
},
|
||||
|
||||
recordTileClick: function(event) {
|
||||
if (event.data === "tile-click") {
|
||||
this.props.dispatcher.dispatch(new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles iframe click"
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
||||
recordTilesSupport: function() {
|
||||
this.props.dispatcher.dispatch(new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles support link click"
|
||||
}));
|
||||
},
|
||||
|
||||
_renderCallToActionLink: function() {
|
||||
if (this.props.isFirefox) {
|
||||
return (
|
||||
@ -155,7 +178,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
<p className="room-waiting-area">
|
||||
{mozL10n.get("rooms_read_while_wait_offer")}
|
||||
<a href={loop.config.tilesSupportUrl}
|
||||
onClick={this.recordClick}
|
||||
onClick={this.recordTilesSupport}
|
||||
rel="noreferrer"
|
||||
target="_blank">
|
||||
<i className="room-waiting-help"></i>
|
||||
@ -414,6 +437,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
|
||||
case ROOM_STATES.FAILED:
|
||||
case ROOM_STATES.CLOSING:
|
||||
case ROOM_STATES.FULL:
|
||||
case ROOM_STATES.ENDED:
|
||||
// the other person has shown up, so we don't want to show an avatar
|
||||
return true;
|
||||
|
||||
@ -519,6 +544,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
||||
return {
|
||||
StandaloneRoomFooter: StandaloneRoomFooter,
|
||||
StandaloneRoomHeader: StandaloneRoomHeader,
|
||||
StandaloneRoomInfoArea: StandaloneRoomInfoArea,
|
||||
StandaloneRoomView: StandaloneRoomView
|
||||
};
|
||||
})(navigator.mozL10n);
|
||||
|
@ -93,7 +93,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
render: function() {
|
||||
if (this.props.isFirefox) {
|
||||
return React.createElement("div", null);
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
React.createElement("div", {className: "promote-firefox"},
|
||||
@ -649,8 +649,8 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
React.PropTypes.instanceOf(FxOSConversationModel)
|
||||
]).isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
|
||||
.isRequired,
|
||||
isFirefox: React.PropTypes.bool.isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection).isRequired,
|
||||
sdk: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
@ -738,7 +738,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
}
|
||||
case "expired": {
|
||||
return (
|
||||
React.createElement(CallUrlExpiredView, null)
|
||||
React.createElement(CallUrlExpiredView, {isFirefox: this.props.isFirefox})
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@ -986,6 +986,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
client: this.props.client,
|
||||
conversation: this.props.conversation,
|
||||
dispatcher: this.props.dispatcher,
|
||||
isFirefox: this.state.isFirefox,
|
||||
notifications: this.props.notifications,
|
||||
sdk: this.props.sdk})
|
||||
);
|
||||
|
@ -93,7 +93,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
|
||||
render: function() {
|
||||
if (this.props.isFirefox) {
|
||||
return <div />;
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="promote-firefox">
|
||||
@ -649,8 +649,8 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
React.PropTypes.instanceOf(FxOSConversationModel)
|
||||
]).isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
|
||||
.isRequired,
|
||||
isFirefox: React.PropTypes.bool.isRequired,
|
||||
notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection).isRequired,
|
||||
sdk: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
@ -738,7 +738,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
}
|
||||
case "expired": {
|
||||
return (
|
||||
<CallUrlExpiredView />
|
||||
<CallUrlExpiredView isFirefox={this.props.isFirefox}/>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
@ -986,6 +986,7 @@ loop.webapp = (function($, _, OT, mozL10n) {
|
||||
client={this.props.client}
|
||||
conversation={this.props.conversation}
|
||||
dispatcher={this.props.dispatcher}
|
||||
isFirefox={this.state.isFirefox}
|
||||
notifications={this.props.notifications}
|
||||
sdk={this.props.sdk} />
|
||||
);
|
||||
|
@ -112,7 +112,7 @@ describe("loop.Client", function() {
|
||||
|
||||
sinon.assert.calledOnce(callback);
|
||||
sinon.assert.calledWithExactly(callback, sinon.match(function(err) {
|
||||
return err.code == 400 && err.message == "invalid token";
|
||||
return err.code === 400 && err.message === "invalid token";
|
||||
}));
|
||||
});
|
||||
|
||||
|
@ -87,21 +87,21 @@ describe("loop.contacts", function() {
|
||||
navigator.mozLoop = {
|
||||
getStrings: function(entityName) {
|
||||
var textContentValue = "fakeText";
|
||||
if (entityName == "add_contact_title") {
|
||||
if (entityName === "add_contact_title") {
|
||||
textContentValue = fakeAddContactTitleText;
|
||||
} else if (entityName == "add_contact_button") {
|
||||
} else if (entityName === "add_contact_button") {
|
||||
textContentValue = fakeAddContactButtonText;
|
||||
} else if (entityName == "edit_contact_title") {
|
||||
} else if (entityName === "edit_contact_title") {
|
||||
textContentValue = fakeEditContactButtonText;
|
||||
} else if (entityName == "edit_contact_done_button") {
|
||||
} else if (entityName === "edit_contact_done_button") {
|
||||
textContentValue = fakeDoneButtonText;
|
||||
}
|
||||
return JSON.stringify({textContent: textContentValue});
|
||||
},
|
||||
getLoopPref: function(pref) {
|
||||
if (pref == "contacts.gravatars.promo") {
|
||||
if (pref === "contacts.gravatars.promo") {
|
||||
return true;
|
||||
} else if (pref == "contacts.gravatars.show") {
|
||||
} else if (pref === "contacts.gravatars.show") {
|
||||
return false;
|
||||
}
|
||||
return "";
|
||||
@ -170,9 +170,9 @@ describe("loop.contacts", function() {
|
||||
|
||||
it("should not show the gravatars promo box when the 'contacts.gravatars.promo' pref is set", function() {
|
||||
sandbox.stub(navigator.mozLoop, "getLoopPref", function(pref) {
|
||||
if (pref == "contacts.gravatars.promo") {
|
||||
if (pref === "contacts.gravatars.promo") {
|
||||
return false;
|
||||
} else if (pref == "contacts.gravatars.show") {
|
||||
} else if (pref === "contacts.gravatars.show") {
|
||||
return true;
|
||||
}
|
||||
return "";
|
||||
|
@ -26,7 +26,7 @@ describe("loop.conversation", function() {
|
||||
},
|
||||
setLoopPref: setLoopPrefStub,
|
||||
getLoopPref: function(prefName) {
|
||||
if (prefName == "debug.sdk") {
|
||||
if (prefName === "debug.sdk") {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -295,7 +295,7 @@ describe("loop.roomViews", function () {
|
||||
beforeEach(function() {
|
||||
sandbox.stub(dispatcher, "dispatch");
|
||||
fakeMozLoop.getLoopPref = function(prefName) {
|
||||
if (prefName == "contextInConversations.enabled") {
|
||||
if (prefName === "contextInConversations.enabled") {
|
||||
return true;
|
||||
}
|
||||
return "test";
|
||||
|
@ -14,6 +14,7 @@
|
||||
<li><a href="desktop-local/">Local tests</a></li>
|
||||
<li><a href="standalone/">Standalone tests</a></li>
|
||||
<li><a href="coverage/">Code Coverage</a></li>
|
||||
<li><a href="../ui/">UI Showcase</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -5,4 +5,7 @@
|
||||
// DOMContentLoaded proved to lead to race conditions.
|
||||
|
||||
sinon.stub(document, "addEventListener");
|
||||
console.log("[stubs.js] addEventListener stubbed to prevent race conditions");
|
||||
console.log("[head.js] addEventListener stubbed to prevent race conditions");
|
||||
|
||||
document.body.appendChild(document.createElement("div")).id = "fixtures";
|
||||
console.log("[head.js] div#fixtures added to attach DOM elements");
|
@ -16,7 +16,7 @@ module.exports = function(config) {
|
||||
"content/shared/libs/lodash-3.9.3.js",
|
||||
"content/shared/libs/backbone-1.2.1.js",
|
||||
"test/shared/vendor/*.js",
|
||||
"test/karma/stubs.js", // Stub out DOM event listener due to races.
|
||||
"test/karma/head.js", // Stub out DOM event listener due to races.
|
||||
"content/shared/js/utils.js",
|
||||
"content/shared/js/models.js",
|
||||
"content/shared/js/mixins.js",
|
||||
|
@ -17,6 +17,7 @@ module.exports = function(config) {
|
||||
"content/shared/libs/react-0.12.2.js",
|
||||
"content/shared/libs/sdk.js",
|
||||
"test/shared/vendor/*.js",
|
||||
"test/karma/head.js", // Add test fixture container
|
||||
"content/shared/js/utils.js",
|
||||
"content/shared/js/store.js",
|
||||
"content/shared/js/models.js",
|
||||
|
@ -10,6 +10,7 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
var TestUtils = React.addons.TestUtils;
|
||||
var CHAT_MESSAGE_TYPES = loop.store.CHAT_MESSAGE_TYPES;
|
||||
var CHAT_CONTENT_TYPES = loop.store.CHAT_CONTENT_TYPES;
|
||||
var fixtures = document.querySelector("#fixtures");
|
||||
|
||||
var dispatcher, fakeSdkDriver, sandbox, store, fakeClock;
|
||||
|
||||
@ -35,6 +36,7 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.restore();
|
||||
React.unmountComponentAtNode(fixtures);
|
||||
});
|
||||
|
||||
describe("TextChatEntriesView", function() {
|
||||
@ -52,6 +54,18 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
_.extend(basicProps, extraProps)));
|
||||
}
|
||||
|
||||
function mountAsRealComponent(extraProps, container) {
|
||||
var basicProps = {
|
||||
dispatcher: dispatcher,
|
||||
messageList: [],
|
||||
useDesktopPaths: false
|
||||
};
|
||||
|
||||
return React.render(
|
||||
React.createElement(loop.shared.views.chat.TextChatEntriesView,
|
||||
_.extend(basicProps, extraProps)), container);
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
store.setStoreState({ textChatEnabled: true });
|
||||
});
|
||||
@ -208,6 +222,115 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
expect(node.querySelectorAll(".text-chat-entry-timestamp").length)
|
||||
.to.eql(1);
|
||||
});
|
||||
|
||||
describe("Scrolling", function() {
|
||||
beforeEach(function() {
|
||||
sandbox.stub(window, "requestAnimationFrame", function(callback) {
|
||||
callback();
|
||||
});
|
||||
|
||||
// We're using scrolling, so we need to mount as a real one.
|
||||
view = mountAsRealComponent({}, fixtures);
|
||||
sandbox.stub(view, "play");
|
||||
|
||||
// We need some basic styling to ensure scrolling.
|
||||
view.getDOMNode().style.overflow = "scroll";
|
||||
view.getDOMNode().style["max-height"] = "4ch";
|
||||
});
|
||||
|
||||
it("should scroll when a text message is added", function() {
|
||||
var messageList = [{
|
||||
type: CHAT_MESSAGE_TYPES.RECEIVED,
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Hello!",
|
||||
receivedTimestamp: "2015-06-25T17:53:55.357Z"
|
||||
}];
|
||||
|
||||
view.setProps({ messageList: messageList });
|
||||
|
||||
node = view.getDOMNode();
|
||||
|
||||
expect(node.scrollTop).eql(node.scrollHeight - node.clientHeight);
|
||||
});
|
||||
|
||||
it("should not scroll when a context tile is added", function() {
|
||||
var messageList = [{
|
||||
type: CHAT_MESSAGE_TYPES.SPECIAL,
|
||||
contentType: CHAT_CONTENT_TYPES.CONTEXT,
|
||||
message: "Awesome!",
|
||||
extraData: {
|
||||
location: "http://invalid.com"
|
||||
}
|
||||
}];
|
||||
|
||||
view.setProps({ messageList: messageList });
|
||||
|
||||
node = view.getDOMNode();
|
||||
|
||||
expect(node.scrollTop).eql(0);
|
||||
});
|
||||
|
||||
it("should scroll when a message is received after a context tile", function() {
|
||||
// The context tile.
|
||||
var messageList = [{
|
||||
type: CHAT_MESSAGE_TYPES.SPECIAL,
|
||||
contentType: CHAT_CONTENT_TYPES.CONTEXT,
|
||||
message: "Awesome!",
|
||||
extraData: {
|
||||
location: "http://invalid.com"
|
||||
}
|
||||
}];
|
||||
|
||||
view.setProps({ messageList: messageList });
|
||||
|
||||
// Now add a message. Don't use the same list as this is a shared object,
|
||||
// that messes with React.
|
||||
var messageList1 = [
|
||||
messageList[0], {
|
||||
type: CHAT_MESSAGE_TYPES.RECEIVED,
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Hello!",
|
||||
receivedTimestamp: "2015-06-25T17:53:55.357Z"
|
||||
}
|
||||
];
|
||||
|
||||
view.setProps({ messageList: messageList1 });
|
||||
|
||||
node = view.getDOMNode();
|
||||
|
||||
expect(node.scrollTop).eql(node.scrollHeight - node.clientHeight);
|
||||
|
||||
});
|
||||
|
||||
it("should not scroll when receiving a message and the scroll is not at the bottom", function() {
|
||||
node = view.getDOMNode();
|
||||
|
||||
var messageList = [{
|
||||
type: CHAT_MESSAGE_TYPES.RECEIVED,
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Hello!",
|
||||
receivedTimestamp: "2015-06-25T17:53:55.357Z"
|
||||
}];
|
||||
|
||||
view.setProps({ messageList: messageList });
|
||||
|
||||
node.scrollTop = 0;
|
||||
|
||||
// Don't use the same list as this is a shared object, that messes with React.
|
||||
var messageList1 = [
|
||||
messageList[0], {
|
||||
type: CHAT_MESSAGE_TYPES.RECEIVED,
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Hello!",
|
||||
receivedTimestamp: "2015-06-25T17:53:55.357Z"
|
||||
}
|
||||
];
|
||||
|
||||
view.setProps({ messageList: messageList1 });
|
||||
|
||||
expect(node.scrollTop).eql(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("TextChatEntry", function() {
|
||||
@ -285,6 +408,10 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
// Fake server to catch all XHR requests.
|
||||
fakeServer = sinon.fakeServer.create();
|
||||
store.setStoreState({ textChatEnabled: true });
|
||||
|
||||
sandbox.stub(navigator.mozL10n, "get", function(string) {
|
||||
return string;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@ -482,5 +609,34 @@ describe("loop.shared.views.TextChatView", function () {
|
||||
|
||||
sinon.assert.notCalled(dispatcher.dispatch);
|
||||
});
|
||||
|
||||
it("should show a placeholder when no messages have been sent", function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
store.receivedTextChatMessage({
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Foo",
|
||||
sentTimestamp: "1970-01-01T00:03:00.000Z",
|
||||
receivedTimestamp: "1970-01-01T00:03:00.000Z"
|
||||
});
|
||||
|
||||
var textBox = view.getDOMNode().querySelector(".text-chat-box input");
|
||||
|
||||
expect(textBox.placeholder).contain("placeholder");
|
||||
});
|
||||
|
||||
it("should not show a placeholder when messages have been sent", function() {
|
||||
view = mountTestComponent();
|
||||
|
||||
store.sendTextChatMessage({
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Foo",
|
||||
sentTimestamp: "2015-06-25T17:53:55.357Z"
|
||||
});
|
||||
|
||||
var textBox = view.getDOMNode().querySelector(".text-chat-box input");
|
||||
|
||||
expect(textBox.placeholder).not.contain("placeholder");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -850,6 +850,28 @@ describe("loop.shared.views", function() {
|
||||
React.createElement(sharedViews.ContextUrlView, props));
|
||||
}
|
||||
|
||||
it("should set a clicks-allowed class if clicks are allowed", function() {
|
||||
view = mountTestComponent({
|
||||
allowClick: true,
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
var wrapper = view.getDOMNode().querySelector(".context-wrapper");
|
||||
|
||||
expect(wrapper.classList.contains("clicks-allowed")).eql(true);
|
||||
});
|
||||
|
||||
it("should not set a clicks-allowed class if clicks are not allowed", function() {
|
||||
view = mountTestComponent({
|
||||
allowClick: false,
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
var wrapper = view.getDOMNode().querySelector(".context-wrapper");
|
||||
|
||||
expect(wrapper.classList.contains("clicks-allowed")).eql(false);
|
||||
});
|
||||
|
||||
it("should display nothing if the url is invalid", function() {
|
||||
view = mountTestComponent({
|
||||
url: "fjrTykyw"
|
||||
@ -900,7 +922,7 @@ describe("loop.shared.views", function() {
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".context-url").href)
|
||||
expect(view.getDOMNode().querySelector(".context-wrapper").href)
|
||||
.eql("http://wonderful.invalid/");
|
||||
});
|
||||
|
||||
@ -910,7 +932,7 @@ describe("loop.shared.views", function() {
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
var linkNode = view.getDOMNode().querySelector(".context-url");
|
||||
var linkNode = view.getDOMNode().querySelector(".context-wrapper");
|
||||
|
||||
TestUtils.Simulate.click(linkNode);
|
||||
|
||||
@ -920,6 +942,19 @@ describe("loop.shared.views", function() {
|
||||
linkInfo: "Shared URL"
|
||||
}));
|
||||
});
|
||||
|
||||
it("should not dispatch an action if clicks are not allowed", function() {
|
||||
view = mountTestComponent({
|
||||
allowClick: false,
|
||||
url: "http://wonderful.invalid"
|
||||
});
|
||||
|
||||
var linkNode = view.getDOMNode().querySelector(".context-wrapper");
|
||||
|
||||
TestUtils.Simulate.click(linkNode);
|
||||
|
||||
sinon.assert.notCalled(dispatcher.dispatch);
|
||||
});
|
||||
});
|
||||
|
||||
describe("MediaView", function() {
|
||||
|
@ -84,8 +84,8 @@
|
||||
});
|
||||
|
||||
describe("Unexpected Warnings Check", function() {
|
||||
it("should long only the warnings we expect", function() {
|
||||
chai.expect(caughtWarnings.length).to.eql(10);
|
||||
it("should log only the warnings we expect", function() {
|
||||
chai.expect(caughtWarnings.length).to.eql(0);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -195,5 +195,22 @@ describe("loop.store.StandaloneMetricsStore", function() {
|
||||
"send", "event", METRICS_GA_CATEGORY.general, METRICS_GA_ACTIONS.audioMute,
|
||||
"mute");
|
||||
});
|
||||
|
||||
describe("Event listeners", function() {
|
||||
it("should call windowUnload when action is dispatched", function() {
|
||||
sandbox.stub(store, "windowUnload");
|
||||
|
||||
dispatcher.dispatch(new sharedActions.WindowUnload());
|
||||
sinon.assert.calledOnce(store.windowUnload);
|
||||
});
|
||||
|
||||
it("should stop listening to activeRoomStore", function() {
|
||||
var stopListeningStub = sandbox.stub(store, "stopListening");
|
||||
store.windowUnload();
|
||||
|
||||
sinon.assert.calledOnce(stopListeningStub);
|
||||
sinon.assert.calledWithExactly(stopListeningStub, store.activeRoomStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -14,6 +14,7 @@ describe("loop.standaloneRoomViews", function() {
|
||||
var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedUtils = loop.shared.utils;
|
||||
var fixtures = document.querySelector("#fixtures");
|
||||
|
||||
var sandbox, dispatcher, activeRoomStore, dispatch;
|
||||
var fakeWindow;
|
||||
@ -60,6 +61,7 @@ describe("loop.standaloneRoomViews", function() {
|
||||
afterEach(function() {
|
||||
loop.shared.mixins.setRootObject(window);
|
||||
sandbox.restore();
|
||||
React.unmountComponentAtNode(fixtures);
|
||||
});
|
||||
|
||||
describe("StandaloneRoomHeader", function() {
|
||||
@ -84,6 +86,39 @@ describe("loop.standaloneRoomViews", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("StandaloneRoomInfoArea in fixture", function() {
|
||||
it("should dispatch a RecordClick action when the tile is clicked", function(done) {
|
||||
// Point the iframe to a page that will auto-"click"
|
||||
loop.config.tilesIframeUrl = "data:text/html,<script>parent.postMessage('tile-click', '*');</script>";
|
||||
|
||||
// Render the iframe into the fixture to cause it to load
|
||||
React.render(
|
||||
React.createElement(
|
||||
loop.standaloneRoomViews.StandaloneRoomInfoArea, {
|
||||
activeRoomStore: activeRoomStore,
|
||||
dispatcher: dispatcher,
|
||||
isFirefox: true,
|
||||
joinRoom: sandbox.stub(),
|
||||
roomState: ROOM_STATES.JOINED,
|
||||
roomUsed: false
|
||||
}), fixtures);
|
||||
|
||||
// Wait for the iframe to load and trigger a message that should also
|
||||
// cause the RecordClick action
|
||||
window.addEventListener("message", function onMessage() {
|
||||
window.removeEventListener("message", onMessage);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles iframe click"
|
||||
}));
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("StandaloneRoomView", function() {
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
@ -181,20 +216,6 @@ describe("loop.standaloneRoomViews", function() {
|
||||
.not.eql(null);
|
||||
});
|
||||
|
||||
it("should display a waiting room message and tile iframe on JOINED",
|
||||
function() {
|
||||
var DUMMY_TILE_URL = "http://tile/";
|
||||
loop.config.tilesIframeUrl = DUMMY_TILE_URL;
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".room-waiting-area"))
|
||||
.not.eql(null);
|
||||
|
||||
var tile = view.getDOMNode().querySelector(".room-waiting-tile");
|
||||
expect(tile).not.eql(null);
|
||||
expect(tile.src).eql(DUMMY_TILE_URL);
|
||||
});
|
||||
|
||||
it("should display an empty room message on SESSION_CONNECTED",
|
||||
function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.SESSION_CONNECTED});
|
||||
@ -212,6 +233,33 @@ describe("loop.standaloneRoomViews", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("Empty room tile offer", function() {
|
||||
it("should display a waiting room message and tile iframe on JOINED", function() {
|
||||
var DUMMY_TILE_URL = "http://tile/";
|
||||
loop.config.tilesIframeUrl = DUMMY_TILE_URL;
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".room-waiting-area")).not.eql(null);
|
||||
|
||||
var tile = view.getDOMNode().querySelector(".room-waiting-tile");
|
||||
expect(tile).not.eql(null);
|
||||
expect(tile.src).eql(DUMMY_TILE_URL);
|
||||
});
|
||||
|
||||
it("should dispatch a RecordClick action when the tile support link is clicked", function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.JOINED});
|
||||
|
||||
TestUtils.Simulate.click(view.getDOMNode().querySelector(".room-waiting-area a"));
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.RecordClick({
|
||||
linkInfo: "Tiles support link click"
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("Prompt media message", function() {
|
||||
it("should display a prompt for user media on MEDIA_WAIT",
|
||||
function() {
|
||||
|
@ -17,6 +17,7 @@ describe("loop.webapp", function() {
|
||||
stubGetPermsAndCacheMedia,
|
||||
fakeAudioXHR,
|
||||
dispatcher,
|
||||
mozL10nGet,
|
||||
WEBSOCKET_REASONS = loop.shared.utils.WEBSOCKET_REASONS;
|
||||
|
||||
beforeEach(function() {
|
||||
@ -27,6 +28,10 @@ describe("loop.webapp", function() {
|
||||
stubGetPermsAndCacheMedia = sandbox.stub(
|
||||
loop.standaloneMedia._MultiplexGum.prototype, "getPermsAndCacheMedia");
|
||||
|
||||
mozL10nGet = sandbox.stub(navigator.mozL10n, "get", function(x) {
|
||||
return "translated:" + x;
|
||||
});
|
||||
|
||||
fakeAudioXHR = {
|
||||
open: sinon.spy(),
|
||||
send: function() {},
|
||||
@ -114,6 +119,7 @@ describe("loop.webapp", function() {
|
||||
ocView = mountTestComponent({
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
isFirefox: true,
|
||||
notifications: notifications,
|
||||
sdk: {
|
||||
on: sandbox.stub()
|
||||
@ -677,8 +683,7 @@ describe("loop.webapp", function() {
|
||||
|
||||
it("should display the UnsupportedDeviceView for `unsupportedDevice` window type",
|
||||
function() {
|
||||
standaloneAppStore.setStoreState({windowType: "unsupportedDevice"});
|
||||
|
||||
standaloneAppStore.setStoreState({windowType: "unsupportedDevice", unsupportedPlatform: "ios"});
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(webappRootView,
|
||||
@ -687,7 +692,7 @@ describe("loop.webapp", function() {
|
||||
|
||||
it("should display the UnsupportedBrowserView for `unsupportedBrowser` window type",
|
||||
function() {
|
||||
standaloneAppStore.setStoreState({windowType: "unsupportedBrowser"});
|
||||
standaloneAppStore.setStoreState({windowType: "unsupportedBrowser", isFirefox: false});
|
||||
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
@ -697,7 +702,7 @@ describe("loop.webapp", function() {
|
||||
|
||||
it("should display the OutgoingConversationView for `outgoing` window type",
|
||||
function() {
|
||||
standaloneAppStore.setStoreState({windowType: "outgoing"});
|
||||
standaloneAppStore.setStoreState({windowType: "outgoing", isFirefox: true});
|
||||
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
@ -707,7 +712,7 @@ describe("loop.webapp", function() {
|
||||
|
||||
it("should display the StandaloneRoomView for `room` window type",
|
||||
function() {
|
||||
standaloneAppStore.setStoreState({windowType: "room"});
|
||||
standaloneAppStore.setStoreState({windowType: "room", isFirefox: true});
|
||||
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
@ -716,7 +721,7 @@ describe("loop.webapp", function() {
|
||||
});
|
||||
|
||||
it("should display the HomeView for `home` window type", function() {
|
||||
standaloneAppStore.setStoreState({windowType: "home"});
|
||||
standaloneAppStore.setStoreState({windowType: "home", isFirefox: true});
|
||||
|
||||
var webappRootView = mountTestComponent();
|
||||
|
||||
@ -1092,17 +1097,17 @@ describe("loop.webapp", function() {
|
||||
isFirefox: true
|
||||
}));
|
||||
|
||||
expect(comp.getDOMNode().querySelectorAll("h3").length).eql(0);
|
||||
expect(comp.getDOMNode()).eql(null);
|
||||
});
|
||||
|
||||
it("should render when not using Firefox", function() {
|
||||
var comp = TestUtils.renderIntoDocument(
|
||||
React.createElement(
|
||||
loop.webapp.PromoteFirefoxView, {
|
||||
React.createElement(loop.webapp.PromoteFirefoxView, {
|
||||
isFirefox: false
|
||||
}));
|
||||
|
||||
expect(comp.getDOMNode().querySelectorAll("h3").length).eql(1);
|
||||
sinon.assert.calledWith(mozL10nGet, "promote_firefox_hello_heading");
|
||||
sinon.assert.calledWith(mozL10nGet, "get_firefox_button");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -387,7 +387,7 @@
|
||||
roomOwner: "fake",
|
||||
roomUrl: "http://showcase",
|
||||
urls: [{
|
||||
description: "A wonderful page!",
|
||||
description: "1171925 - Clicking the title or favicon for context (in the conversation/standalone windows) should appear to be part of the link and open the webpage",
|
||||
location: "http://wonderful.invalid"
|
||||
// use the fallback thumbnail
|
||||
}]
|
||||
@ -1541,7 +1541,7 @@
|
||||
|
||||
// This simulates the mocha layout for errors which means we can run
|
||||
// this alongside our other unit tests but use the same harness.
|
||||
var expectedWarningsCount = 18;
|
||||
var expectedWarningsCount = 16;
|
||||
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
|
||||
if (uncaughtError || warningsMismatch) {
|
||||
$("#results").append("<div class='failures'><em>" +
|
||||
|
@ -387,7 +387,7 @@
|
||||
roomOwner: "fake",
|
||||
roomUrl: "http://showcase",
|
||||
urls: [{
|
||||
description: "A wonderful page!",
|
||||
description: "1171925 - Clicking the title or favicon for context (in the conversation/standalone windows) should appear to be part of the link and open the webpage",
|
||||
location: "http://wonderful.invalid"
|
||||
// use the fallback thumbnail
|
||||
}]
|
||||
@ -1541,7 +1541,7 @@
|
||||
|
||||
// This simulates the mocha layout for errors which means we can run
|
||||
// this alongside our other unit tests but use the same harness.
|
||||
var expectedWarningsCount = 18;
|
||||
var expectedWarningsCount = 16;
|
||||
var warningsMismatch = caughtWarnings.length !== expectedWarningsCount;
|
||||
if (uncaughtError || warningsMismatch) {
|
||||
$("#results").append("<div class='failures'><em>" +
|
||||
|
@ -113,7 +113,10 @@ function screenshot() {
|
||||
}
|
||||
|
||||
let WebProgressListener = {
|
||||
onLocationChange: function onLocationChange(aWebProgress) {
|
||||
onLocationChange(webProgress, request, URI, flags) {
|
||||
if (flags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
|
||||
return;
|
||||
}
|
||||
makeScrollbarsFloating();
|
||||
},
|
||||
QueryInterface: function QueryInterface(aIID) {
|
||||
|
@ -33,7 +33,7 @@
|
||||
background-position: -48px center;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#eyedropper-button {
|
||||
background-image: url("chrome://browser/skin/devtools/command-eyedropper@2x.png");
|
||||
}
|
||||
|
@ -42,7 +42,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.breakpoint {
|
||||
background-image: url("chrome://browser/skin/devtools/editor-breakpoint@2x.png");
|
||||
}
|
||||
@ -56,7 +56,7 @@
|
||||
background-image: url("chrome://browser/skin/devtools/editor-debug-location.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.debugLocation {
|
||||
background-image: url("chrome://browser/skin/devtools/editor-debug-location@2x.png");
|
||||
}
|
||||
@ -68,7 +68,7 @@
|
||||
url("chrome://browser/skin/devtools/editor-breakpoint.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.breakpoint.debugLocation {
|
||||
background-image:
|
||||
url("chrome://browser/skin/devtools/editor-debug-location@2x.png"),
|
||||
|
@ -65,7 +65,7 @@ const SEARCH_DELAY = 200;
|
||||
// The number of lines that are displayed in the console output by default, for
|
||||
// each category. The user can change this number by adjusting the hidden
|
||||
// "devtools.hud.loglimit.{network,cssparser,exception,console}" preferences.
|
||||
const DEFAULT_LOG_LIMIT = 200;
|
||||
const DEFAULT_LOG_LIMIT = 1000;
|
||||
|
||||
// The various categories of messages. We start numbering at zero so we can
|
||||
// use these as indexes into the MESSAGE_PREFERENCE_KEYS matrix below.
|
||||
|
@ -1189,12 +1189,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 14px, 28px, 0);
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 14px, 42px, 0);
|
||||
}
|
||||
|
||||
@ -1207,12 +1205,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 42px, 28px, 28px);
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 42px, 42px, 28px);
|
||||
}
|
||||
|
||||
@ -1225,12 +1221,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-stop-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), transparent);
|
||||
-moz-image-region: rect(14px, 28px, 28px, 14px);
|
||||
}
|
||||
|
||||
#urlbar-stop-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 28px, 42px, 14px);
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1716,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
.urlbar-history-dropmarker[open="true"],
|
||||
.urlbar-history-dropmarker:hover:active {
|
||||
-moz-image-region: var(--urlbar-dropmarker-active-region);
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
@ -1743,11 +1742,6 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
.urlbar-icon[open="true"],
|
||||
.urlbar-icon:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
#urlbar-search-footer {
|
||||
border-top: 1px solid hsla(210,4%,10%,.14);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
@ -1920,10 +1914,6 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
|
||||
list-style-image: url("chrome://browser/skin/reload-stop-go.png");
|
||||
}
|
||||
|
||||
#urlbar > toolbarbutton:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
#urlbar-go-button {
|
||||
-moz-image-region: rect(0, 42px, 14px, 28px);
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ body {
|
||||
background-image: url("debugger-play.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#element-picker::before {
|
||||
background-image: url("chrome://browser/skin/devtools/command-pick@2x.png");
|
||||
background-size: 64px;
|
||||
@ -362,7 +362,7 @@ body {
|
||||
background-image: url(rewind.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.timeline .toggle::before {
|
||||
background-image: url(debugger-pause@2x.png);
|
||||
}
|
||||
|
@ -145,7 +145,7 @@
|
||||
list-style-image: url(debugger-step-out.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#resume {
|
||||
list-style-image: url(debugger-play@2x.png);
|
||||
-moz-image-region: rect(0px,64px,32px,32px);
|
||||
@ -250,7 +250,7 @@
|
||||
background-size: 12px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.selected .call-item-gutter {
|
||||
background-image: url("editor-debug-location@2x.png");
|
||||
}
|
||||
|
@ -82,7 +82,7 @@
|
||||
-moz-image-region: rect(0px, 64px, 16px, 48px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#developer-toolbar-toolbox-button {
|
||||
list-style-image: url("chrome://browser/skin/devtools/toggle-tools@2x.png");
|
||||
-moz-image-region: rect(0px, 32px, 32px, 0px);
|
||||
@ -111,7 +111,7 @@
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#developer-toolbar-closebutton {
|
||||
list-style-image: url("chrome://browser/skin/devtools/close@2x.png");
|
||||
}
|
||||
@ -199,7 +199,7 @@ html|*#gcli-output-frame {
|
||||
background-position: -16px center;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.gclitoolbar-input-node::before {
|
||||
background-image: url("chrome://browser/skin/devtools/commandline-icon@2x.png");
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ body {
|
||||
background-size: 5px 8px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.property-value, .other-property-value {
|
||||
background-image: url(arrow-e@2x.png);
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ div.CodeMirror span.eval-text {
|
||||
background-position: -42px 0;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.theme-twisty, .theme-checkbox {
|
||||
background-image: url("chrome://browser/skin/devtools/controls@2x.png");
|
||||
}
|
||||
@ -372,7 +372,7 @@ div.CodeMirror span.eval-text {
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.theme-tooltip-panel .panel-arrow[side="top"],
|
||||
.theme-tooltip-panel .panel-arrow[side="bottom"] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/tooltip/arrow-vertical-dark@2x.png");
|
||||
|
@ -66,7 +66,7 @@
|
||||
list-style-image: url(debugger-blackbox.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#black-box {
|
||||
list-style-image: url(debugger-blackbox@2x.png);
|
||||
}
|
||||
@ -76,7 +76,7 @@
|
||||
list-style-image: url(debugger-prettyprint.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#pretty-print {
|
||||
list-style-image: url(debugger-prettyprint@2x.png);
|
||||
}
|
||||
@ -86,7 +86,7 @@
|
||||
list-style-image: url(debugger-toggleBreakpoints.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#toggle-breakpoints {
|
||||
list-style-image: url(debugger-toggleBreakpoints@2x.png);
|
||||
}
|
||||
@ -104,7 +104,7 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#sources-toolbar .devtools-toolbarbutton:not([label]) {
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
}
|
||||
@ -138,7 +138,7 @@
|
||||
-moz-margin-end: 5px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#black-boxed-message-button > .button-box > .button-icon {
|
||||
background-image: url(debugger-blackbox@2x.png);
|
||||
}
|
||||
@ -226,7 +226,7 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#trace {
|
||||
list-style-image: url(tracer-icon@2x.png);
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
@ -328,7 +328,7 @@
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.dbg-expression-arrow {
|
||||
background-image: url(commandline-icon@2x.png);
|
||||
}
|
||||
@ -564,7 +564,7 @@
|
||||
list-style-image: url(debugger-play.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#resume {
|
||||
list-style-image: url(debugger-pause@2x.png);
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
@ -596,7 +596,7 @@
|
||||
list-style-image: url(debugger-step-out.png);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#step-over {
|
||||
list-style-image: url(debugger-step-over@2x.png);
|
||||
}
|
||||
@ -626,7 +626,7 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#instruments-pane-toggle {
|
||||
list-style-image: url(debugger-collapse@2x.png);
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
|
@ -60,7 +60,7 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#inspector-pane-toggle {
|
||||
list-style-image: url(debugger-collapse@2x.png);
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
|
@ -343,7 +343,7 @@ div.CodeMirror span.eval-text {
|
||||
background-position: -14px 0;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.theme-twisty, .theme-checkbox {
|
||||
background-image: url("chrome://browser/skin/devtools/controls@2x.png");
|
||||
}
|
||||
@ -381,7 +381,7 @@ div.CodeMirror span.eval-text {
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.theme-tooltip-panel .panel-arrow[side="top"],
|
||||
.theme-tooltip-panel .panel-arrow[side="bottom"] {
|
||||
list-style-image: url("chrome://browser/skin/devtools/tooltip/arrow-vertical-light@2x.png");
|
||||
|
@ -416,7 +416,7 @@ box.requests-menu-status[code^="5"] {
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#details-pane-toggle {
|
||||
list-style-image: url("chrome://browser/skin/devtools/debugger-collapse@2x.png");
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
@ -556,7 +556,7 @@ box.requests-menu-status[code^="5"] {
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.security-warning-icon {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
|
@ -155,7 +155,7 @@
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-rotate.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.devtools-responsiveui-close {
|
||||
list-style-image: url("chrome://browser/skin/devtools/close@2x.png");
|
||||
}
|
||||
@ -174,7 +174,7 @@
|
||||
-moz-image-region: rect(0px,32px,16px,16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.devtools-responsiveui-touch {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-touch@2x.png");
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
@ -189,7 +189,7 @@
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.devtools-responsiveui-screenshot {
|
||||
list-style-image: url("chrome://browser/skin/devtools/responsiveui-screenshot@2x.png");
|
||||
}
|
||||
@ -324,7 +324,7 @@
|
||||
border-bottom-left-radius: 12px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.devtools-responsiveui-resizebarV {
|
||||
background-image: url("chrome://browser/skin/devtools/responsive-vertical-resizer@2x.png");
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
||||
}
|
||||
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.ruleview-warning {
|
||||
background-image: url(alerticon-warning@2x.png);
|
||||
}
|
||||
@ -198,7 +198,7 @@
|
||||
background-size: 1em;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.ruleview-bezierswatch {
|
||||
background: url("chrome://browser/skin/devtools/cubic-bezier-swatch@2x.png");
|
||||
background-size: 1em;
|
||||
|
@ -60,7 +60,7 @@
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.side-menu-widget-item-checkbox .checkbox-check {
|
||||
background-image: url(itemToggle@2x.png);
|
||||
}
|
||||
|
@ -115,7 +115,7 @@
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.stylesheet-enabled {
|
||||
background-image: url(itemToggle@2x.png);
|
||||
}
|
||||
|
@ -317,7 +317,7 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.devtools-button::before {
|
||||
background-size: 32px;
|
||||
}
|
||||
@ -438,7 +438,7 @@
|
||||
-moz-image-region: rect(0, 32px, 16px, 16px);
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.theme-dark .devtools-searchinput {
|
||||
background-image: url(magnifying-glass@2x.png);
|
||||
}
|
||||
@ -768,7 +768,7 @@
|
||||
background-image: url("chrome://browser/skin/devtools/command-rulers.png");
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#command-button-paintflashing > image {
|
||||
background-image: url("chrome://browser/skin/devtools/command-paintflashing@2x.png");
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ text {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
#inspector-pane-toggle {
|
||||
list-style-image: url(debugger-collapse@2x.png);
|
||||
-moz-image-region: rect(0px,32px,32px,0px);
|
||||
|
@ -360,7 +360,7 @@ a {
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.jsterm-input-node {
|
||||
background-image: -moz-image-rect(url('chrome://browser/skin/devtools/commandline-icon@2x.png'), 0, 64, 32, 32);
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.scrollbutton-up > .toolbarbutton-icon,
|
||||
.scrollbutton-down > .toolbarbutton-icon {
|
||||
background-image: url("breadcrumbs-scrollbutton@2x.png");
|
||||
@ -641,7 +641,7 @@
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.variable-or-property-non-writable-icon {
|
||||
background-image: url("chrome://browser/skin/devtools/vview-lock@2x.png");
|
||||
}
|
||||
@ -741,7 +741,7 @@
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.variables-view-delete {
|
||||
background-image: url("chrome://browser/skin/devtools/vview-delete@2x.png");
|
||||
}
|
||||
@ -767,7 +767,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.variables-view-edit {
|
||||
background-image: url("chrome://browser/skin/devtools/vview-edit@2x.png");
|
||||
}
|
||||
@ -793,7 +793,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.variables-view-open-inspector {
|
||||
background-image: url("chrome://browser/skin/devtools/vview-open-inspector@2x.png");
|
||||
}
|
||||
@ -1424,7 +1424,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-resolution: 1.25dppx) {
|
||||
@media (min-resolution: 1.1dppx) {
|
||||
.tree-widget-item:before {
|
||||
background-image: url("chrome://browser/skin/devtools/controls@2x.png");
|
||||
}
|
||||
|
@ -95,7 +95,6 @@
|
||||
height: 16px;
|
||||
margin-top: -12px;
|
||||
-moz-margin-start: -16px;
|
||||
display: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@ -103,35 +102,29 @@
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/crashed.svg");
|
||||
}
|
||||
|
||||
.tab-icon-overlay[crashed],
|
||||
.tab-icon-overlay[soundplaying][pinned],
|
||||
.tab-icon-overlay[muted][pinned]:not([crashed]) {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned],
|
||||
.tab-icon-overlay[muted][pinned]:not([crashed]) {
|
||||
.tab-icon-overlay[soundplaying],
|
||||
.tab-icon-overlay[muted]:not([crashed]) {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned]:hover,
|
||||
.tab-icon-overlay[muted][pinned]:not([crashed]):hover {
|
||||
.tab-icon-overlay[soundplaying]:hover,
|
||||
.tab-icon-overlay[muted]:not([crashed]):hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.tab-icon-overlay[soundplaying][pinned] {
|
||||
.tab-icon-overlay[soundplaying] {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio");
|
||||
}
|
||||
|
||||
.tab-icon-overlay[muted][pinned]:not([crashed]) {
|
||||
.tab-icon-overlay[muted]:not([crashed]) {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-muted");
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying][pinned]:not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[soundplaying]:not(:hover) {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white");
|
||||
}
|
||||
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[muted][pinned]:not([crashed]):not(:hover) {
|
||||
#TabsToolbar[brighttext] .tab-icon-overlay[muted]:not([crashed]):not(:hover) {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio-small.svg#tab-audio-white-muted");
|
||||
}
|
||||
|
||||
@ -161,11 +154,6 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tab-icon-sound:not([soundplaying]):not([muted]),
|
||||
.tab-icon-sound[pinned] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-icon-sound[soundplaying] {
|
||||
list-style-image: url("chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio-backgroundTab");
|
||||
}
|
||||
|
@ -1383,15 +1383,6 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
padding: 2px 2px;
|
||||
}
|
||||
|
||||
.urlbar-icon:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
.urlbar-icon[open="true"],
|
||||
.urlbar-icon:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.1), transparent);
|
||||
}
|
||||
|
||||
#urlbar-search-footer {
|
||||
border-top: 1px solid hsla(210,4%,10%,.14);
|
||||
background-color: hsla(210,4%,10%,.07);
|
||||
@ -1478,13 +1469,11 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
-moz-image-region: var(--urlbar-dropmarker-hover-region);
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover:active,
|
||||
.urlbar-history-dropmarker[open="true"] {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), transparent);
|
||||
-moz-image-region: var(--urlbar-dropmarker-active-region);
|
||||
}
|
||||
|
||||
@ -1669,12 +1658,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 14px, 28px, 0);
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 14px, 42px, 0);
|
||||
}
|
||||
|
||||
@ -1687,12 +1674,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 42px, 28px, 28px);
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 42px, 42px, 28px);
|
||||
}
|
||||
|
||||
@ -1705,12 +1690,10 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||
}
|
||||
|
||||
#urlbar-stop-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), transparent);
|
||||
-moz-image-region: rect(14px, 28px, 28px, 14px);
|
||||
}
|
||||
|
||||
#urlbar-stop-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 28px, 42px, 14px);
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,11 @@
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.util.ActivityResultHandler;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.JSONUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.WebActivityMapper;
|
||||
|
||||
import org.json.JSONArray;
|
||||
@ -26,16 +29,21 @@ import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public final class IntentHelper implements GeckoEventListener {
|
||||
public final class IntentHelper implements GeckoEventListener,
|
||||
NativeEventListener {
|
||||
|
||||
private static final String LOGTAG = "GeckoIntentHelper";
|
||||
private static final String[] EVENTS = {
|
||||
"Intent:GetHandlers",
|
||||
"Intent:Open",
|
||||
"Intent:OpenForResult",
|
||||
"Intent:OpenNoHandler",
|
||||
"WebActivity:Open"
|
||||
};
|
||||
|
||||
private static final String[] NATIVE_EVENTS = {
|
||||
"Intent:OpenNoHandler",
|
||||
};
|
||||
|
||||
// via http://developer.android.com/distribute/tools/promote/linking.html
|
||||
private static String MARKET_INTENT_URI_PACKAGE_PREFIX = "market://details?id=";
|
||||
private static String EXTRA_BROWSER_FALLBACK_URL = "browser_fallback_url";
|
||||
@ -49,7 +57,8 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
|
||||
private IntentHelper(Activity activity) {
|
||||
this.activity = activity;
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this, EVENTS);
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener) this, EVENTS);
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener) this, NATIVE_EVENTS);
|
||||
}
|
||||
|
||||
public static IntentHelper init(Activity activity) {
|
||||
@ -64,11 +73,19 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
|
||||
public static void destroy() {
|
||||
if (instance != null) {
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(instance, EVENTS);
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) instance, EVENTS);
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) instance, NATIVE_EVENTS);
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message, final EventCallback callback) {
|
||||
if (event.equals("Intent:OpenNoHandler")) {
|
||||
openNoHandler(message, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, JSONObject message) {
|
||||
try {
|
||||
@ -78,8 +95,6 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
open(message);
|
||||
} else if (event.equals("Intent:OpenForResult")) {
|
||||
openForResult(message);
|
||||
} else if (event.equals("Intent:OpenNoHandler")) {
|
||||
openNoHandler(message);
|
||||
} else if (event.equals("WebActivity:Open")) {
|
||||
openWebActivity(message);
|
||||
}
|
||||
@ -132,13 +147,17 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
* and we can bring the user directly to the application page in an app market. If a package is
|
||||
* not specified and there is a fallback url in the intent extras, we open that url. If neither
|
||||
* is present, we alert the user that we were unable to open the link.
|
||||
*
|
||||
* @param msg A message with the uri with no handlers as the value for the "uri" key
|
||||
* @param callback A callback that will be called with success & no params if Java loads a page, or with error and
|
||||
* the uri to load if Java does not load a page
|
||||
*/
|
||||
private void openNoHandler(final JSONObject msg) {
|
||||
final String uri = msg.optString("uri");
|
||||
private void openNoHandler(final NativeJSObject msg, final EventCallback callback) {
|
||||
final String uri = msg.getString("uri");
|
||||
|
||||
if (TextUtils.isEmpty(uri)) {
|
||||
openUnknownProtocolErrorPage("");
|
||||
Log.w(LOGTAG, "Received empty URL - loading about:neterror");
|
||||
callback.sendError(getUnknownProtocolErrorPageUri(""));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -147,14 +166,16 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
// TODO (bug 1173626): This will not handle android-app uris on non 5.1 devices.
|
||||
intent = Intent.parseUri(uri, 0);
|
||||
} catch (final URISyntaxException e) {
|
||||
String errorUri;
|
||||
try {
|
||||
openUnknownProtocolErrorPage(URLEncoder.encode(uri, "UTF-8"));
|
||||
errorUri = getUnknownProtocolErrorPageUri(URLEncoder.encode(uri, "UTF-8"));
|
||||
} catch (final UnsupportedEncodingException encodingE) {
|
||||
openUnknownProtocolErrorPage("");
|
||||
errorUri = getUnknownProtocolErrorPageUri("");
|
||||
}
|
||||
|
||||
// Don't log the exception to prevent leaking URIs.
|
||||
Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror");
|
||||
callback.sendError(errorUri);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -174,28 +195,31 @@ public final class IntentHelper implements GeckoEventListener {
|
||||
final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(marketUri));
|
||||
marketIntent.addCategory(Intent.CATEGORY_BROWSABLE);
|
||||
marketIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
// (Bug 1192436) We don't know if marketIntent matches any Activities (e.g. non-Play
|
||||
// Store devices). If it doesn't, clicking the link will cause no action to occur.
|
||||
activity.startActivity(marketIntent);
|
||||
callback.sendSuccess(null);
|
||||
|
||||
} else if (intent.hasExtra(EXTRA_BROWSER_FALLBACK_URL)) {
|
||||
final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL);
|
||||
Tabs.getInstance().loadUrl(fallbackUrl);
|
||||
callback.sendError(fallbackUrl);
|
||||
|
||||
} else {
|
||||
openUnknownProtocolErrorPage(intent.getData().toString());
|
||||
// Don't log the URI to prevent leaking it.
|
||||
Log.w(LOGTAG, "Unable to open URI, default case - loading about:neterror");
|
||||
callback.sendError(getUnknownProtocolErrorPageUri(intent.getData().toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens about:neterror with the unknownProtocolFound text.
|
||||
* Returns an about:neterror uri with the unknownProtocolFound text as a parameter.
|
||||
* @param encodedUri The encoded uri. While the page does not open correctly without specifying
|
||||
* a uri parameter, it happily accepts the empty String so this argument may
|
||||
* be the empty String.
|
||||
*/
|
||||
private void openUnknownProtocolErrorPage(final String encodedUri) {
|
||||
final String errorUri = UNKNOWN_PROTOCOL_URI_PREFIX + encodedUri;
|
||||
Tabs.getInstance().loadUrl(errorUri);
|
||||
private String getUnknownProtocolErrorPageUri(final String encodedUri) {
|
||||
return UNKNOWN_PROTOCOL_URI_PREFIX + encodedUri;
|
||||
}
|
||||
|
||||
private void openWebActivity(JSONObject message) throws JSONException {
|
||||
|
@ -41,7 +41,7 @@ public class RestrictedProfiles {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
if (isGuestProfile()) {
|
||||
if (isGuestProfile(context)) {
|
||||
return new GuestProfileConfiguration();
|
||||
} else if(isRestrictedProfile(context)) {
|
||||
return new RestrictedProfileConfiguration(context);
|
||||
@ -50,8 +50,13 @@ public class RestrictedProfiles {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGuestProfile() {
|
||||
return GeckoAppShell.getGeckoInterface().getProfile().inGuestMode();
|
||||
private static boolean isGuestProfile(Context context) {
|
||||
GeckoAppShell.GeckoInterface geckoInterface = GeckoAppShell.getGeckoInterface();
|
||||
if (geckoInterface != null) {
|
||||
return geckoInterface.getProfile().inGuestMode();
|
||||
}
|
||||
|
||||
return GeckoProfile.get(context).inGuestMode();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
|
@ -564,14 +564,10 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
<!ENTITY identity_connection_insecure "Insecure connection">
|
||||
|
||||
<!-- Mixed content notifications in site identity popup -->
|
||||
<!ENTITY mixed_content_blocked_all "&brandShortName; has blocked insecure elements on this page.">
|
||||
<!ENTITY mixed_content_blocked_some "&brandShortName; has blocked some insecure elements on this page.">
|
||||
<!ENTITY mixed_content_display_loaded "This page has some insecure elements.">
|
||||
<!ENTITY mixed_content_protection_disabled "You have disabled protection from insecure elements.">
|
||||
|
||||
<!ENTITY loaded_mixed_content_message "This page is displaying content that isn\'t secure.">
|
||||
<!ENTITY blocked_mixed_content_message_top "&brandShortName; has blocked content that isn\'t secure.">
|
||||
<!ENTITY blocked_mixed_content_message_bottom "Most websites will still work properly even when this content is blocked.">
|
||||
<!ENTITY mixed_content_blocked_all1 "&brandShortName; has blocked insecure content on this page.">
|
||||
<!ENTITY mixed_content_blocked_some1 "&brandShortName; has blocked some of the insecure content on this page.">
|
||||
<!ENTITY mixed_content_display_loaded1 "Parts of this page are not secure (such as images).">
|
||||
<!ENTITY mixed_content_protection_disabled1 "You have disabled protection from insecure content.">
|
||||
|
||||
<!-- Tracking content notifications in site identity popup -->
|
||||
<!ENTITY doorhanger_tracking_title "Tracking protection">
|
||||
|
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 178 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 45 KiB |
@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/firstrun_min_height"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="21"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="10dp">
|
||||
|
||||
<ImageView android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/large_icon"/>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="29"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:background="@color/android:white">
|
||||
|
||||
<TextView android:layout_width="@dimen/firstrun_content_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingTop="30dp"
|
||||
android:textAppearance="@style/TextAppearance.FirstrunLight.Main"
|
||||
android:text="@string/firstrun_welcome_message"/>
|
||||
|
||||
<TextView android:layout_width="@dimen/firstrun_content_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="30dp"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.FirstrunRegular.Body"
|
||||
android:text="@string/firstrun_welcome_subtext"/>
|
||||
|
||||
<Button android:id="@+id/welcome_account"
|
||||
style="@style/Widget.Firstrun.Button"
|
||||
android:background="@drawable/button_background_action_orange_round"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/firstrun_welcome_button_account"/>
|
||||
|
||||
<TextView android:id="@+id/welcome_browse"
|
||||
android:layout_width="@dimen/firstrun_content_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="92dp"
|
||||
android:padding="20dp"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.FirstrunRegular.Link"
|
||||
android:text="@string/firstrun_welcome_button_browser"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/trackingprotection_title"
|
||||
android:focusable="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.DoorHanger.Medium"/>
|
||||
|
||||
<TextView android:id="@+id/trackingprotection_enabled"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.DoorHanger.Medium.Bold"/>
|
||||
|
||||
<TextView android:id="@+id/trackingprotection_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
@ -13,31 +13,29 @@
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="@dimen/firstrun_min_height"
|
||||
android:background="@color/android:white"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="21"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="10dp">
|
||||
<FrameLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/link_blue">
|
||||
|
||||
<ImageView android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
<ImageView android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/large_icon"/>
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/firstrun_background_coffee"/>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="29"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:background="@color/android:white">
|
||||
<ImageView android:layout_width="@dimen/firstrun_brand_size"
|
||||
android:layout_height="@dimen/firstrun_brand_size"
|
||||
android:src="@drawable/large_icon"
|
||||
android:layout_gravity="center"/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView android:layout_width="@dimen/firstrun_content_width"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingTop="30dp"
|
||||
android:textAppearance="@style/TextAppearance.FirstrunLight.Main"
|
||||
android:text="@string/firstrun_welcome_message"/>
|
||||
@ -64,5 +62,4 @@
|
||||
android:textAppearance="@style/TextAppearance.FirstrunRegular.Link"
|
||||
android:text="@string/firstrun_welcome_button_browser"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@ -24,6 +24,8 @@
|
||||
<dimen name="browser_toolbar_site_security_padding_vertical">21dp</dimen>
|
||||
<dimen name="browser_toolbar_site_security_padding_horizontal">8dp</dimen>
|
||||
|
||||
<dimen name="firstrun_brand_size">72dp</dimen>
|
||||
|
||||
<dimen name="tabs_panel_indicator_width">72dp</dimen>
|
||||
<dimen name="tabs_panel_button_width">60dp</dimen>
|
||||
<dimen name="panel_grid_view_column_width">200dp</dimen>
|
||||
|
@ -60,6 +60,7 @@
|
||||
|
||||
<dimen name="firstrun_content_width">300dp</dimen>
|
||||
<dimen name="firstrun_min_height">180dp</dimen>
|
||||
<dimen name="firstrun_brand_size">48dp</dimen>
|
||||
|
||||
<dimen name="overlay_prompt_content_width">260dp</dimen>
|
||||
<dimen name="overlay_prompt_button_width">148dp</dimen>
|
||||
|
@ -469,10 +469,10 @@
|
||||
<string name="identity_connection_secure">&identity_connection_secure;</string>
|
||||
<string name="identity_connection_insecure">&identity_connection_insecure;</string>
|
||||
|
||||
<string name="mixed_content_blocked_all">&mixed_content_blocked_all;</string>
|
||||
<string name="mixed_content_blocked_some">&mixed_content_blocked_some;</string>
|
||||
<string name="mixed_content_display_loaded">&mixed_content_display_loaded;</string>
|
||||
<string name="mixed_content_protection_disabled">&mixed_content_protection_disabled;</string>
|
||||
<string name="mixed_content_blocked_all">&mixed_content_blocked_all1;</string>
|
||||
<string name="mixed_content_blocked_some">&mixed_content_blocked_some1;</string>
|
||||
<string name="mixed_content_display_loaded">&mixed_content_display_loaded1;</string>
|
||||
<string name="mixed_content_protection_disabled">&mixed_content_protection_disabled1;</string>
|
||||
|
||||
<string name="doorhanger_tracking_title">&doorhanger_tracking_title;</string>
|
||||
<string name="doorhanger_tracking_state_enabled">&doorhanger_tracking_state_enabled;</string>
|
||||
|
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 3.2 KiB |