зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound a=merge on a CLOSED TREE
This commit is contained in:
Коммит
1ec6503fd8
|
@ -858,8 +858,6 @@ pref("browser.sessionstore.debug", false);
|
|||
pref("browser.sessionstore.debug.no_auto_updates", false);
|
||||
// Forget closed windows/tabs after two weeks
|
||||
pref("browser.sessionstore.cleanup.forget_closed_after", 1209600000);
|
||||
// Maximum number of bytes of DOMSessionStorage data we collect per origin.
|
||||
pref("browser.sessionstore.dom_storage_limit", 2048);
|
||||
// Amount of failed SessionFile writes until we restart the worker.
|
||||
pref("browser.sessionstore.max_write_failures", 5);
|
||||
|
||||
|
@ -1224,6 +1222,7 @@ pref("services.sync.prefs.sync.intl.accept_languages", true);
|
|||
pref("services.sync.prefs.sync.layout.spellcheckDefault", true);
|
||||
pref("services.sync.prefs.sync.lightweightThemes.selectedThemeID", true);
|
||||
pref("services.sync.prefs.sync.lightweightThemes.usedThemes", true);
|
||||
pref("services.sync.prefs.sync.media.eme.enabled", true);
|
||||
pref("services.sync.prefs.sync.network.cookie.cookieBehavior", true);
|
||||
pref("services.sync.prefs.sync.network.cookie.lifetimePolicy", true);
|
||||
pref("services.sync.prefs.sync.network.cookie.thirdparty.sessionOnly", true);
|
||||
|
|
|
@ -11,11 +11,15 @@ const CONTAINER_PAGE = "http://not-tracking.example.com/browser/browser/base/con
|
|||
const TPC_PREF = "network.cookie.cookieBehavior";
|
||||
|
||||
add_task(async function setup() {
|
||||
let oldCanRecord = Services.telemetry.canRecordExtended;
|
||||
Services.telemetry.canRecordExtended = true;
|
||||
|
||||
// Avoid the content blocking tour interfering with our tests by popping up.
|
||||
await SpecialPowers.pushPrefEnv({set: [[ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS]]});
|
||||
await UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
UrlClassifierTestUtils.cleanupTestTrackers();
|
||||
});
|
||||
});
|
||||
|
@ -38,6 +42,8 @@ async function assertSitesListed(trackersBlocked, thirdPartyBlocked, firstPartyB
|
|||
|
||||
await openIdentityPopup();
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let categoryItem =
|
||||
document.getElementById("identity-popup-content-blocking-category-cookies");
|
||||
ok(BrowserTestUtils.is_visible(categoryItem), "TP category item is visible");
|
||||
|
@ -48,6 +54,11 @@ async function assertSitesListed(trackersBlocked, thirdPartyBlocked, firstPartyB
|
|||
|
||||
ok(true, "Cookies view was shown");
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN).parent;
|
||||
let buttonEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "cookies_subview_btn");
|
||||
is(buttonEvents.length, 1, "recorded telemetry for the button click");
|
||||
|
||||
let listHeaders = cookiesView.querySelectorAll(".identity-popup-cookiesView-list-header");
|
||||
is(listHeaders.length, 3, "We have 3 list headers");
|
||||
|
||||
|
|
|
@ -7,17 +7,17 @@ const TP_PREF = "privacy.trackingprotection.enabled";
|
|||
const TPC_PREF = "network.cookie.cookieBehavior";
|
||||
const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/test/trackingUI/trackingPage.html";
|
||||
|
||||
async function waitAndAssertPreferencesShown() {
|
||||
async function waitAndAssertPreferencesShown(_spotlight) {
|
||||
await BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
|
||||
await TestUtils.waitForCondition(() => gBrowser.currentURI.spec == "about:preferences#privacy",
|
||||
"Should open about:preferences.");
|
||||
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {}, async function() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {spotlight: _spotlight}, async function({spotlight}) {
|
||||
let doc = content.document;
|
||||
let section = await ContentTaskUtils.waitForCondition(
|
||||
() => doc.querySelector(".spotlight"), "The spotlight should appear.");
|
||||
is(section.getAttribute("data-subcategory"), "trackingprotection",
|
||||
"The trackingprotection section is spotlighted.");
|
||||
is(section.getAttribute("data-subcategory"), spotlight,
|
||||
"The correct section is spotlighted.");
|
||||
});
|
||||
|
||||
BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
@ -30,14 +30,13 @@ add_task(async function setup() {
|
|||
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
UrlClassifierTestUtils.cleanupTestTrackers();
|
||||
});
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
});
|
||||
|
||||
// Tests that pressing the preferences icon in the identity popup
|
||||
// Tests that pressing the content blocking preferences icon in the identity popup
|
||||
// links to about:preferences
|
||||
add_task(async function testOpenPreferencesFromPrefsButton() {
|
||||
add_task(async function testOpenPreferencesFromCBPrefsButton() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async function() {
|
||||
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
|
||||
gIdentityHandler._identityBox.click();
|
||||
|
@ -45,9 +44,11 @@ add_task(async function testOpenPreferencesFromPrefsButton() {
|
|||
|
||||
let preferencesButton = document.getElementById("tracking-protection-preferences-button");
|
||||
|
||||
ok(!BrowserTestUtils.is_hidden(preferencesButton), "The enable tracking protection button is shown.");
|
||||
ok(BrowserTestUtils.is_visible(preferencesButton), "The preferences button is shown.");
|
||||
|
||||
let shown = waitAndAssertPreferencesShown();
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let shown = waitAndAssertPreferencesShown("trackingprotection");
|
||||
preferencesButton.click();
|
||||
await shown;
|
||||
|
||||
|
@ -58,35 +59,105 @@ add_task(async function testOpenPreferencesFromPrefsButton() {
|
|||
});
|
||||
});
|
||||
|
||||
// Tests that clicking the contentblocking category items "add blocking" labels
|
||||
// Tests that pressing the permissions preferences icon in the identity popup
|
||||
// links to about:preferences
|
||||
add_task(async function testOpenPreferencesFromAddBlockingButtons() {
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
[TP_PREF, false],
|
||||
[TPC_PREF, Ci.nsICookieService.BEHAVIOR_ACCEPT],
|
||||
]});
|
||||
add_task(async function testOpenPreferencesFromPermissionsPrefsButton() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async function() {
|
||||
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
|
||||
gIdentityHandler._identityBox.click();
|
||||
await promisePanelOpen;
|
||||
|
||||
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
|
||||
let addBlockingButtons = document.querySelectorAll(".identity-popup-content-blocking-category-add-blocking");
|
||||
for (let button of addBlockingButtons) {
|
||||
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
|
||||
gIdentityHandler._identityBox.click();
|
||||
await promisePanelOpen;
|
||||
let preferencesButton = document.getElementById("identity-popup-permission-preferences-button");
|
||||
|
||||
ok(BrowserTestUtils.is_visible(button), "Button is shown.");
|
||||
let shown = waitAndAssertPreferencesShown();
|
||||
button.click();
|
||||
await shown;
|
||||
ok(BrowserTestUtils.is_visible(preferencesButton), "The preferences button is shown.");
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).parent;
|
||||
let clickEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3].endsWith("_add_blocking"));
|
||||
is(clickEvents.length, 1, "recorded telemetry for the click");
|
||||
}
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let shown = waitAndAssertPreferencesShown("permissions");
|
||||
preferencesButton.click();
|
||||
await shown;
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).parent;
|
||||
let clickEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "permission_prefs_btn");
|
||||
is(clickEvents.length, 1, "recorded telemetry for the click");
|
||||
});
|
||||
});
|
||||
|
||||
// Tests that pressing the preferences button in the trackers subview
|
||||
// links to about:preferences
|
||||
add_task(async function testOpenPreferencesFromTrackersSubview() {
|
||||
Services.prefs.setBoolPref(TP_PREF, true);
|
||||
|
||||
add_task(async function cleanup() {
|
||||
UrlClassifierTestUtils.cleanupTestTrackers();
|
||||
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
|
||||
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
|
||||
gIdentityHandler._identityBox.click();
|
||||
await promisePanelOpen;
|
||||
|
||||
let categoryItem =
|
||||
document.getElementById("identity-popup-content-blocking-category-tracking-protection");
|
||||
ok(BrowserTestUtils.is_visible(categoryItem), "TP category item is visible");
|
||||
let trackersView = document.getElementById("identity-popup-trackersView");
|
||||
let viewShown = BrowserTestUtils.waitForEvent(trackersView, "ViewShown");
|
||||
categoryItem.click();
|
||||
await viewShown;
|
||||
|
||||
ok(true, "Trackers view was shown");
|
||||
|
||||
let preferencesButton = document.getElementById("identity-popup-trackersView-settings-button");
|
||||
|
||||
ok(BrowserTestUtils.is_visible(preferencesButton), "The preferences button is shown.");
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let shown = waitAndAssertPreferencesShown("trackingprotection");
|
||||
preferencesButton.click();
|
||||
await shown;
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).parent;
|
||||
let clickEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "trackers_prefs_btn");
|
||||
is(clickEvents.length, 1, "recorded telemetry for the click");
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref(TP_PREF);
|
||||
});
|
||||
|
||||
// Tests that pressing the preferences button in the cookies subview
|
||||
// links to about:preferences
|
||||
add_task(async function testOpenPreferencesFromCookiesSubview() {
|
||||
Services.prefs.setIntPref(TPC_PREF, Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER);
|
||||
|
||||
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function() {
|
||||
let promisePanelOpen = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popupshown");
|
||||
gIdentityHandler._identityBox.click();
|
||||
await promisePanelOpen;
|
||||
|
||||
let categoryItem =
|
||||
document.getElementById("identity-popup-content-blocking-category-cookies");
|
||||
ok(BrowserTestUtils.is_visible(categoryItem), "TP category item is visible");
|
||||
let cookiesView = document.getElementById("identity-popup-cookiesView");
|
||||
let viewShown = BrowserTestUtils.waitForEvent(cookiesView, "ViewShown");
|
||||
categoryItem.click();
|
||||
await viewShown;
|
||||
|
||||
ok(true, "Cookies view was shown");
|
||||
|
||||
let preferencesButton = document.getElementById("identity-popup-cookiesView-settings-button");
|
||||
|
||||
ok(BrowserTestUtils.is_visible(preferencesButton), "The preferences button is shown.");
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let shown = waitAndAssertPreferencesShown("trackingprotection");
|
||||
preferencesButton.click();
|
||||
await shown;
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true).parent;
|
||||
let clickEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "cookies_prefs_btn");
|
||||
is(clickEvents.length, 1, "recorded telemetry for the click");
|
||||
});
|
||||
|
||||
Services.prefs.clearUserPref(TPC_PREF);
|
||||
});
|
||||
|
|
|
@ -9,11 +9,15 @@ const TRACKING_PAGE = "http://tracking.example.org/browser/browser/base/content/
|
|||
const TP_PREF = "privacy.trackingprotection.enabled";
|
||||
|
||||
add_task(async function setup() {
|
||||
let oldCanRecord = Services.telemetry.canRecordExtended;
|
||||
Services.telemetry.canRecordExtended = true;
|
||||
|
||||
// Avoid the content blocking tour interfering with our tests by popping up.
|
||||
await SpecialPowers.pushPrefEnv({set: [[ContentBlocking.prefIntroCount, ContentBlocking.MAX_INTROS]]});
|
||||
await UrlClassifierTestUtils.addTestTrackers();
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.telemetry.canRecordExtended = oldCanRecord;
|
||||
UrlClassifierTestUtils.cleanupTestTrackers();
|
||||
});
|
||||
});
|
||||
|
@ -22,6 +26,8 @@ async function assertSitesListed(blocked) {
|
|||
await BrowserTestUtils.withNewTab(TRACKING_PAGE, async function(browser) {
|
||||
await openIdentityPopup();
|
||||
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
let categoryItem =
|
||||
document.getElementById("identity-popup-content-blocking-category-tracking-protection");
|
||||
ok(BrowserTestUtils.is_visible(categoryItem), "TP category item is visible");
|
||||
|
@ -32,6 +38,11 @@ async function assertSitesListed(blocked) {
|
|||
|
||||
ok(true, "Trackers view was shown");
|
||||
|
||||
let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN).parent;
|
||||
let buttonEvents = events.filter(
|
||||
e => e[1] == "security.ui.identitypopup" && e[2] == "click" && e[3] == "trackers_subview_btn");
|
||||
is(buttonEvents.length, 1, "recorded telemetry for the button click");
|
||||
|
||||
let listItems = trackersView.querySelectorAll(".identity-popup-content-blocking-list-item");
|
||||
is(listItems.length, 1, "We have 1 tracker in the list");
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<button id="identity-popup-security-expander"
|
||||
class="identity-popup-expander"
|
||||
when-connection="not-secure secure secure-ev secure-cert-user-overridden"
|
||||
oncommand="gIdentityHandler.showSecuritySubView();"/>
|
||||
oncommand="gIdentityHandler.showSecuritySubView(); gIdentityHandler.recordClick('security_subview_btn');"/>
|
||||
</hbox>
|
||||
|
||||
<!-- Tracking Protection Section -->
|
||||
|
@ -75,14 +75,14 @@
|
|||
|
||||
<vbox id="identity-popup-content-blocking-category-list">
|
||||
<toolbarbutton id="identity-popup-content-blocking-category-tracking-protection"
|
||||
onclick="ContentBlocking.showTrackersSubview()"
|
||||
onclick="ContentBlocking.showTrackersSubview(); gIdentityHandler.recordClick('trackers_subview_btn');"
|
||||
class="identity-popup-content-blocking-category" align="center">
|
||||
<image class="identity-popup-content-blocking-category-icon tracking-protection-icon"/>
|
||||
<label flex="1" class="identity-popup-content-blocking-category-label">&contentBlocking.trackingProtection3.label;</label>
|
||||
<label flex="1" id="identity-popup-content-blocking-tracking-protection-state-label" class="identity-popup-content-blocking-category-state-label"/>
|
||||
</toolbarbutton>
|
||||
<toolbarbutton id="identity-popup-content-blocking-category-cookies"
|
||||
onclick="ContentBlocking.showCookiesSubview()"
|
||||
onclick="ContentBlocking.showCookiesSubview(); gIdentityHandler.recordClick('cookies_subview_btn');"
|
||||
class="identity-popup-content-blocking-category" align="center">
|
||||
<image class="identity-popup-content-blocking-category-icon thirdpartycookies-icon"/>
|
||||
<label flex="1" id="identity-popup-content-blocking-category-label-default"
|
||||
|
@ -126,7 +126,7 @@
|
|||
<toolbarbutton id="identity-popup-permission-preferences-button"
|
||||
class="identity-popup-preferences-button subviewbutton"
|
||||
tooltiptext="&identity.permissionsPreferences.tooltip;"
|
||||
oncommand="gIdentityHandler.openPermissionPreferences();" />
|
||||
oncommand="gIdentityHandler.openPermissionPreferences(); gIdentityHandler.recordClick('permission_prefs_btn');" />
|
||||
</hbox>
|
||||
<vbox id="identity-popup-permission-list"/>
|
||||
<description id="identity-popup-permission-reload-hint">&identity.permissionsReloadHint;</description>
|
||||
|
@ -250,7 +250,7 @@
|
|||
<button id="identity-popup-trackersView-settings-button"
|
||||
label="&contentBlocking.manageSettings.label;"
|
||||
accesskey="&contentBlocking.manageSettings.accesskey;"
|
||||
oncommand="ContentBlocking.openPreferences();"/>
|
||||
oncommand="ContentBlocking.openPreferences(); gIdentityHandler.recordClick('trackers_prefs_btn');"/>
|
||||
</vbox>
|
||||
</panelview>
|
||||
|
||||
|
@ -265,7 +265,7 @@
|
|||
<button id="identity-popup-cookiesView-settings-button"
|
||||
label="&contentBlocking.manageSettings.label;"
|
||||
accesskey="&contentBlocking.manageSettings.accesskey;"
|
||||
oncommand="ContentBlocking.openPreferences();"/>
|
||||
oncommand="ContentBlocking.openPreferences(); gIdentityHandler.recordClick('cookies_prefs_btn');"/>
|
||||
</vbox>
|
||||
</panelview>
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
[lwt-newtab-brighttext] {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
.secondary {
|
||||
background-color: $grey-10-10;
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
// lifted from https://gist.github.com/kitze/23d82bb9eb0baabfd03a6a720b1d637f
|
||||
export const ConditionalWrapper = ({condition, wrap, children}) => (condition ? wrap(children) : children);
|
|
@ -23,7 +23,7 @@
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
[lwt-newtab-brighttext] & {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) & {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {Button} from "../../components/Button/Button";
|
||||
import {ConditionalWrapper} from "../../components/ConditionalWrapper/ConditionalWrapper";
|
||||
import React from "react";
|
||||
import {RichText} from "../../components/RichText/RichText";
|
||||
import {safeURI} from "../../template-utils";
|
||||
|
@ -67,22 +68,64 @@ export class SimpleSnippet extends React.PureComponent {
|
|||
sendClick={props.sendClick} />);
|
||||
}
|
||||
|
||||
wrapSectionHeader(url) {
|
||||
return function(children) {
|
||||
return <a href={url}>{children}</a>;
|
||||
};
|
||||
}
|
||||
|
||||
wrapSnippetContent(children) {
|
||||
return <div className="innerContentWrapper">{children}</div>;
|
||||
}
|
||||
|
||||
renderSectionHeader() {
|
||||
const {props} = this;
|
||||
|
||||
// an icon and text must be specified to render the section header
|
||||
if (props.content.section_title_icon && props.content.section_title_text) {
|
||||
const sectionTitleIcon = safeURI(props.content.section_title_icon);
|
||||
const sectionTitleURL = props.content.section_title_url;
|
||||
|
||||
return (
|
||||
<div className="section-header">
|
||||
<h3 className="section-title">
|
||||
<ConditionalWrapper condition={sectionTitleURL} wrap={this.wrapSectionHeader(sectionTitleURL)}>
|
||||
<span className="icon icon-small-spacer" style={{backgroundImage: `url("${sectionTitleIcon}")`}} />
|
||||
<span className="section-title-text">{props.content.section_title_text}</span>
|
||||
</ConditionalWrapper>
|
||||
</h3>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {props} = this;
|
||||
const sectionHeader = this.renderSectionHeader();
|
||||
let className = "SimpleSnippet";
|
||||
|
||||
if (props.className) {
|
||||
className += ` ${props.className}`;
|
||||
}
|
||||
if (props.content.tall) {
|
||||
className += " tall";
|
||||
}
|
||||
if (sectionHeader) {
|
||||
className += " has-section-header";
|
||||
}
|
||||
|
||||
return (<SnippetBase {...props} className={className} textStyle={this.props.textStyle}>
|
||||
<img src={safeURI(props.content.icon) || DEFAULT_ICON_PATH} className="icon" />
|
||||
<div>
|
||||
{this.renderTitle()} <p className="body">{this.renderText()}</p>
|
||||
{this.props.extraContent}
|
||||
</div>
|
||||
{<div>{this.renderButton()}</div>}
|
||||
{sectionHeader}
|
||||
<ConditionalWrapper condition={sectionHeader} wrap={this.wrapSnippetContent}>
|
||||
<img src={safeURI(props.content.icon) || DEFAULT_ICON_PATH} className="icon" />
|
||||
<div>
|
||||
{this.renderTitle()} <p className="body">{this.renderText()}</p>
|
||||
{this.props.extraContent}
|
||||
</div>
|
||||
{<div>{this.renderButton()}</div>}
|
||||
</ConditionalWrapper>
|
||||
</SnippetBase>);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,6 +97,20 @@
|
|||
"description": "Additional parameters for link action, example which specific menu the button should open"
|
||||
}
|
||||
}
|
||||
},
|
||||
"section_title_icon": {
|
||||
"type": "string",
|
||||
"description": "Section title icon. 16x16px. SVG or PNG preferred. section_title_text must also be specified to display."
|
||||
},
|
||||
"section_title_text": {
|
||||
"type": "string",
|
||||
"description": "Section title text. section_title_icon must also be specified to display."
|
||||
},
|
||||
"section_title_url": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/link_url"},
|
||||
{"description": "A url, section_title_text links to this"}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
@ -105,6 +119,7 @@
|
|||
"button_action": ["button_label"],
|
||||
"button_url": ["button_label"],
|
||||
"button_color": ["button_label"],
|
||||
"button_background_color": ["button_label"]
|
||||
"button_background_color": ["button_label"],
|
||||
"section_title_url": ["section_title_text"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
$section-header-height: 30px;
|
||||
$icon-width: 54px; // width of primary icon + margin
|
||||
|
||||
.SimpleSnippet {
|
||||
&.tall {
|
||||
padding: 27px 0;
|
||||
|
@ -88,4 +91,45 @@
|
|||
.icon {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
&.has-section-header .innerWrapper {
|
||||
// account for section header being 100% width
|
||||
flex-wrap: wrap;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
// wrapper div added if section-header is displayed that allows icon/text/button
|
||||
// to squish instead of wrapping. this is effectively replicating layout behavior
|
||||
// when section-header is *not* present.
|
||||
.innerContentWrapper {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
flex: 0 0 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
// color should match that of 'Recommended by Pocket' and 'Highlights' in newtab page
|
||||
color: var(--newtab-section-header-text-color);
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
font-weight: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 16px;
|
||||
margin-inline-end: 6px;
|
||||
margin-top: -2px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
background: $yellow-50;
|
||||
padding: 2px 5px;
|
||||
|
||||
[lwt-newtab-brighttext] & {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) & {
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,15 @@ export class BaseContent extends React.PureComponent {
|
|||
this.props.dispatch(ac.UserEvent({event: "OPEN_NEWTAB_PREFS"}));
|
||||
}
|
||||
|
||||
disableDarkTheme() {
|
||||
// Dark themes are not supported in discovery stream view
|
||||
// Add force-light-theme class to body tag to disable dark mode. See Bug 1519764
|
||||
const bodyClassNames = global.document.body.classList;
|
||||
if (!bodyClassNames.contains("force-light-theme")) {
|
||||
bodyClassNames.add("force-light-theme");
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {props} = this;
|
||||
const {App} = props;
|
||||
|
@ -147,6 +156,10 @@ export class BaseContent extends React.PureComponent {
|
|||
const isDiscoveryStream = props.DiscoveryStream.config && props.DiscoveryStream.config.enabled;
|
||||
const searchHandoffEnabled = prefs["improvesearch.handoffToAwesomebar"];
|
||||
|
||||
if (isDiscoveryStream) {
|
||||
this.disableDarkTheme();
|
||||
}
|
||||
|
||||
const outerClassName = [
|
||||
"outer-wrapper",
|
||||
shouldBeFixedToTop && "fixed-to-top",
|
||||
|
@ -171,7 +184,10 @@ export class BaseContent extends React.PureComponent {
|
|||
<ManualMigration />
|
||||
</div>
|
||||
}
|
||||
{isDiscoveryStream ? <DiscoveryStreamBase /> : <Sections />}
|
||||
{isDiscoveryStream ? (
|
||||
<ErrorBoundary className="borderless-error">
|
||||
<DiscoveryStreamBase />
|
||||
</ErrorBoundary>) : <Sections />}
|
||||
<PrefsButton onClick={this.openPreferences} />
|
||||
</div>
|
||||
<ConfirmDialog />
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.force-light-theme {
|
||||
--newtab-background-color: #{$grey-10} !important; // sass-lint:disable-line no-important
|
||||
--newtab-text-primary-color: #{$grey-90} !important; // sass-lint:disable-line no-important
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
// Offset the snippets container so things at the bottom of the page are still
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
[lwt-newtab-brighttext] & {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) & {
|
||||
background-color: $grey-60;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
renderComponent(component) {
|
||||
renderComponent(component, embedWidth) {
|
||||
let rows;
|
||||
const {spocs} = this.props.DiscoveryStream;
|
||||
|
||||
|
@ -157,6 +157,8 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
return (
|
||||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<Hero
|
||||
subComponentType={embedWidth >= 9 ? `cards` : `list`}
|
||||
feed={component.feed}
|
||||
title={component.header && component.header.title}
|
||||
data={component.data}
|
||||
border={component.properties.border}
|
||||
|
@ -173,6 +175,8 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<List
|
||||
feed={component.feed}
|
||||
fullWidth={component.properties.full_width}
|
||||
hasBorders={component.properties.border === "border"}
|
||||
hasImages={component.properties.has_images}
|
||||
hasNumbers={component.properties.has_numbers}
|
||||
items={component.properties.items}
|
||||
|
@ -203,7 +207,7 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
{row.components.map((component, componentIndex) => {
|
||||
styles[rowIndex] = [...styles[rowIndex] || [], component.styles];
|
||||
return (<div key={`component-${componentIndex}`}>
|
||||
{this.renderComponent(component)}
|
||||
{this.renderComponent(component, row.width)}
|
||||
</div>);
|
||||
})}
|
||||
</div>
|
||||
|
|
|
@ -31,7 +31,7 @@ export class DSCard extends React.PureComponent {
|
|||
</div>
|
||||
<div className="meta">
|
||||
<header className="title">{this.props.title}</header>
|
||||
<p className="excerpt">{this.props.excerpt}</p>
|
||||
{this.props.excerpt && <p className="excerpt">{this.props.excerpt}</p>}
|
||||
{this.props.context ? (
|
||||
<p className="context">{this.props.context}</p>
|
||||
) : (
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import {DSCard} from "../DSCard/DSCard.jsx";
|
||||
import {List} from "../List/List.jsx";
|
||||
import React from "react";
|
||||
import {truncateText} from "content-src/lib/truncate-text";
|
||||
|
||||
export class Hero extends React.PureComponent {
|
||||
constructor(props) {
|
||||
|
@ -36,7 +38,6 @@ export class Hero extends React.PureComponent {
|
|||
|
||||
let [heroRec, ...otherRecs] = data.recommendations.slice(0, this.props.items);
|
||||
this.heroRec = heroRec;
|
||||
let truncateText = (text, cap) => `${text.substring(0, cap)}${text.length > cap ? `...` : ``}`;
|
||||
|
||||
// Note that `{index + 1}` is necessary below for telemetry since we treat heroRec as index 0.
|
||||
let cards = otherRecs.map((rec, index) => (
|
||||
|
@ -49,10 +50,20 @@ export class Hero extends React.PureComponent {
|
|||
index={index + 1}
|
||||
type={this.props.type}
|
||||
dispatch={this.props.dispatch}
|
||||
context={truncateText(rec.context || "", 22)}
|
||||
source={truncateText(`TODO: SOURCE`, 22)} />
|
||||
context={truncateText(rec.context, 22)}
|
||||
source={truncateText(rec.domain, 22)} />
|
||||
));
|
||||
|
||||
let list = (
|
||||
<List
|
||||
recStartingPoint={1}
|
||||
feed={this.props.feed}
|
||||
hasImages={true}
|
||||
hasBorders={this.props.border === `border`}
|
||||
items={this.props.items}
|
||||
type={`Hero`} />
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="ds-header">{this.props.title}</div>
|
||||
|
@ -67,12 +78,12 @@ export class Hero extends React.PureComponent {
|
|||
{heroRec.context ? (
|
||||
<p className="context">{truncateText(heroRec.context, 22)}</p>
|
||||
) : (
|
||||
<p>{truncateText(`TODO: SOURCE`, 22)}</p>
|
||||
<p>{truncateText(heroRec.domain, 22)}</p>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
<div className="cards">
|
||||
{ cards }
|
||||
<div className={`${this.props.subComponentType}`}>
|
||||
{ this.props.subComponentType === `cards` ? cards : list }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
$card-header-in-hero-font-size: 13;
|
||||
$card-header-in-hero-line-height: 20;
|
||||
|
||||
.ds-hero {
|
||||
.img {
|
||||
@include image-as-background;
|
||||
}
|
||||
|
||||
header {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.538;
|
||||
}
|
||||
|
||||
.ds-list {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.ds-card {
|
||||
border: 0;
|
||||
|
||||
|
@ -14,6 +30,17 @@
|
|||
|
||||
.meta {
|
||||
padding: 0;
|
||||
|
||||
.title {
|
||||
// show only 2 lines of copy
|
||||
@include limit-visibile-lines(2, $card-header-in-hero-line-height, $card-header-in-hero-font-size);
|
||||
font-size: $card-header-in-hero-font-size * 1px;
|
||||
line-height: $card-header-in-hero-line-height * 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +56,11 @@
|
|||
border-top: $border-secondary;
|
||||
border-bottom: $border-secondary;
|
||||
|
||||
@at-root .ds-hero-no-border .wrapper {
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover .meta header {
|
||||
color: $blue-60;
|
||||
}
|
||||
|
@ -72,6 +104,17 @@
|
|||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px;
|
||||
|
||||
.img-wrapper {
|
||||
margin: 0;
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.meta {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.img {
|
||||
height: 0;
|
||||
padding-top: 100%; // 1:1 aspect ratio
|
||||
|
@ -97,6 +140,7 @@
|
|||
|
||||
.img-wrapper {
|
||||
width: 67%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.img {
|
||||
|
@ -114,6 +158,7 @@
|
|||
|
||||
p {
|
||||
font-size: 15px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import {connect} from "react-redux";
|
||||
import React from "react";
|
||||
import {truncateText} from "content-src/lib/truncate-text";
|
||||
|
||||
/**
|
||||
* @note exported for testing only
|
||||
|
@ -39,6 +40,7 @@ export class ListItem extends React.PureComponent {
|
|||
{this.props.title}
|
||||
</b>
|
||||
</div>
|
||||
{this.props.excerpt && <div className="ds-list-item-excerpt">{truncateText(this.props.excerpt, 90)}</div>}
|
||||
<div className="ds-list-item-info">{this.props.domain}</div>
|
||||
</div>
|
||||
<div className="ds-list-image" style={{backgroundImage: `url(${this.props.image_src})`}} />
|
||||
|
@ -60,25 +62,29 @@ export function _List(props) {
|
|||
|
||||
const recs = feed.data.recommendations;
|
||||
|
||||
let recMarkup = recs.slice(0, props.items).map((rec, index) => (
|
||||
let recMarkup = recs.slice(props.recStartingPoint, props.items).map((rec, index) => (
|
||||
<ListItem {...rec} key={`ds-list-item-${index}`} index={index} type={props.type} dispatch={props.dispatch} />)
|
||||
);
|
||||
|
||||
const listStyles = [
|
||||
"ds-list",
|
||||
props.fullWidth ? "ds-list-full-width" : "",
|
||||
props.hasBorders ? "ds-list-borders" : "",
|
||||
props.hasImages ? "ds-list-images" : "",
|
||||
props.hasNumbers ? "ds-list-numbers" : "",
|
||||
];
|
||||
return (
|
||||
<div>
|
||||
{props.header && props.header.title ? <div className="ds-header">{props.header.title}</div> : null }
|
||||
<hr className="ds-list-border" />
|
||||
<ul className={listStyles.join(" ")}>{recMarkup}</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_List.defaultProps = {
|
||||
recStartingPoint: 0, // Index of recommendations to start displaying from
|
||||
fullWidth: false, // Display items taking up the whole column
|
||||
hasBorders: false, // Display lines separating each item
|
||||
hasImages: false, // Display images for each item
|
||||
hasNumbers: false, // Display numbers for each item
|
||||
items: 6, // Number of stories to display. TODO: get from endpoint
|
||||
|
|
|
@ -1,17 +1,44 @@
|
|||
// Type sizes
|
||||
$item-font-size: 13;
|
||||
$item-image-size: 72px;
|
||||
$item-line-height: 20;
|
||||
|
||||
.ds-list-border {
|
||||
border: 0;
|
||||
border-top: $border-secondary;
|
||||
// XXX this is gross, and attaches the bottom-border to the item above.
|
||||
// Ideally, we'd attach the top-border to the item that needs it.
|
||||
// Unfortunately the border needs to go _above_ the row gap as currently
|
||||
// set up, which means that some refactoring will be required to do this.
|
||||
@mixin bottom-border-except-last-grid-row($columns) {
|
||||
.ds-list-item:not(:nth-last-child(-n+#{$columns})) {
|
||||
border-bottom: $border-secondary;
|
||||
margin-bottom: -1px; // cancel out the pixel we used for the border
|
||||
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
// Instead of using margin, we need to use these to override stuff that comes
|
||||
// by default from <hr>.
|
||||
margin-block-start: 8px;
|
||||
margin-block-end: 8px;
|
||||
@mixin set-item-sizes($font-size, $line-height, $image-size) {
|
||||
.ds-list-item {
|
||||
// XXX see if we really want absolute units, maybe hoist somewhere central?
|
||||
font-size: $font-size * 1px;
|
||||
line-height: $line-height * 1px;
|
||||
}
|
||||
|
||||
.ds-list-item-excerpt {
|
||||
@include limit-visibile-lines(2, $line-height, $font-size);
|
||||
}
|
||||
|
||||
.ds-list-item-info {
|
||||
@include limit-visibile-lines(1, $line-height, $font-size);
|
||||
}
|
||||
|
||||
.ds-list-item-title {
|
||||
@include limit-visibile-lines(2, $line-height, $font-size);
|
||||
}
|
||||
|
||||
.ds-list-image {
|
||||
min-width: $image-size;
|
||||
width: $image-size;
|
||||
}
|
||||
}
|
||||
|
||||
.ds-list {
|
||||
|
@ -23,22 +50,35 @@ $item-line-height: 20;
|
|||
// regression detection?
|
||||
padding-inline-start: 0;
|
||||
|
||||
// "2/3 width layout"
|
||||
.ds-column-5 &,
|
||||
.ds-column-6 &,
|
||||
.ds-column-7 &,
|
||||
.ds-column-8 & {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-row-gap: 24px;
|
||||
&:not(.ds-list-full-width) {
|
||||
@include set-item-sizes($item-font-size, $item-line-height, $item-image-size);
|
||||
|
||||
// "2/3 width layout"
|
||||
.ds-column-5 &,
|
||||
.ds-column-6 &,
|
||||
.ds-column-7 &,
|
||||
.ds-column-8 & {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
// "Full width layout"
|
||||
.ds-column-9 &,
|
||||
.ds-column-10 &,
|
||||
.ds-column-11 &,
|
||||
.ds-column-12 & {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 18px;
|
||||
}
|
||||
|
||||
.ds-list-item-excerpt {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// "Full width layout"
|
||||
.ds-column-9 &,
|
||||
.ds-column-10 &,
|
||||
.ds-column-11 &,
|
||||
.ds-column-12 & {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 18px;
|
||||
&:not(.ds-list-images) {
|
||||
.ds-list-image {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -47,12 +87,6 @@ $item-line-height: 20;
|
|||
}
|
||||
}
|
||||
|
||||
.ds-list-images {
|
||||
.ds-list-item .ds-list-image {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ds-list-numbers {
|
||||
$counter-whitespace: ($item-line-height - $item-font-size) * 1px;
|
||||
$counter-size: ($item-font-size) * 2px + $counter-whitespace;
|
||||
|
@ -90,22 +124,42 @@ $item-line-height: 20;
|
|||
}
|
||||
}
|
||||
|
||||
// XXX this is gross, and attaches the bottom-border to the item above.
|
||||
// Ideally, we'd attach the top-border to the item that needs it.
|
||||
// Unfortunately the border needs to go _above_ the row gap as currently
|
||||
// set up, which means that some refactoring will be required to do this.
|
||||
.ds-list-item:nth-child(-n+3) { // all but the last three items
|
||||
border-bottom: $border-secondary;
|
||||
margin-bottom: -1px; // cancel out the pixel we used for the border
|
||||
.ds-list-borders {
|
||||
border-top: $border-secondary;
|
||||
padding-top: $item-line-height * 1px;
|
||||
|
||||
padding-bottom: 2px;
|
||||
&.ds-list-full-width,
|
||||
.ds-column-1 &,
|
||||
.ds-column-2 &,
|
||||
.ds-column-3 &,
|
||||
.ds-column-4 & {
|
||||
@include bottom-border-except-last-grid-row(1);
|
||||
}
|
||||
|
||||
&:not(.ds-list-full-width) {
|
||||
// "2/3 width layout"
|
||||
.ds-column-5 &,
|
||||
.ds-column-6 &,
|
||||
.ds-column-7 &,
|
||||
.ds-column-8 & {
|
||||
@include bottom-border-except-last-grid-row(2);
|
||||
}
|
||||
|
||||
// "Full width layout"
|
||||
.ds-column-9 &,
|
||||
.ds-column-10 &,
|
||||
.ds-column-11 &,
|
||||
.ds-column-12 & {
|
||||
@include bottom-border-except-last-grid-row(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ds-list-full-width {
|
||||
@include set-item-sizes(17, 24, $item-image-size * 2);
|
||||
}
|
||||
|
||||
.ds-list-item {
|
||||
// XXX see if we really want absolute units, maybe hoist somewhere central?
|
||||
line-height: $item-line-height * 1px;
|
||||
font-size: $item-font-size * 1px;
|
||||
|
||||
// reset some stuff from <li>. Should maybe be hoisted when we have better
|
||||
// regression detection?
|
||||
display: block;
|
||||
|
@ -120,18 +174,17 @@ $item-line-height: 20;
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ds-list-item-excerpt {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ds-list-item-info {
|
||||
@include limit-visibile-lines(1, $item-line-height, $item-font-size);
|
||||
|
||||
color: $grey-50;
|
||||
|
||||
overflow: hidden;
|
||||
color: var(--newtab-text-secondary-color);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ds-list-item-title {
|
||||
@include limit-visibile-lines(2, $item-line-height, $item-font-size);
|
||||
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
|
@ -141,15 +194,10 @@ $item-line-height: 20;
|
|||
}
|
||||
|
||||
.ds-list-image {
|
||||
$image-size: 72px;
|
||||
|
||||
@include image-as-background;
|
||||
display: none;
|
||||
height: $image-size;
|
||||
height: $item-image-size;
|
||||
margin-inline-start: $item-font-size * 1px;
|
||||
min-height: $image-size;
|
||||
min-width: $image-size;
|
||||
width: $image-size;
|
||||
min-height: $item-image-size;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
justify-items: center;
|
||||
line-height: $error-fallback-line-height;
|
||||
|
||||
&.borderless-error {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--newtab-text-conditional-color);
|
||||
text-decoration: underline;
|
||||
|
|
|
@ -146,7 +146,7 @@ export class _Search extends React.PureComponent {
|
|||
tabIndex="-1"
|
||||
title={this.props.intl.formatMessage({id: "search_web_placeholder"})}>
|
||||
<div className="fake-textbox">{this.props.intl.formatMessage({id: "search_web_placeholder"})}</div>
|
||||
<div className="fake-editable" tabIndex="-1" aria-hidden="true" contentEditable="" onDrop={this.onSearchHandoffDrop} onPaste={this.onSearchHandoffPaste} />
|
||||
<input type="search" className="fake-editable" tabIndex="-1" aria-hidden="true" onDrop={this.onSearchHandoffDrop} onPaste={this.onSearchHandoffPaste} />
|
||||
<div className="fake-caret" />
|
||||
</button>
|
||||
{/*
|
||||
|
|
|
@ -181,6 +181,8 @@ $glyph-forward: url('chrome://browser/skin/forward.svg');
|
|||
|
||||
.fake-editable {
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export function truncateText(text = "", cap) {
|
||||
return text.substring(0, cap).trim() + (text.length > cap ? "…" : "");
|
||||
}
|
|
@ -78,7 +78,7 @@ body {
|
|||
--newtab-snippets-background-color: #{$white};
|
||||
--newtab-snippets-hairline-color: transparent;
|
||||
|
||||
&[lwt-newtab-brighttext] {
|
||||
&[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
// General styles
|
||||
--newtab-background-color: #{$grey-80};
|
||||
--newtab-border-primary-color: #{$grey-10-80};
|
||||
|
|
|
@ -4,7 +4,7 @@ $os-infopanel-arrow-height: 10px;
|
|||
$os-infopanel-arrow-offset-end: 7px;
|
||||
$os-infopanel-arrow-width: 18px;
|
||||
|
||||
[lwt-newtab-brighttext] {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ body {
|
|||
--newtab-card-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
--newtab-snippets-background-color: #FFF;
|
||||
--newtab-snippets-hairline-color: transparent; }
|
||||
body[lwt-newtab-brighttext] {
|
||||
body[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
--newtab-background-color: #2A2A2E;
|
||||
--newtab-border-primary-color: rgba(249, 249, 250, 0.8);
|
||||
--newtab-border-secondary-color: rgba(249, 249, 250, 0.1);
|
||||
|
@ -336,6 +336,10 @@ input[type='text'], input[type='search'] {
|
|||
.outer-wrapper a {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
|
||||
.force-light-theme {
|
||||
--newtab-background-color: #F9F9FA !important;
|
||||
--newtab-text-primary-color: #0C0C0D !important; }
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding-bottom: 68px;
|
||||
|
@ -399,6 +403,8 @@ main {
|
|||
justify-content: center;
|
||||
justify-items: center;
|
||||
line-height: 1.5; }
|
||||
.as-error-fallback.borderless-error {
|
||||
box-shadow: none; }
|
||||
.as-error-fallback a {
|
||||
color: var(--newtab-text-conditional-color);
|
||||
text-decoration: underline; }
|
||||
|
@ -1081,6 +1087,8 @@ main {
|
|||
caret-color: transparent; }
|
||||
.search-handoff-button .fake-editable {
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -1343,7 +1351,7 @@ main {
|
|||
height: 122px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
[lwt-newtab-brighttext] .card-outer .card-preview-image-outer {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .card-outer .card-preview-image-outer {
|
||||
background-color: #4A4A4F; }
|
||||
.card-outer .card-preview-image-outer::after {
|
||||
border-bottom: 1px solid var(--newtab-card-hairline-color);
|
||||
|
@ -1682,7 +1690,7 @@ main {
|
|||
.asrouter-admin .message-item.current .message-id span {
|
||||
background: #FFE900;
|
||||
padding: 2px 5px; }
|
||||
[lwt-newtab-brighttext] .asrouter-admin .message-item.current .message-id span {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .asrouter-admin .message-item.current .message-id span {
|
||||
color: #000; }
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
|
@ -1855,6 +1863,16 @@ main {
|
|||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box; }
|
||||
|
||||
.ds-hero header {
|
||||
font-weight: 600; }
|
||||
|
||||
.ds-hero p {
|
||||
line-height: 1.538; }
|
||||
|
||||
.ds-hero .ds-list {
|
||||
border-top: 0;
|
||||
padding-top: 0; }
|
||||
|
||||
.ds-hero .ds-card {
|
||||
border: 0; }
|
||||
.ds-hero .ds-card:hover {
|
||||
|
@ -1863,6 +1881,13 @@ main {
|
|||
border-radius: 0; }
|
||||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
.ds-hero .ds-card .meta .title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-hero .ds-card .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
@ -1873,6 +1898,9 @@ main {
|
|||
padding: 20px 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color); }
|
||||
.ds-hero-no-border .wrapper {
|
||||
border-top: 0;
|
||||
border-bottom: 0; }
|
||||
.ds-hero .wrapper:hover .meta header {
|
||||
color: #0060DF; }
|
||||
.ds-hero .wrapper:active .meta header {
|
||||
|
@ -1897,6 +1925,19 @@ main {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
.ds-column-5 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-6 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-7 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-8 .ds-hero .wrapper .img-wrapper {
|
||||
margin: 0;
|
||||
grid-column: 2;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .meta,
|
||||
.ds-column-6 .ds-hero .wrapper .meta,
|
||||
.ds-column-7 .ds-hero .wrapper .meta,
|
||||
.ds-column-8 .ds-hero .wrapper .meta {
|
||||
grid-column: 1;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .img,
|
||||
.ds-column-6 .ds-hero .wrapper .img,
|
||||
.ds-column-7 .ds-hero .wrapper .img,
|
||||
|
@ -1923,7 +1964,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-11 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-12 .ds-hero .wrapper .img-wrapper {
|
||||
width: 67%; }
|
||||
width: 67%;
|
||||
margin: 0; }
|
||||
.ds-column-9 .ds-hero .wrapper .img,
|
||||
.ds-column-10 .ds-hero .wrapper .img,
|
||||
.ds-column-11 .ds-hero .wrapper .img,
|
||||
|
@ -1945,7 +1987,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .meta p,
|
||||
.ds-column-11 .ds-hero .wrapper .meta p,
|
||||
.ds-column-12 .ds-hero .wrapper .meta p {
|
||||
font-size: 15px; }
|
||||
font-size: 15px;
|
||||
line-height: 1.6; }
|
||||
|
||||
.ds-column-9 .ds-hero .cards,
|
||||
.ds-column-10 .ds-hero .cards,
|
||||
|
@ -1960,36 +2003,44 @@ main {
|
|||
height: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color); }
|
||||
|
||||
.ds-list-border {
|
||||
border: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 1px;
|
||||
margin-block-start: 8px;
|
||||
margin-block-end: 8px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-row-gap: 24px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
.ds-column-5 .ds-list,
|
||||
.ds-column-6 .ds-list,
|
||||
.ds-column-7 .ds-list,
|
||||
.ds-column-8 .ds-list {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-row-gap: 24px; }
|
||||
.ds-column-9 .ds-list,
|
||||
.ds-column-10 .ds-list,
|
||||
.ds-column-11 .ds-list,
|
||||
.ds-column-12 .ds-list {
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item {
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-image {
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
.ds-column-5 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-6 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-7 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-8 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(2, 1fr); }
|
||||
.ds-column-9 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-10 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-11 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-12 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 18px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
display: none; }
|
||||
.ds-list:not(.ds-list-images) .ds-list-image {
|
||||
display: none; }
|
||||
.ds-list a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.ds-list-images .ds-list-item .ds-list-image {
|
||||
display: block; }
|
||||
|
||||
.ds-list-numbers .ds-list-item {
|
||||
counter-increment: list; }
|
||||
|
||||
|
@ -2013,14 +2064,53 @@ main {
|
|||
.ds-list-numbers .ds-list-item-link:active::before {
|
||||
background-color: #003EAA; }
|
||||
|
||||
.ds-list-item:nth-child(-n+3) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-list-borders {
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 20px; }
|
||||
.ds-list-borders.ds-list-full-width .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-1 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-2 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-3 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-4 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-5 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-6 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-7 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-8 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-9 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-10 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-11 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-12 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item {
|
||||
font-size: 17px;
|
||||
line-height: 24px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-excerpt {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-info {
|
||||
max-height: 1.41176em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-image {
|
||||
min-width: 144px;
|
||||
width: 144px; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
|
@ -2028,15 +2118,13 @@ main {
|
|||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-excerpt {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden;
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
color: var(--newtab-text-secondary-color);
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
|
@ -2049,12 +2137,9 @@ main {
|
|||
border-radius: 4px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
height: 72px;
|
||||
margin-inline-start: 13px;
|
||||
min-height: 72px;
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
min-height: 72px; }
|
||||
.ds-list-item:hover .ds-list-item-title {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
.ds-list-item:active .ds-list-item-title {
|
||||
|
@ -2241,18 +2326,18 @@ main {
|
|||
.ASRouterButton.secondary:active {
|
||||
background-color: rgba(12, 12, 13, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.1); }
|
||||
[lwt-newtab-brighttext] .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.2); }
|
||||
[lwt-newtab-brighttext] .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .footer .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.4); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.5); }
|
||||
|
||||
.SnippetBaseContainer {
|
||||
|
@ -2274,7 +2359,7 @@ main {
|
|||
color: var(--newtab-link-primary-color); }
|
||||
.SnippetBaseContainer a:hover {
|
||||
text-decoration: underline; }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer input[type='checkbox'] {
|
||||
margin-inline-start: 0; }
|
||||
|
@ -2581,6 +2666,34 @@ main {
|
|||
.SimpleSnippet .icon {
|
||||
align-self: flex-start; }
|
||||
|
||||
.SimpleSnippet.has-section-header .innerWrapper {
|
||||
flex-wrap: wrap;
|
||||
padding-top: 7px; }
|
||||
|
||||
.SimpleSnippet .innerContentWrapper {
|
||||
align-items: center;
|
||||
display: flex; }
|
||||
|
||||
.SimpleSnippet .section-header {
|
||||
flex: 0 0 100%;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.SimpleSnippet .section-title {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 0; }
|
||||
.SimpleSnippet .section-title a {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
font-weight: inherit;
|
||||
text-decoration: none; }
|
||||
.SimpleSnippet .section-title .icon {
|
||||
height: 16px;
|
||||
margin-inline-end: 6px;
|
||||
margin-top: -2px;
|
||||
width: 16px; }
|
||||
|
||||
.SubmitFormSnippet {
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,6 +1,6 @@
|
|||
@charset "UTF-8";
|
||||
/* This is the mac variant */
|
||||
[lwt-newtab-brighttext] {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
-moz-osx-font-smoothing: grayscale; }
|
||||
|
||||
html {
|
||||
|
@ -71,7 +71,7 @@ body {
|
|||
--newtab-card-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
--newtab-snippets-background-color: #FFF;
|
||||
--newtab-snippets-hairline-color: transparent; }
|
||||
body[lwt-newtab-brighttext] {
|
||||
body[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
--newtab-background-color: #2A2A2E;
|
||||
--newtab-border-primary-color: rgba(249, 249, 250, 0.8);
|
||||
--newtab-border-secondary-color: rgba(249, 249, 250, 0.1);
|
||||
|
@ -339,6 +339,10 @@ input[type='text'], input[type='search'] {
|
|||
.outer-wrapper a {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
|
||||
.force-light-theme {
|
||||
--newtab-background-color: #F9F9FA !important;
|
||||
--newtab-text-primary-color: #0C0C0D !important; }
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding-bottom: 68px;
|
||||
|
@ -402,6 +406,8 @@ main {
|
|||
justify-content: center;
|
||||
justify-items: center;
|
||||
line-height: 1.5; }
|
||||
.as-error-fallback.borderless-error {
|
||||
box-shadow: none; }
|
||||
.as-error-fallback a {
|
||||
color: var(--newtab-text-conditional-color);
|
||||
text-decoration: underline; }
|
||||
|
@ -1084,6 +1090,8 @@ main {
|
|||
caret-color: transparent; }
|
||||
.search-handoff-button .fake-editable {
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -1346,7 +1354,7 @@ main {
|
|||
height: 122px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
[lwt-newtab-brighttext] .card-outer .card-preview-image-outer {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .card-outer .card-preview-image-outer {
|
||||
background-color: #4A4A4F; }
|
||||
.card-outer .card-preview-image-outer::after {
|
||||
border-bottom: 1px solid var(--newtab-card-hairline-color);
|
||||
|
@ -1685,7 +1693,7 @@ main {
|
|||
.asrouter-admin .message-item.current .message-id span {
|
||||
background: #FFE900;
|
||||
padding: 2px 5px; }
|
||||
[lwt-newtab-brighttext] .asrouter-admin .message-item.current .message-id span {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .asrouter-admin .message-item.current .message-id span {
|
||||
color: #000; }
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
|
@ -1858,6 +1866,16 @@ main {
|
|||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box; }
|
||||
|
||||
.ds-hero header {
|
||||
font-weight: 600; }
|
||||
|
||||
.ds-hero p {
|
||||
line-height: 1.538; }
|
||||
|
||||
.ds-hero .ds-list {
|
||||
border-top: 0;
|
||||
padding-top: 0; }
|
||||
|
||||
.ds-hero .ds-card {
|
||||
border: 0; }
|
||||
.ds-hero .ds-card:hover {
|
||||
|
@ -1866,6 +1884,13 @@ main {
|
|||
border-radius: 0; }
|
||||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
.ds-hero .ds-card .meta .title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-hero .ds-card .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
@ -1876,6 +1901,9 @@ main {
|
|||
padding: 20px 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color); }
|
||||
.ds-hero-no-border .wrapper {
|
||||
border-top: 0;
|
||||
border-bottom: 0; }
|
||||
.ds-hero .wrapper:hover .meta header {
|
||||
color: #0060DF; }
|
||||
.ds-hero .wrapper:active .meta header {
|
||||
|
@ -1900,6 +1928,19 @@ main {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
.ds-column-5 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-6 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-7 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-8 .ds-hero .wrapper .img-wrapper {
|
||||
margin: 0;
|
||||
grid-column: 2;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .meta,
|
||||
.ds-column-6 .ds-hero .wrapper .meta,
|
||||
.ds-column-7 .ds-hero .wrapper .meta,
|
||||
.ds-column-8 .ds-hero .wrapper .meta {
|
||||
grid-column: 1;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .img,
|
||||
.ds-column-6 .ds-hero .wrapper .img,
|
||||
.ds-column-7 .ds-hero .wrapper .img,
|
||||
|
@ -1926,7 +1967,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-11 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-12 .ds-hero .wrapper .img-wrapper {
|
||||
width: 67%; }
|
||||
width: 67%;
|
||||
margin: 0; }
|
||||
.ds-column-9 .ds-hero .wrapper .img,
|
||||
.ds-column-10 .ds-hero .wrapper .img,
|
||||
.ds-column-11 .ds-hero .wrapper .img,
|
||||
|
@ -1948,7 +1990,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .meta p,
|
||||
.ds-column-11 .ds-hero .wrapper .meta p,
|
||||
.ds-column-12 .ds-hero .wrapper .meta p {
|
||||
font-size: 15px; }
|
||||
font-size: 15px;
|
||||
line-height: 1.6; }
|
||||
|
||||
.ds-column-9 .ds-hero .cards,
|
||||
.ds-column-10 .ds-hero .cards,
|
||||
|
@ -1963,36 +2006,44 @@ main {
|
|||
height: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color); }
|
||||
|
||||
.ds-list-border {
|
||||
border: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 1px;
|
||||
margin-block-start: 8px;
|
||||
margin-block-end: 8px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-row-gap: 24px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
.ds-column-5 .ds-list,
|
||||
.ds-column-6 .ds-list,
|
||||
.ds-column-7 .ds-list,
|
||||
.ds-column-8 .ds-list {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-row-gap: 24px; }
|
||||
.ds-column-9 .ds-list,
|
||||
.ds-column-10 .ds-list,
|
||||
.ds-column-11 .ds-list,
|
||||
.ds-column-12 .ds-list {
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item {
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-image {
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
.ds-column-5 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-6 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-7 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-8 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(2, 1fr); }
|
||||
.ds-column-9 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-10 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-11 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-12 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 18px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
display: none; }
|
||||
.ds-list:not(.ds-list-images) .ds-list-image {
|
||||
display: none; }
|
||||
.ds-list a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.ds-list-images .ds-list-item .ds-list-image {
|
||||
display: block; }
|
||||
|
||||
.ds-list-numbers .ds-list-item {
|
||||
counter-increment: list; }
|
||||
|
||||
|
@ -2016,14 +2067,53 @@ main {
|
|||
.ds-list-numbers .ds-list-item-link:active::before {
|
||||
background-color: #003EAA; }
|
||||
|
||||
.ds-list-item:nth-child(-n+3) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-list-borders {
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 20px; }
|
||||
.ds-list-borders.ds-list-full-width .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-1 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-2 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-3 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-4 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-5 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-6 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-7 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-8 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-9 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-10 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-11 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-12 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item {
|
||||
font-size: 17px;
|
||||
line-height: 24px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-excerpt {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-info {
|
||||
max-height: 1.41176em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-image {
|
||||
min-width: 144px;
|
||||
width: 144px; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
|
@ -2031,15 +2121,13 @@ main {
|
|||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-excerpt {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden;
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
color: var(--newtab-text-secondary-color);
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
|
@ -2052,12 +2140,9 @@ main {
|
|||
border-radius: 4px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
height: 72px;
|
||||
margin-inline-start: 13px;
|
||||
min-height: 72px;
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
min-height: 72px; }
|
||||
.ds-list-item:hover .ds-list-item-title {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
.ds-list-item:active .ds-list-item-title {
|
||||
|
@ -2244,18 +2329,18 @@ main {
|
|||
.ASRouterButton.secondary:active {
|
||||
background-color: rgba(12, 12, 13, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.1); }
|
||||
[lwt-newtab-brighttext] .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.2); }
|
||||
[lwt-newtab-brighttext] .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .footer .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.4); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.5); }
|
||||
|
||||
.SnippetBaseContainer {
|
||||
|
@ -2277,7 +2362,7 @@ main {
|
|||
color: var(--newtab-link-primary-color); }
|
||||
.SnippetBaseContainer a:hover {
|
||||
text-decoration: underline; }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer input[type='checkbox'] {
|
||||
margin-inline-start: 0; }
|
||||
|
@ -2584,6 +2669,34 @@ main {
|
|||
.SimpleSnippet .icon {
|
||||
align-self: flex-start; }
|
||||
|
||||
.SimpleSnippet.has-section-header .innerWrapper {
|
||||
flex-wrap: wrap;
|
||||
padding-top: 7px; }
|
||||
|
||||
.SimpleSnippet .innerContentWrapper {
|
||||
align-items: center;
|
||||
display: flex; }
|
||||
|
||||
.SimpleSnippet .section-header {
|
||||
flex: 0 0 100%;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.SimpleSnippet .section-title {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 0; }
|
||||
.SimpleSnippet .section-title a {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
font-weight: inherit;
|
||||
text-decoration: none; }
|
||||
.SimpleSnippet .section-title .icon {
|
||||
height: 16px;
|
||||
margin-inline-end: 6px;
|
||||
margin-top: -2px;
|
||||
width: 16px; }
|
||||
|
||||
.SubmitFormSnippet {
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -68,7 +68,7 @@ body {
|
|||
--newtab-card-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
--newtab-snippets-background-color: #FFF;
|
||||
--newtab-snippets-hairline-color: transparent; }
|
||||
body[lwt-newtab-brighttext] {
|
||||
body[lwt-newtab-brighttext]:not(.force-light-theme) {
|
||||
--newtab-background-color: #2A2A2E;
|
||||
--newtab-border-primary-color: rgba(249, 249, 250, 0.8);
|
||||
--newtab-border-secondary-color: rgba(249, 249, 250, 0.1);
|
||||
|
@ -336,6 +336,10 @@ input[type='text'], input[type='search'] {
|
|||
.outer-wrapper a {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
|
||||
.force-light-theme {
|
||||
--newtab-background-color: #F9F9FA !important;
|
||||
--newtab-text-primary-color: #0C0C0D !important; }
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding-bottom: 68px;
|
||||
|
@ -399,6 +403,8 @@ main {
|
|||
justify-content: center;
|
||||
justify-items: center;
|
||||
line-height: 1.5; }
|
||||
.as-error-fallback.borderless-error {
|
||||
box-shadow: none; }
|
||||
.as-error-fallback a {
|
||||
color: var(--newtab-text-conditional-color);
|
||||
text-decoration: underline; }
|
||||
|
@ -1081,6 +1087,8 @@ main {
|
|||
caret-color: transparent; }
|
||||
.search-handoff-button .fake-editable {
|
||||
color: transparent;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -1343,7 +1351,7 @@ main {
|
|||
height: 122px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
[lwt-newtab-brighttext] .card-outer .card-preview-image-outer {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .card-outer .card-preview-image-outer {
|
||||
background-color: #4A4A4F; }
|
||||
.card-outer .card-preview-image-outer::after {
|
||||
border-bottom: 1px solid var(--newtab-card-hairline-color);
|
||||
|
@ -1682,7 +1690,7 @@ main {
|
|||
.asrouter-admin .message-item.current .message-id span {
|
||||
background: #FFE900;
|
||||
padding: 2px 5px; }
|
||||
[lwt-newtab-brighttext] .asrouter-admin .message-item.current .message-id span {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .asrouter-admin .message-item.current .message-id span {
|
||||
color: #000; }
|
||||
.asrouter-admin .message-item.blocked .message-id,
|
||||
.asrouter-admin .message-item.blocked .message-summary {
|
||||
|
@ -1855,6 +1863,16 @@ main {
|
|||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box; }
|
||||
|
||||
.ds-hero header {
|
||||
font-weight: 600; }
|
||||
|
||||
.ds-hero p {
|
||||
line-height: 1.538; }
|
||||
|
||||
.ds-hero .ds-list {
|
||||
border-top: 0;
|
||||
padding-top: 0; }
|
||||
|
||||
.ds-hero .ds-card {
|
||||
border: 0; }
|
||||
.ds-hero .ds-card:hover {
|
||||
|
@ -1863,6 +1881,13 @@ main {
|
|||
border-radius: 0; }
|
||||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
.ds-hero .ds-card .meta .title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-hero .ds-card .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
@ -1873,6 +1898,9 @@ main {
|
|||
padding: 20px 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color); }
|
||||
.ds-hero-no-border .wrapper {
|
||||
border-top: 0;
|
||||
border-bottom: 0; }
|
||||
.ds-hero .wrapper:hover .meta header {
|
||||
color: #0060DF; }
|
||||
.ds-hero .wrapper:active .meta header {
|
||||
|
@ -1897,6 +1925,19 @@ main {
|
|||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
.ds-column-5 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-6 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-7 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-8 .ds-hero .wrapper .img-wrapper {
|
||||
margin: 0;
|
||||
grid-column: 2;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .meta,
|
||||
.ds-column-6 .ds-hero .wrapper .meta,
|
||||
.ds-column-7 .ds-hero .wrapper .meta,
|
||||
.ds-column-8 .ds-hero .wrapper .meta {
|
||||
grid-column: 1;
|
||||
grid-row: 1; }
|
||||
.ds-column-5 .ds-hero .wrapper .img,
|
||||
.ds-column-6 .ds-hero .wrapper .img,
|
||||
.ds-column-7 .ds-hero .wrapper .img,
|
||||
|
@ -1923,7 +1964,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-11 .ds-hero .wrapper .img-wrapper,
|
||||
.ds-column-12 .ds-hero .wrapper .img-wrapper {
|
||||
width: 67%; }
|
||||
width: 67%;
|
||||
margin: 0; }
|
||||
.ds-column-9 .ds-hero .wrapper .img,
|
||||
.ds-column-10 .ds-hero .wrapper .img,
|
||||
.ds-column-11 .ds-hero .wrapper .img,
|
||||
|
@ -1945,7 +1987,8 @@ main {
|
|||
.ds-column-10 .ds-hero .wrapper .meta p,
|
||||
.ds-column-11 .ds-hero .wrapper .meta p,
|
||||
.ds-column-12 .ds-hero .wrapper .meta p {
|
||||
font-size: 15px; }
|
||||
font-size: 15px;
|
||||
line-height: 1.6; }
|
||||
|
||||
.ds-column-9 .ds-hero .cards,
|
||||
.ds-column-10 .ds-hero .cards,
|
||||
|
@ -1960,36 +2003,44 @@ main {
|
|||
height: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color); }
|
||||
|
||||
.ds-list-border {
|
||||
border: 0;
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 1px;
|
||||
margin-block-start: 8px;
|
||||
margin-block-end: 8px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-row-gap: 24px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
.ds-column-5 .ds-list,
|
||||
.ds-column-6 .ds-list,
|
||||
.ds-column-7 .ds-list,
|
||||
.ds-column-8 .ds-list {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-row-gap: 24px; }
|
||||
.ds-column-9 .ds-list,
|
||||
.ds-column-10 .ds-list,
|
||||
.ds-column-11 .ds-list,
|
||||
.ds-column-12 .ds-list {
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item {
|
||||
font-size: 13px;
|
||||
line-height: 20px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-image {
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
.ds-column-5 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-6 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-7 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-8 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(2, 1fr); }
|
||||
.ds-column-9 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-10 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-11 .ds-list:not(.ds-list-full-width),
|
||||
.ds-column-12 .ds-list:not(.ds-list-full-width) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 18px; }
|
||||
.ds-list:not(.ds-list-full-width) .ds-list-item-excerpt {
|
||||
display: none; }
|
||||
.ds-list:not(.ds-list-images) .ds-list-image {
|
||||
display: none; }
|
||||
.ds-list a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.ds-list-images .ds-list-item .ds-list-image {
|
||||
display: block; }
|
||||
|
||||
.ds-list-numbers .ds-list-item {
|
||||
counter-increment: list; }
|
||||
|
||||
|
@ -2013,14 +2064,53 @@ main {
|
|||
.ds-list-numbers .ds-list-item-link:active::before {
|
||||
background-color: #003EAA; }
|
||||
|
||||
.ds-list-item:nth-child(-n+3) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-list-borders {
|
||||
border-top: 1px solid var(--newtab-border-secondary-color);
|
||||
padding-top: 20px; }
|
||||
.ds-list-borders.ds-list-full-width .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-1 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-2 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-3 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)),
|
||||
.ds-column-4 .ds-list-borders .ds-list-item:not(:nth-last-child(-n+1)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-5 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-6 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-7 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)),
|
||||
.ds-column-8 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+2)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
.ds-column-9 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-10 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-11 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)),
|
||||
.ds-column-12 .ds-list-borders:not(.ds-list-full-width) .ds-list-item:not(:nth-last-child(-n+3)) {
|
||||
border-bottom: 1px solid var(--newtab-border-secondary-color);
|
||||
margin-bottom: -1px;
|
||||
padding-bottom: 2px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item {
|
||||
font-size: 17px;
|
||||
line-height: 24px; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-excerpt {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-info {
|
||||
max-height: 1.41176em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-item-title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
|
||||
.ds-list-full-width .ds-list-image {
|
||||
min-width: 144px;
|
||||
width: 144px; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
|
@ -2028,15 +2118,13 @@ main {
|
|||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-excerpt {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
max-height: 1.53846em;
|
||||
overflow: hidden;
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
color: var(--newtab-text-secondary-color);
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
max-height: 3.07692em;
|
||||
overflow: hidden;
|
||||
margin-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
|
@ -2049,12 +2137,9 @@ main {
|
|||
border-radius: 4px;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
box-sizing: border-box;
|
||||
display: none;
|
||||
height: 72px;
|
||||
margin-inline-start: 13px;
|
||||
min-height: 72px;
|
||||
min-width: 72px;
|
||||
width: 72px; }
|
||||
min-height: 72px; }
|
||||
.ds-list-item:hover .ds-list-item-title {
|
||||
color: var(--newtab-link-primary-color); }
|
||||
.ds-list-item:active .ds-list-item-title {
|
||||
|
@ -2241,18 +2326,18 @@ main {
|
|||
.ASRouterButton.secondary:active {
|
||||
background-color: rgba(12, 12, 13, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.1); }
|
||||
[lwt-newtab-brighttext] .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.2); }
|
||||
[lwt-newtab-brighttext] .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
|
||||
[lwt-newtab-brighttext] .footer .secondary {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary {
|
||||
background-color: rgba(249, 249, 250, 0.3); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:hover {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:hover {
|
||||
background-color: rgba(249, 249, 250, 0.4); }
|
||||
[lwt-newtab-brighttext] .footer .secondary:active {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .footer .secondary:active {
|
||||
background-color: rgba(249, 249, 250, 0.5); }
|
||||
|
||||
.SnippetBaseContainer {
|
||||
|
@ -2274,7 +2359,7 @@ main {
|
|||
color: var(--newtab-link-primary-color); }
|
||||
.SnippetBaseContainer a:hover {
|
||||
text-decoration: underline; }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
[lwt-newtab-brighttext]:not(.force-light-theme) .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer input[type='checkbox'] {
|
||||
margin-inline-start: 0; }
|
||||
|
@ -2581,6 +2666,34 @@ main {
|
|||
.SimpleSnippet .icon {
|
||||
align-self: flex-start; }
|
||||
|
||||
.SimpleSnippet.has-section-header .innerWrapper {
|
||||
flex-wrap: wrap;
|
||||
padding-top: 7px; }
|
||||
|
||||
.SimpleSnippet .innerContentWrapper {
|
||||
align-items: center;
|
||||
display: flex; }
|
||||
|
||||
.SimpleSnippet .section-header {
|
||||
flex: 0 0 100%;
|
||||
margin-bottom: 10px; }
|
||||
|
||||
.SimpleSnippet .section-title {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
display: inline-block;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 0; }
|
||||
.SimpleSnippet .section-title a {
|
||||
color: var(--newtab-section-header-text-color);
|
||||
font-weight: inherit;
|
||||
text-decoration: none; }
|
||||
.SimpleSnippet .section-title .icon {
|
||||
height: 16px;
|
||||
margin-inline-end: 6px;
|
||||
margin-top: -2px;
|
||||
width: 16px; }
|
||||
|
||||
.SubmitFormSnippet {
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1948,7 +1948,7 @@ module.exports = {"title":"EOYSnippet","description":"Fundraising Snippet","vers
|
|||
/* 19 */
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = {"title":"SimpleSnippet","description":"A simple template with an icon, text, and optional button.","version":"1.1.1","type":"object","definitions":{"plainText":{"description":"Plain text (no HTML allowed)","type":"string"},"richText":{"description":"Text with HTML subset allowed: i, b, u, strong, em, br","type":"string"},"link_url":{"description":"Target for links or buttons","type":"string","format":"uri"}},"properties":{"title":{"allOf":[{"$ref":"#/definitions/plainText"},{"description":"Snippet title displayed before snippet text"}]},"text":{"allOf":[{"$ref":"#/definitions/richText"},{"description":"Main body text of snippet. HTML subset allowed: i, b, u, strong, em, br"}]},"icon":{"type":"string","description":"Snippet icon. 64x64px. SVG or PNG preferred."},"title_icon":{"type":"string","description":"Small icon that shows up before the title / text. 16x16px. SVG or PNG preferred. Grayscale."},"button_action":{"type":"string","description":"The type of action the button should trigger."},"button_url":{"allOf":[{"$ref":"#/definitions/link_url"},{"description":"A url, button_label links to this"}]},"button_action_args":{"type":"string","description":"Additional parameters for button action, example which specific menu the button should open"},"button_label":{"allOf":[{"$ref":"#/definitions/plainText"},{"description":"Text for a button next to main snippet text that links to button_url. Requires button_url."}]},"button_color":{"type":"string","description":"The text color of the button. Valid CSS color."},"button_background_color":{"type":"string","description":"The background color of the button. Valid CSS color."},"block_button_text":{"type":"string","description":"Tooltip text used for dismiss button.","default":"Remove this"},"tall":{"type":"boolean","description":"To be used by fundraising only, increases height to roughly 120px. Defaults to false."},"do_not_autoblock":{"type":"boolean","description":"Used to prevent blocking the snippet after the CTA (link or button) has been clicked"},"links":{"additionalProperties":{"url":{"allOf":[{"$ref":"#/definitions/link_url"},{"description":"The url where the link points to."}]},"metric":{"type":"string","description":"Custom event name sent with telemetry event."},"args":{"type":"string","description":"Additional parameters for link action, example which specific menu the button should open"}}}},"additionalProperties":false,"required":["text"],"dependencies":{"button_action":["button_label"],"button_url":["button_label"],"button_color":["button_label"],"button_background_color":["button_label"]}};
|
||||
module.exports = {"title":"SimpleSnippet","description":"A simple template with an icon, text, and optional button.","version":"1.1.1","type":"object","definitions":{"plainText":{"description":"Plain text (no HTML allowed)","type":"string"},"richText":{"description":"Text with HTML subset allowed: i, b, u, strong, em, br","type":"string"},"link_url":{"description":"Target for links or buttons","type":"string","format":"uri"}},"properties":{"title":{"allOf":[{"$ref":"#/definitions/plainText"},{"description":"Snippet title displayed before snippet text"}]},"text":{"allOf":[{"$ref":"#/definitions/richText"},{"description":"Main body text of snippet. HTML subset allowed: i, b, u, strong, em, br"}]},"icon":{"type":"string","description":"Snippet icon. 64x64px. SVG or PNG preferred."},"title_icon":{"type":"string","description":"Small icon that shows up before the title / text. 16x16px. SVG or PNG preferred. Grayscale."},"button_action":{"type":"string","description":"The type of action the button should trigger."},"button_url":{"allOf":[{"$ref":"#/definitions/link_url"},{"description":"A url, button_label links to this"}]},"button_action_args":{"type":"string","description":"Additional parameters for button action, example which specific menu the button should open"},"button_label":{"allOf":[{"$ref":"#/definitions/plainText"},{"description":"Text for a button next to main snippet text that links to button_url. Requires button_url."}]},"button_color":{"type":"string","description":"The text color of the button. Valid CSS color."},"button_background_color":{"type":"string","description":"The background color of the button. Valid CSS color."},"block_button_text":{"type":"string","description":"Tooltip text used for dismiss button.","default":"Remove this"},"tall":{"type":"boolean","description":"To be used by fundraising only, increases height to roughly 120px. Defaults to false."},"do_not_autoblock":{"type":"boolean","description":"Used to prevent blocking the snippet after the CTA (link or button) has been clicked"},"links":{"additionalProperties":{"url":{"allOf":[{"$ref":"#/definitions/link_url"},{"description":"The url where the link points to."}]},"metric":{"type":"string","description":"Custom event name sent with telemetry event."},"args":{"type":"string","description":"Additional parameters for link action, example which specific menu the button should open"}}},"section_title_icon":{"type":"string","description":"Section title icon. 16x16px. SVG or PNG preferred. section_title_text must also be specified to display."},"section_title_text":{"type":"string","description":"Section title text. section_title_icon must also be specified to display."},"section_title_url":{"allOf":[{"$ref":"#/definitions/link_url"},{"description":"A url, section_title_text links to this"}]}},"additionalProperties":false,"required":["text"],"dependencies":{"button_action":["button_label"],"button_url":["button_label"],"button_color":["button_label"],"button_background_color":["button_label"],"section_title_url":["section_title_text"]}};
|
||||
|
||||
/***/ }),
|
||||
/* 20 */
|
||||
|
@ -2372,6 +2372,15 @@ class BaseContent extends react__WEBPACK_IMPORTED_MODULE_9___default.a.PureCompo
|
|||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({ event: "OPEN_NEWTAB_PREFS" }));
|
||||
}
|
||||
|
||||
disableDarkTheme() {
|
||||
// Dark themes are not supported in discovery stream view
|
||||
// Add force-light-theme class to body tag to disable dark mode. See Bug 1519764
|
||||
const bodyClassNames = global.document.body.classList;
|
||||
if (!bodyClassNames.contains("force-light-theme")) {
|
||||
bodyClassNames.add("force-light-theme");
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { App } = props;
|
||||
|
@ -2383,6 +2392,10 @@ class BaseContent extends react__WEBPACK_IMPORTED_MODULE_9___default.a.PureCompo
|
|||
const isDiscoveryStream = props.DiscoveryStream.config && props.DiscoveryStream.config.enabled;
|
||||
const searchHandoffEnabled = prefs["improvesearch.handoffToAwesomebar"];
|
||||
|
||||
if (isDiscoveryStream) {
|
||||
this.disableDarkTheme();
|
||||
}
|
||||
|
||||
const outerClassName = ["outer-wrapper", shouldBeFixedToTop && "fixed-to-top", prefs.showSearch && this.state.fixedSearch && !noSectionsEnabled && "fixed-search", prefs.showSearch && noSectionsEnabled && "only-search"].filter(v => v).join(" ");
|
||||
|
||||
return react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(
|
||||
|
@ -2411,7 +2424,11 @@ class BaseContent extends react__WEBPACK_IMPORTED_MODULE_9___default.a.PureCompo
|
|||
{ className: "non-collapsible-section" },
|
||||
react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_ManualMigration_ManualMigration__WEBPACK_IMPORTED_MODULE_7__["ManualMigration"], null)
|
||||
),
|
||||
isDiscoveryStream ? react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_DiscoveryStreamBase_DiscoveryStreamBase__WEBPACK_IMPORTED_MODULE_5__["DiscoveryStreamBase"], null) : react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_Sections_Sections__WEBPACK_IMPORTED_MODULE_11__["Sections"], null),
|
||||
isDiscoveryStream ? react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(
|
||||
content_src_components_ErrorBoundary_ErrorBoundary__WEBPACK_IMPORTED_MODULE_6__["ErrorBoundary"],
|
||||
{ className: "borderless-error" },
|
||||
react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_DiscoveryStreamBase_DiscoveryStreamBase__WEBPACK_IMPORTED_MODULE_5__["DiscoveryStreamBase"], null)
|
||||
) : react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_Sections_Sections__WEBPACK_IMPORTED_MODULE_11__["Sections"], null),
|
||||
react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(PrefsButton, { onClick: this.openPreferences })
|
||||
),
|
||||
react__WEBPACK_IMPORTED_MODULE_9___default.a.createElement(content_src_components_ConfirmDialog_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__["ConfirmDialog"], null)
|
||||
|
@ -6410,7 +6427,7 @@ class _Search extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureComponent
|
|||
{ className: "fake-textbox" },
|
||||
this.props.intl.formatMessage({ id: "search_web_placeholder" })
|
||||
),
|
||||
react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", { className: "fake-editable", tabIndex: "-1", "aria-hidden": "true", contentEditable: "", onDrop: this.onSearchHandoffDrop, onPaste: this.onSearchHandoffPaste }),
|
||||
react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("input", { type: "search", className: "fake-editable", tabIndex: "-1", "aria-hidden": "true", onDrop: this.onSearchHandoffDrop, onPaste: this.onSearchHandoffPaste }),
|
||||
react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", { className: "fake-caret" })
|
||||
),
|
||||
react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("input", {
|
||||
|
@ -7056,7 +7073,7 @@ class DSCard_DSCard extends external_React_default.a.PureComponent {
|
|||
{ className: "title" },
|
||||
this.props.title
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
this.props.excerpt && external_React_default.a.createElement(
|
||||
"p",
|
||||
{ className: "excerpt" },
|
||||
this.props.excerpt
|
||||
|
@ -7132,127 +7149,10 @@ CardGrid_CardGrid.defaultProps = {
|
|||
// EXTERNAL MODULE: external "ReactRedux"
|
||||
var external_ReactRedux_ = __webpack_require__(24);
|
||||
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/Hero/Hero.jsx
|
||||
|
||||
|
||||
|
||||
|
||||
class Hero_Hero extends external_React_default.a.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
if (this.props.dispatch) {
|
||||
this.props.dispatch(Actions["actionCreators"].UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: 0
|
||||
}));
|
||||
|
||||
this.props.dispatch(Actions["actionCreators"].ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{ id: this.heroRec.id, pos: 0 }]
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!data || !data.recommendations) {
|
||||
return external_React_default.a.createElement("div", null);
|
||||
}
|
||||
|
||||
let [heroRec, ...otherRecs] = data.recommendations.slice(0, this.props.items);
|
||||
this.heroRec = heroRec;
|
||||
let truncateText = (text, cap) => `${text.substring(0, cap)}${text.length > cap ? `...` : ``}`;
|
||||
|
||||
// Note that `{index + 1}` is necessary below for telemetry since we treat heroRec as index 0.
|
||||
let cards = otherRecs.map((rec, index) => external_React_default.a.createElement(DSCard_DSCard, {
|
||||
key: `dscard-${index}`,
|
||||
image_src: rec.image_src,
|
||||
title: truncateText(rec.title, 44),
|
||||
url: rec.url,
|
||||
id: rec.id,
|
||||
index: index + 1,
|
||||
type: this.props.type,
|
||||
dispatch: this.props.dispatch,
|
||||
context: truncateText(rec.context || "", 22),
|
||||
source: truncateText(`TODO: SOURCE`, 22) }));
|
||||
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "ds-header" },
|
||||
this.props.title
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: `ds-hero ds-hero-${this.props.border}` },
|
||||
external_React_default.a.createElement(
|
||||
"a",
|
||||
{ href: heroRec.url, className: "wrapper", onClick: this.onLinkClick },
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "img-wrapper" },
|
||||
external_React_default.a.createElement("div", { className: "img", style: { backgroundImage: `url(${heroRec.image_src})` } })
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "meta" },
|
||||
external_React_default.a.createElement(
|
||||
"header",
|
||||
null,
|
||||
truncateText(heroRec.title, 28)
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"p",
|
||||
null,
|
||||
truncateText(heroRec.excerpt, 114)
|
||||
),
|
||||
heroRec.context ? external_React_default.a.createElement(
|
||||
"p",
|
||||
{ className: "context" },
|
||||
truncateText(heroRec.context, 22)
|
||||
) : external_React_default.a.createElement(
|
||||
"p",
|
||||
null,
|
||||
truncateText(`TODO: SOURCE`, 22)
|
||||
)
|
||||
)
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "cards" },
|
||||
cards
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
// CONCATENATED MODULE: ./content-src/lib/truncate-text.js
|
||||
function truncateText(text = "", cap) {
|
||||
return text.substring(0, cap).trim() + (text.length > cap ? "…" : "");
|
||||
}
|
||||
|
||||
Hero_Hero.defaultProps = {
|
||||
data: {},
|
||||
border: `border`,
|
||||
items: 1 // Number of stories to display
|
||||
};
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule.jsx
|
||||
|
||||
|
||||
class HorizontalRule_HorizontalRule extends external_React_default.a.PureComponent {
|
||||
render() {
|
||||
return external_React_default.a.createElement("hr", { className: "ds-hr" });
|
||||
}
|
||||
}
|
||||
// EXTERNAL MODULE: ./content-src/components/DiscoveryStreamImpressionStats/ImpressionStats.jsx
|
||||
var ImpressionStats = __webpack_require__(29);
|
||||
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/List/List.jsx
|
||||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
||||
|
||||
|
@ -7260,6 +7160,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
|
|||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @note exported for testing only
|
||||
*/
|
||||
|
@ -7306,6 +7207,11 @@ class List_ListItem extends external_React_default.a.PureComponent {
|
|||
this.props.title
|
||||
)
|
||||
),
|
||||
this.props.excerpt && external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "ds-list-item-excerpt" },
|
||||
truncateText(this.props.excerpt, 90)
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "ds-list-item-info" },
|
||||
|
@ -7330,9 +7236,9 @@ function _List(props) {
|
|||
|
||||
const recs = feed.data.recommendations;
|
||||
|
||||
let recMarkup = recs.slice(0, props.items).map((rec, index) => external_React_default.a.createElement(List_ListItem, _extends({}, rec, { key: `ds-list-item-${index}`, index: index, type: props.type, dispatch: props.dispatch })));
|
||||
let recMarkup = recs.slice(props.recStartingPoint, props.items).map((rec, index) => external_React_default.a.createElement(List_ListItem, _extends({}, rec, { key: `ds-list-item-${index}`, index: index, type: props.type, dispatch: props.dispatch })));
|
||||
|
||||
const listStyles = ["ds-list", props.hasImages ? "ds-list-images" : "", props.hasNumbers ? "ds-list-numbers" : ""];
|
||||
const listStyles = ["ds-list", props.fullWidth ? "ds-list-full-width" : "", props.hasBorders ? "ds-list-borders" : "", props.hasImages ? "ds-list-images" : "", props.hasNumbers ? "ds-list-numbers" : ""];
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
|
@ -7341,7 +7247,6 @@ function _List(props) {
|
|||
{ className: "ds-header" },
|
||||
props.header.title
|
||||
) : null,
|
||||
external_React_default.a.createElement("hr", { className: "ds-list-border" }),
|
||||
external_React_default.a.createElement(
|
||||
"ul",
|
||||
{ className: listStyles.join(" ") },
|
||||
|
@ -7351,12 +7256,145 @@ function _List(props) {
|
|||
}
|
||||
|
||||
_List.defaultProps = {
|
||||
recStartingPoint: 0, // Index of recommendations to start displaying from
|
||||
fullWidth: false, // Display items taking up the whole column
|
||||
hasBorders: false, // Display lines separating each item
|
||||
hasImages: false, // Display images for each item
|
||||
hasNumbers: false, // Display numbers for each item
|
||||
items: 6 // Number of stories to display. TODO: get from endpoint
|
||||
};
|
||||
|
||||
const List = Object(external_ReactRedux_["connect"])(state => ({ DiscoveryStream: state.DiscoveryStream }))(_List);
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/Hero/Hero.jsx
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Hero_Hero extends external_React_default.a.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
if (this.props.dispatch) {
|
||||
this.props.dispatch(Actions["actionCreators"].UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: 0
|
||||
}));
|
||||
|
||||
this.props.dispatch(Actions["actionCreators"].ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{ id: this.heroRec.id, pos: 0 }]
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { data } = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!data || !data.recommendations) {
|
||||
return external_React_default.a.createElement("div", null);
|
||||
}
|
||||
|
||||
let [heroRec, ...otherRecs] = data.recommendations.slice(0, this.props.items);
|
||||
this.heroRec = heroRec;
|
||||
|
||||
// Note that `{index + 1}` is necessary below for telemetry since we treat heroRec as index 0.
|
||||
let cards = otherRecs.map((rec, index) => external_React_default.a.createElement(DSCard_DSCard, {
|
||||
key: `dscard-${index}`,
|
||||
image_src: rec.image_src,
|
||||
title: truncateText(rec.title, 44),
|
||||
url: rec.url,
|
||||
id: rec.id,
|
||||
index: index + 1,
|
||||
type: this.props.type,
|
||||
dispatch: this.props.dispatch,
|
||||
context: truncateText(rec.context, 22),
|
||||
source: truncateText(rec.domain, 22) }));
|
||||
|
||||
let list = external_React_default.a.createElement(List, {
|
||||
recStartingPoint: 1,
|
||||
feed: this.props.feed,
|
||||
hasImages: true,
|
||||
hasBorders: this.props.border === `border`,
|
||||
items: this.props.items,
|
||||
type: `Hero` });
|
||||
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "ds-header" },
|
||||
this.props.title
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: `ds-hero ds-hero-${this.props.border}` },
|
||||
external_React_default.a.createElement(
|
||||
"a",
|
||||
{ href: heroRec.url, className: "wrapper", onClick: this.onLinkClick },
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "img-wrapper" },
|
||||
external_React_default.a.createElement("div", { className: "img", style: { backgroundImage: `url(${heroRec.image_src})` } })
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "meta" },
|
||||
external_React_default.a.createElement(
|
||||
"header",
|
||||
null,
|
||||
truncateText(heroRec.title, 28)
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"p",
|
||||
null,
|
||||
truncateText(heroRec.excerpt, 114)
|
||||
),
|
||||
heroRec.context ? external_React_default.a.createElement(
|
||||
"p",
|
||||
{ className: "context" },
|
||||
truncateText(heroRec.context, 22)
|
||||
) : external_React_default.a.createElement(
|
||||
"p",
|
||||
null,
|
||||
truncateText(heroRec.domain, 22)
|
||||
)
|
||||
)
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: `${this.props.subComponentType}` },
|
||||
this.props.subComponentType === `cards` ? cards : list
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Hero_Hero.defaultProps = {
|
||||
data: {},
|
||||
border: `border`,
|
||||
items: 1 // Number of stories to display
|
||||
};
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule.jsx
|
||||
|
||||
|
||||
class HorizontalRule_HorizontalRule extends external_React_default.a.PureComponent {
|
||||
render() {
|
||||
return external_React_default.a.createElement("hr", { className: "ds-hr" });
|
||||
}
|
||||
}
|
||||
// EXTERNAL MODULE: ./content-src/components/DiscoveryStreamImpressionStats/ImpressionStats.jsx
|
||||
var ImpressionStats = __webpack_require__(29);
|
||||
|
||||
// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/Navigation/Navigation.jsx
|
||||
|
||||
|
||||
|
@ -7725,7 +7763,7 @@ class DiscoveryStreamBase_DiscoveryStreamBase extends external_React_default.a.P
|
|||
});
|
||||
}
|
||||
|
||||
renderComponent(component) {
|
||||
renderComponent(component, embedWidth) {
|
||||
let rows;
|
||||
const { spocs } = this.props.DiscoveryStream;
|
||||
|
||||
|
@ -7766,6 +7804,8 @@ class DiscoveryStreamBase_DiscoveryStreamBase extends external_React_default.a.P
|
|||
ImpressionStats["ImpressionStats"],
|
||||
{ rows: rows, dispatch: this.props.dispatch, source: component.type },
|
||||
external_React_default.a.createElement(Hero_Hero, {
|
||||
subComponentType: embedWidth >= 9 ? `cards` : `list`,
|
||||
feed: component.feed,
|
||||
title: component.header && component.header.title,
|
||||
data: component.data,
|
||||
border: component.properties.border,
|
||||
|
@ -7782,6 +7822,8 @@ class DiscoveryStreamBase_DiscoveryStreamBase extends external_React_default.a.P
|
|||
{ rows: rows, dispatch: this.props.dispatch, source: component.type },
|
||||
external_React_default.a.createElement(List, {
|
||||
feed: component.feed,
|
||||
fullWidth: component.properties.full_width,
|
||||
hasBorders: component.properties.border === "border",
|
||||
hasImages: component.properties.has_images,
|
||||
hasNumbers: component.properties.has_numbers,
|
||||
items: component.properties.items,
|
||||
|
@ -7821,7 +7863,7 @@ class DiscoveryStreamBase_DiscoveryStreamBase extends external_React_default.a.P
|
|||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
{ key: `component-${componentIndex}` },
|
||||
this.renderComponent(component)
|
||||
this.renderComponent(component, row.width)
|
||||
);
|
||||
})
|
||||
)
|
||||
|
@ -7881,6 +7923,9 @@ const Button = props => {
|
|||
props.children
|
||||
);
|
||||
};
|
||||
// CONCATENATED MODULE: ./content-src/asrouter/components/ConditionalWrapper/ConditionalWrapper.jsx
|
||||
// lifted from https://gist.github.com/kitze/23d82bb9eb0baabfd03a6a720b1d637f
|
||||
const ConditionalWrapper = ({ condition, wrap, children }) => condition ? wrap(children) : children;
|
||||
// EXTERNAL MODULE: ./content-src/asrouter/components/RichText/RichText.jsx
|
||||
var RichText = __webpack_require__(16);
|
||||
|
||||
|
@ -7966,6 +8011,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
|
|||
|
||||
|
||||
|
||||
|
||||
const DEFAULT_ICON_PATH = "chrome://branding/content/icon64.png";
|
||||
|
||||
class SimpleSnippet_SimpleSnippet extends external_React_default.a.PureComponent {
|
||||
|
@ -8035,35 +8081,95 @@ class SimpleSnippet_SimpleSnippet extends external_React_default.a.PureComponent
|
|||
sendClick: props.sendClick });
|
||||
}
|
||||
|
||||
wrapSectionHeader(url) {
|
||||
return function (children) {
|
||||
return external_React_default.a.createElement(
|
||||
"a",
|
||||
{ href: url },
|
||||
children
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
wrapSnippetContent(children) {
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "innerContentWrapper" },
|
||||
children
|
||||
);
|
||||
}
|
||||
|
||||
renderSectionHeader() {
|
||||
const { props } = this;
|
||||
|
||||
// an icon and text must be specified to render the section header
|
||||
if (props.content.section_title_icon && props.content.section_title_text) {
|
||||
const sectionTitleIcon = Object(template_utils["safeURI"])(props.content.section_title_icon);
|
||||
const sectionTitleURL = props.content.section_title_url;
|
||||
|
||||
return external_React_default.a.createElement(
|
||||
"div",
|
||||
{ className: "section-header" },
|
||||
external_React_default.a.createElement(
|
||||
"h3",
|
||||
{ className: "section-title" },
|
||||
external_React_default.a.createElement(
|
||||
ConditionalWrapper,
|
||||
{ condition: sectionTitleURL, wrap: this.wrapSectionHeader(sectionTitleURL) },
|
||||
external_React_default.a.createElement("span", { className: "icon icon-small-spacer", style: { backgroundImage: `url("${sectionTitleIcon}")` } }),
|
||||
external_React_default.a.createElement(
|
||||
"span",
|
||||
{ className: "section-title-text" },
|
||||
props.content.section_title_text
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const sectionHeader = this.renderSectionHeader();
|
||||
let className = "SimpleSnippet";
|
||||
|
||||
if (props.className) {
|
||||
className += ` ${props.className}`;
|
||||
}
|
||||
if (props.content.tall) {
|
||||
className += " tall";
|
||||
}
|
||||
if (sectionHeader) {
|
||||
className += " has-section-header";
|
||||
}
|
||||
|
||||
return external_React_default.a.createElement(
|
||||
SnippetBase_SnippetBase,
|
||||
_extends({}, props, { className: className, textStyle: this.props.textStyle }),
|
||||
external_React_default.a.createElement("img", { src: Object(template_utils["safeURI"])(props.content.icon) || DEFAULT_ICON_PATH, className: "icon" }),
|
||||
sectionHeader,
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
this.renderTitle(),
|
||||
" ",
|
||||
ConditionalWrapper,
|
||||
{ condition: sectionHeader, wrap: this.wrapSnippetContent },
|
||||
external_React_default.a.createElement("img", { src: Object(template_utils["safeURI"])(props.content.icon) || DEFAULT_ICON_PATH, className: "icon" }),
|
||||
external_React_default.a.createElement(
|
||||
"p",
|
||||
{ className: "body" },
|
||||
this.renderText()
|
||||
"div",
|
||||
null,
|
||||
this.renderTitle(),
|
||||
" ",
|
||||
external_React_default.a.createElement(
|
||||
"p",
|
||||
{ className: "body" },
|
||||
this.renderText()
|
||||
),
|
||||
this.props.extraContent
|
||||
),
|
||||
this.props.extraContent
|
||||
),
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
this.renderButton()
|
||||
external_React_default.a.createElement(
|
||||
"div",
|
||||
null,
|
||||
this.renderButton()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -183,7 +183,7 @@ const PREFS_CONFIG = new Map([
|
|||
} else {
|
||||
searchShortcuts.push("google");
|
||||
}
|
||||
if (["AT", "DE", "FR", "GB", "IT", "JP", "US"].includes(geo)) {
|
||||
if (["DE", "FR", "GB", "IT", "JP", "US"].includes(geo)) {
|
||||
searchShortcuts.push("amazon");
|
||||
}
|
||||
return searchShortcuts.join(",");
|
||||
|
@ -217,6 +217,7 @@ const PREFS_CONFIG = new Map([
|
|||
title: "Configuration for the new pocket new tab",
|
||||
value: JSON.stringify({
|
||||
enabled: false,
|
||||
show_spocs: true,
|
||||
// This is currently an exmple layout used for dev purposes.
|
||||
layout_endpoint: "https://getpocket.com/v3/newtab/layout?version=1&consumer_key=40249-e88c401e1b1f2242d9e441c4&layout_variant=basic",
|
||||
}),
|
||||
|
|
|
@ -42,6 +42,12 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
return this._prefCache.config;
|
||||
}
|
||||
|
||||
get showSpocs() {
|
||||
// showSponsored is generally a use set spoc opt out,
|
||||
// show_spocs is generally a mozilla set value.
|
||||
return this.store.getState().Prefs.values.showSponsored && this.config.show_spocs;
|
||||
}
|
||||
|
||||
setupPrefs() {
|
||||
Services.prefs.addObserver(CONFIG_PREF_NAME, this);
|
||||
// Send the initial state of the pref on our reducer
|
||||
|
@ -157,31 +163,40 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
|
||||
async loadSpocs() {
|
||||
const cachedData = await this.cache.get() || {};
|
||||
let {spocs} = cachedData;
|
||||
if (!spocs || !(Date.now() - spocs.lastUpdated < SPOCS_FEEDS_UPDATE_TIME)) {
|
||||
const spocsResponse = await this.fetchSpocs();
|
||||
if (spocsResponse) {
|
||||
spocs = {
|
||||
lastUpdated: Date.now(),
|
||||
data: spocsResponse,
|
||||
};
|
||||
await this.cache.set("spocs", spocs);
|
||||
} else {
|
||||
Cu.reportError("No response for spocs_endpoint prop");
|
||||
// Use old data if we have it, otherwise nothing.
|
||||
spocs = spocs || {};
|
||||
let spocs;
|
||||
|
||||
if (this.showSpocs) {
|
||||
spocs = cachedData.spocs;
|
||||
if (!spocs || !(Date.now() - spocs.lastUpdated < SPOCS_FEEDS_UPDATE_TIME)) {
|
||||
const spocsResponse = await this.fetchSpocs();
|
||||
if (spocsResponse) {
|
||||
spocs = {
|
||||
lastUpdated: Date.now(),
|
||||
data: spocsResponse,
|
||||
};
|
||||
await this.cache.set("spocs", spocs);
|
||||
} else {
|
||||
Cu.reportError("No response for spocs_endpoint prop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spocs) {
|
||||
this.store.dispatch(ac.BroadcastToContent({
|
||||
type: at.DISCOVERY_STREAM_SPOCS_UPDATE,
|
||||
data: {
|
||||
lastUpdated: spocs.lastUpdated,
|
||||
spocs: spocs.data,
|
||||
},
|
||||
}));
|
||||
}
|
||||
// Use good data if we have it, otherwise nothing.
|
||||
// We can have no data if spocs set to off.
|
||||
// We can have no data if request fails and there is no good cache.
|
||||
// We want to send an update spocs or not, so client can render something.
|
||||
spocs = spocs || {
|
||||
lastUpdated: Date.now(),
|
||||
data: {},
|
||||
};
|
||||
|
||||
this.store.dispatch(ac.BroadcastToContent({
|
||||
type: at.DISCOVERY_STREAM_SPOCS_UPDATE,
|
||||
data: {
|
||||
lastUpdated: spocs.lastUpdated,
|
||||
spocs: spocs.data,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
async getComponentFeed(feedUrl) {
|
||||
|
@ -275,6 +290,12 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
|
|||
// When this feed is shutting down:
|
||||
this.uninitPrefs();
|
||||
break;
|
||||
case at.PREF_CHANGED:
|
||||
// Check if spocs was disabled. Remove them if they were.
|
||||
if (action.data.name === "showSponsored") {
|
||||
await this.loadSpocs();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -219,6 +219,34 @@ const MESSAGES = () => ([
|
|||
"test": "takeover",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "SIMPLE_TEST_WITH_SECTION_HEADING",
|
||||
"template": "simple_snippet",
|
||||
"content": {
|
||||
"button_label": "Get one now!",
|
||||
"button_url": "https://www.mozilla.org/en-US/firefox/accounts",
|
||||
"icon": TEST_ICON,
|
||||
"title": "Firefox Account!",
|
||||
"text": "<syncLink>Sync it, link it, take it with you</syncLink>. All this and more with a Firefox Account.",
|
||||
"links": {"syncLink": {"url": "https://www.mozilla.org/en-US/firefox/accounts"}},
|
||||
"block_button_text": "Block",
|
||||
"section_title_icon": "resource://activity-stream/data/content/assets/glyph-pocket-16.svg",
|
||||
"section_title_text": "Messages from Mozilla",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "SIMPLE_TEST_WITH_SECTION_HEADING_AND_LINK",
|
||||
"template": "simple_snippet",
|
||||
"content": {
|
||||
"icon": TEST_ICON,
|
||||
"title": "Firefox Account!",
|
||||
"text": "Sync it, link it, take it with you. All this and more with a Firefox Account.",
|
||||
"block_button_text": "Block",
|
||||
"section_title_icon": "resource://activity-stream/data/content/assets/glyph-pocket-16.svg",
|
||||
"section_title_text": "Messages from Mozilla (click for info)",
|
||||
"section_title_url": "https://www.mozilla.org/about",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const SnippetsTestMessageProvider = {
|
||||
|
|
|
@ -163,7 +163,7 @@ this.TopSitesFeed = class TopSitesFeed {
|
|||
const shouldPin = this.store.getState().Prefs.values[SEARCH_SHORTCUTS_SEARCH_ENGINES_PREF]
|
||||
.split(",")
|
||||
.map(getSearchProvider)
|
||||
.filter(s => s);
|
||||
.filter(s => s && s.shortURL !== this._currentSearchHostname);
|
||||
|
||||
// If we've previously inserted all search shortcuts return early
|
||||
if (shouldPin.every(shortcut => prevInsertedShortcuts.includes(shortcut.shortURL))) {
|
||||
|
|
|
@ -91,6 +91,11 @@ section_disclaimer_topstories_buttontext=Tamam, başa düşdüm
|
|||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Firefox Ev Məzmunu
|
||||
prefs_home_description=Firefox Evdə hansı məzmunları görmək istədiyinizi seçin.
|
||||
|
||||
prefs_content_discovery_header=Firefox Ev
|
||||
prefs_content_discovery_description=Firefox Evdəki Məzmun Kəşfi yüksək keyfiyyətli və sizə uyğun internet məqalələrini kəşf etməyinizə imkan verir.
|
||||
prefs_content_discovery_button=Məzmun Kəşfini Söndür
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
@ -144,7 +149,6 @@ pocket_read_more=Məşhur Mövzular:
|
|||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Daha çox hekayə gör
|
||||
pocket_more_reccommendations=Daha Çox Tövsiyyələr
|
||||
pocket_learn_more=Ətraflı Öyrən
|
||||
pocket_how_it_works=Bu necə işləyir
|
||||
pocket_cta_button=Pocket əldə edin
|
||||
pocket_cta_text=Sevdiyiniz məqalələri Pocket-də saxlayın və möhtəşəm yeni yazıları kəşf edin.
|
||||
|
|
|
@ -91,6 +91,9 @@ section_disclaimer_topstories_buttontext=Ok, ¡ya caché!
|
|||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Contenido de la página de inicio de Firefox
|
||||
prefs_home_description=Elige qué contenido quieres en tu pantalla de inicio de Firefox.
|
||||
|
||||
prefs_content_discovery_header=Inicio de Firefox
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
|
|
@ -93,6 +93,7 @@ prefs_home_header=Contenu de la page d’accueil de Firefox
|
|||
prefs_home_description=Choisissez le contenu que vous souhaitez pour la page d’accueil de Firefox.
|
||||
|
||||
prefs_content_discovery_header=Page d’accueil de Firefox
|
||||
prefs_content_discovery_button=Désactiver la découverte de contenu
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
|
|
|
@ -91,6 +91,9 @@ section_disclaimer_topstories_buttontext=Oĩma, hesakãma chéve
|
|||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Kuatiarogue retepy Firefox ñepyrũháme
|
||||
prefs_home_description=Eiporavo mba’e retepýpa eipota Firefox mba’erechaha ñepyrũháme.
|
||||
|
||||
prefs_content_discovery_header=Firefox kuatiarogue ñepyrũ
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
@ -144,7 +147,6 @@ pocket_read_more=Ñe'ẽmbyrã Ojehayhuvéva:
|
|||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Ahechaseve Mombe'upy
|
||||
pocket_more_reccommendations=Hetave je’eporã
|
||||
pocket_learn_more=Kuaave
|
||||
pocket_how_it_works=Mba’éichapa omba’apo
|
||||
pocket_cta_button=Eguereko Pocket
|
||||
pocket_cta_text=Eñongatu umi eipotáva tembiasakue Pocket-pe ha emombarete ne akã ñemoñe’ẽ ha’evévape.
|
||||
|
|
|
@ -22,7 +22,7 @@ type_label_visited=Đã truy cập
|
|||
type_label_bookmarked=Đã được đánh dấu
|
||||
type_label_recommended=Xu hướng
|
||||
type_label_pocket=Đã lưu vào Pocket
|
||||
type_label_downloaded=Đã tải về
|
||||
type_label_downloaded=Đã tải xuống
|
||||
|
||||
# LOCALIZATION NOTE (menu_action_*): These strings are displayed in a context
|
||||
# menu and are meant as a call to action for a given page.
|
||||
|
@ -91,6 +91,11 @@ section_disclaimer_topstories_buttontext=Ok, đã hiểu
|
|||
# what is shown for the homepage, new windows, and new tabs.
|
||||
prefs_home_header=Nội dung trang chủ của Firefox
|
||||
prefs_home_description=Chọn nội dung mà bạn muốn thêm vào trang chủ của Firefox.
|
||||
|
||||
prefs_content_discovery_header=Trang chủ Firefox
|
||||
prefs_content_discovery_description=Khám phá nội dung trong trang chủ Firefox cho phép bạn khám phá các bài viết chất lượng cao, có liên quan trên web.
|
||||
prefs_content_discovery_button=Tắt khám phá nội dung
|
||||
|
||||
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
|
||||
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
|
|
|
@ -40,9 +40,9 @@ window.gActivityStreamStrings = {
|
|||
"section_disclaimer_topstories_buttontext": "Tamam, başa düşdüm",
|
||||
"prefs_home_header": "Firefox Ev Məzmunu",
|
||||
"prefs_home_description": "Firefox Evdə hansı məzmunları görmək istədiyinizi seçin.",
|
||||
"prefs_content_discovery_header": "Firefox Home",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_content_discovery_header": "Firefox Ev",
|
||||
"prefs_content_discovery_description": "Firefox Evdəki Məzmun Kəşfi yüksək keyfiyyətli və sizə uyğun internet məqalələrini kəşf etməyinizə imkan verir.",
|
||||
"prefs_content_discovery_button": "Məzmun Kəşfini Söndür",
|
||||
"prefs_section_rows_option": "{num} sətir;{num} sətir",
|
||||
"prefs_search_header": "Web Axtarış",
|
||||
"prefs_topsites_description": "Ən çox ziyarət etdiyiniz saytlar",
|
||||
|
@ -110,6 +110,5 @@ window.gActivityStreamStrings = {
|
|||
"firstrun_privacy_notice": "Məxfilik Bildirişi",
|
||||
"firstrun_continue_to_login": "Davam et",
|
||||
"firstrun_skip_login": "Bu addımı keç",
|
||||
"context_menu_title": "Menyunu aç",
|
||||
"pocket_learn_more": "Ətraflı Öyrən"
|
||||
"context_menu_title": "Menyunu aç"
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ window.gActivityStreamStrings = {
|
|||
"section_disclaimer_topstories_buttontext": "Ok, ¡ya caché!",
|
||||
"prefs_home_header": "Contenido de la página de inicio de Firefox",
|
||||
"prefs_home_description": "Elige qué contenido quieres en tu pantalla de inicio de Firefox.",
|
||||
"prefs_content_discovery_header": "Página de inicio de Firefox",
|
||||
"prefs_content_discovery_header": "Inicio de Firefox",
|
||||
"prefs_content_discovery_description": "Content Discovery en la página de inicio de Firefox le permite descubrir artículos relevantes de alta calidad en toda la web.",
|
||||
"prefs_content_discovery_button": "Desactivar Content Discovery",
|
||||
"prefs_section_rows_option": "{num} fila;{num} filas",
|
||||
|
|
|
@ -42,7 +42,7 @@ window.gActivityStreamStrings = {
|
|||
"prefs_home_description": "Choisissez le contenu que vous souhaitez pour la page d’accueil de Firefox.",
|
||||
"prefs_content_discovery_header": "Page d’accueil de Firefox",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_content_discovery_button": "Désactiver la découverte de contenu",
|
||||
"prefs_section_rows_option": "{num} ligne;{num} lignes",
|
||||
"prefs_search_header": "Recherche web",
|
||||
"prefs_topsites_description": "Les sites que vous visitez le plus",
|
||||
|
|
|
@ -40,7 +40,7 @@ window.gActivityStreamStrings = {
|
|||
"section_disclaimer_topstories_buttontext": "Oĩma, hesakãma chéve",
|
||||
"prefs_home_header": "Kuatiarogue retepy Firefox ñepyrũháme",
|
||||
"prefs_home_description": "Eiporavo mba’e retepýpa eipota Firefox mba’erechaha ñepyrũháme.",
|
||||
"prefs_content_discovery_header": "Firefox Home",
|
||||
"prefs_content_discovery_header": "Firefox kuatiarogue ñepyrũ",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_section_rows_option": "{num} rysýi; {num} rysýi",
|
||||
|
@ -110,6 +110,5 @@ window.gActivityStreamStrings = {
|
|||
"firstrun_privacy_notice": "Ñemigua purureko",
|
||||
"firstrun_continue_to_login": "Eku'ejey",
|
||||
"firstrun_skip_login": "Ehejánte kóva",
|
||||
"context_menu_title": "Eike poravorãme",
|
||||
"pocket_learn_more": "Kuaave"
|
||||
"context_menu_title": "Eike poravorãme"
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ window.gActivityStreamStrings = {
|
|||
"type_label_bookmarked": "Đã được đánh dấu",
|
||||
"type_label_recommended": "Xu hướng",
|
||||
"type_label_pocket": "Đã lưu vào Pocket",
|
||||
"type_label_downloaded": "Đã tải về",
|
||||
"type_label_downloaded": "Đã tải xuống",
|
||||
"menu_action_bookmark": "Đánh dấu",
|
||||
"menu_action_remove_bookmark": "Xóa đánh dấu",
|
||||
"menu_action_open_new_window": "Mở trong cửa sổ mới",
|
||||
|
@ -40,9 +40,9 @@ window.gActivityStreamStrings = {
|
|||
"section_disclaimer_topstories_buttontext": "Ok, đã hiểu",
|
||||
"prefs_home_header": "Nội dung trang chủ của Firefox",
|
||||
"prefs_home_description": "Chọn nội dung mà bạn muốn thêm vào trang chủ của Firefox.",
|
||||
"prefs_content_discovery_header": "Firefox Home",
|
||||
"prefs_content_discovery_description": "Content Discovery in Firefox Home allows you to discover high-quality, relevant articles from across the web.",
|
||||
"prefs_content_discovery_button": "Turn Off Content Discovery",
|
||||
"prefs_content_discovery_header": "Trang chủ Firefox",
|
||||
"prefs_content_discovery_description": "Khám phá nội dung trong trang chủ Firefox cho phép bạn khám phá các bài viết chất lượng cao, có liên quan trên web.",
|
||||
"prefs_content_discovery_button": "Tắt khám phá nội dung",
|
||||
"prefs_section_rows_option": "{num} hàng",
|
||||
"prefs_search_header": "Tìm kiếm web",
|
||||
"prefs_topsites_description": "Những trang bạn truy cập nhiều nhất",
|
||||
|
|
|
@ -58,8 +58,8 @@ test_newtab({
|
|||
before: setDefaultTopSites,
|
||||
test: async function searchTopSites_dismiss() {
|
||||
const siteSelector = ".search-shortcut";
|
||||
await ContentTaskUtils.waitForCondition(() => content.document.querySelectorAll(siteSelector).length === 2,
|
||||
"2 search topsites are loaded by default");
|
||||
await ContentTaskUtils.waitForCondition(() => content.document.querySelectorAll(siteSelector).length === 1,
|
||||
"1 search topsites is loaded by default");
|
||||
|
||||
const contextMenuItems = content.openContextMenuAndGetOptions(siteSelector);
|
||||
is(contextMenuItems.length, 2, "Search TopSites should only have Unpin and Dismiss");
|
||||
|
|
|
@ -126,7 +126,7 @@ test_newtab({
|
|||
await ContentTaskUtils.waitForCondition(() => content.document.querySelector(".search-shortcut .title.pinned"), "Wait for pinned search topsites");
|
||||
|
||||
const searchTopSites = content.document.querySelectorAll(".title.pinned");
|
||||
ok(searchTopSites.length >= 2, "There should be at least 2 search topsites");
|
||||
ok(searchTopSites.length >= 1, "There should be at least 2 search topsites");
|
||||
|
||||
searchTopSites[0].click();
|
||||
|
||||
|
|
|
@ -69,6 +69,38 @@ describe("SimpleSnippet", () => {
|
|||
assert.calledOnce(wrapper.props().onAction);
|
||||
assert.calledWithExactly(wrapper.props().onAction, {type: "OPEN_APPLICATIONS_MENU", data: {args: "appMenu"}});
|
||||
});
|
||||
it("should not wrap the main content if a section header is not present", () => {
|
||||
const wrapper = mountAndCheckProps({text: "bar"});
|
||||
assert.lengthOf(wrapper.find(".innerContentWrapper"), 0);
|
||||
});
|
||||
it("should wrap the main content if a section header is present", () => {
|
||||
const wrapper = mountAndCheckProps({
|
||||
section_title_icon: "data:image/gif;base64,R0lGODl",
|
||||
section_title_text: "Messages from Mozilla",
|
||||
});
|
||||
|
||||
assert.lengthOf(wrapper.find(".innerContentWrapper"), 1);
|
||||
});
|
||||
it("should render a section header if text and icon are specified", () => {
|
||||
const wrapper = mountAndCheckProps({
|
||||
section_title_icon: "data:image/gif;base64,R0lGODl",
|
||||
section_title_text: "Messages from Mozilla",
|
||||
});
|
||||
|
||||
assert.equal(wrapper.find(".section-title .icon").prop("style").backgroundImage, 'url("data:image/gif;base64,R0lGODl")');
|
||||
assert.equal(wrapper.find(".section-title-text").text().trim(), "Messages from Mozilla");
|
||||
// ensure there is no <a> when a section_title_url is not specified
|
||||
assert.lengthOf(wrapper.find(".section-title a"), 0);
|
||||
});
|
||||
it("should render a section header wrapped in an <a> tag if a url is provided", () => {
|
||||
const wrapper = mountAndCheckProps({
|
||||
section_title_icon: "data:image/gif;base64,R0lGODl",
|
||||
section_title_text: "Messages from Mozilla",
|
||||
section_title_url: "https://www.mozilla.org",
|
||||
});
|
||||
|
||||
assert.equal(wrapper.find(".section-title a").prop("href"), "https://www.mozilla.org");
|
||||
});
|
||||
it("should send an OPEN_URL action when button_url is defined and button is clicked", () => {
|
||||
const wrapper = mountAndCheckProps({
|
||||
button_label: "Button",
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import {truncateText} from "content-src/lib/truncate-text";
|
||||
|
||||
describe("truncateText", () => {
|
||||
it("should accept nothing", () => {
|
||||
assert.equal(truncateText(), "");
|
||||
});
|
||||
|
||||
it("should give back string with no truncating", () => {
|
||||
const str = "hello";
|
||||
|
||||
assert.equal(truncateText(str), str);
|
||||
});
|
||||
|
||||
it("should give back short string for long cap", () => {
|
||||
const str = "hello";
|
||||
|
||||
assert.equal(truncateText(str, 100), str);
|
||||
});
|
||||
|
||||
it("should give back string for exact cap", () => {
|
||||
const str = "hello";
|
||||
|
||||
assert.equal(truncateText(str, str.length), str);
|
||||
});
|
||||
|
||||
it("should cap off long string with ellipsis", () => {
|
||||
const str = "hello world";
|
||||
|
||||
assert.equal(truncateText(str, 5), "hello…");
|
||||
});
|
||||
|
||||
it("should avoid putting ellipsis after whitespace", () => {
|
||||
const str = "hello world";
|
||||
|
||||
assert.equal(truncateText(str, 10), "hello…");
|
||||
});
|
||||
});
|
|
@ -18,7 +18,7 @@ describe("DiscoveryStreamFeed", () => {
|
|||
sandbox = sinon.createSandbox();
|
||||
configPrefStub = sandbox.stub(global.Services.prefs, "getStringPref")
|
||||
.withArgs(CONFIG_PREF_NAME)
|
||||
.returns(JSON.stringify({enabled: false, layout_endpoint: "foo.com"}));
|
||||
.returns(JSON.stringify({enabled: false, show_spocs: false, layout_endpoint: "foo.com"}));
|
||||
|
||||
// Fetch
|
||||
fetchStub = sandbox.stub(global, "fetch");
|
||||
|
@ -38,11 +38,11 @@ describe("DiscoveryStreamFeed", () => {
|
|||
|
||||
describe("#observe", () => {
|
||||
it("should update state.DiscoveryStream.config when the pref changes", async () => {
|
||||
configPrefStub.returns(JSON.stringify({enabled: true, layout_endpoint: "foo"}));
|
||||
configPrefStub.returns(JSON.stringify({enabled: true, show_spocs: false, layout_endpoint: "foo"}));
|
||||
|
||||
feed.observe(null, null, CONFIG_PREF_NAME);
|
||||
|
||||
assert.deepEqual(feed.store.getState().DiscoveryStream.config, {enabled: true, layout_endpoint: "foo"});
|
||||
assert.deepEqual(feed.store.getState().DiscoveryStream.config, {enabled: true, show_spocs: false, layout_endpoint: "foo"});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -173,6 +173,9 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
describe("#loadSpocs", () => {
|
||||
beforeEach(() => {
|
||||
Object.defineProperty(feed, "showSpocs", {get: () => true});
|
||||
});
|
||||
it("should fetch fresh data if cache is empty", async () => {
|
||||
sandbox.stub(feed.cache, "get").returns(Promise.resolve());
|
||||
sandbox.stub(feed, "fetchSpocs").returns(Promise.resolve("data"));
|
||||
|
@ -210,6 +213,19 @@ describe("DiscoveryStreamFeed", () => {
|
|||
});
|
||||
|
||||
describe("#fetchSpocs", () => {
|
||||
beforeEach(() => {
|
||||
Object.defineProperty(feed, "showSpocs", {get: () => true});
|
||||
});
|
||||
it("should return null for fetchSpocs with no spocs_endpoint", async () => {
|
||||
feed.store.dispatch(ac.BroadcastToContent({
|
||||
type: at.DISCOVERY_STREAM_SPOCS_ENDPOINT,
|
||||
data: "",
|
||||
}));
|
||||
|
||||
const result = await feed.fetchSpocs();
|
||||
|
||||
assert.isNull(result);
|
||||
});
|
||||
it("should return old spocs if fetch failed", async () => {
|
||||
sandbox.stub(feed.cache, "set").returns(Promise.resolve());
|
||||
feed.store.dispatch(ac.BroadcastToContent({
|
||||
|
@ -241,6 +257,37 @@ describe("DiscoveryStreamFeed", () => {
|
|||
assert.equal(feed.store.getState().DiscoveryStream.spocs.data, "new data");
|
||||
});
|
||||
});
|
||||
describe("#showSpocs", () => {
|
||||
it("should return false from showSpocs if user pref showSponsored is false", async () => {
|
||||
feed.store.getState = () => ({
|
||||
Prefs: {values: {showSponsored: false}},
|
||||
});
|
||||
Object.defineProperty(feed, "config", {get: () => ({show_spocs: true})});
|
||||
|
||||
assert.isFalse(feed.showSpocs);
|
||||
});
|
||||
it("should return false from showSpocs if DiscoveryStrea pref show_spocs is false", async () => {
|
||||
feed.store.getState = () => ({
|
||||
Prefs: {values: {showSponsored: true}},
|
||||
});
|
||||
Object.defineProperty(feed, "config", {get: () => ({show_spocs: false})});
|
||||
|
||||
assert.isFalse(feed.showSpocs);
|
||||
});
|
||||
it("should return true from showSpocs if both prefs are true", async () => {
|
||||
feed.store.getState = () => ({
|
||||
Prefs: {values: {showSponsored: true}},
|
||||
});
|
||||
Object.defineProperty(feed, "config", {get: () => ({show_spocs: true})});
|
||||
|
||||
assert.isTrue(feed.showSpocs);
|
||||
});
|
||||
it("should fire loadSpocs is showSponsored pref changes", async () => {
|
||||
sandbox.stub(feed, "loadSpocs").returns(Promise.resolve());
|
||||
await feed.onAction({type: at.PREF_CHANGED, data: {name: "showSponsored"}});
|
||||
assert.calledOnce(feed.loadSpocs);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#clearCache", () => {
|
||||
it("should set .layout, .feeds and .spocs to {}", async () => {
|
||||
|
|
|
@ -1343,6 +1343,12 @@ describe("Top Sites Feed", () => {
|
|||
assert.deepEqual(fakeNewTabUtils.pinnedLinks.links[6], {url: "https://amazon.com", searchTopSite: true, label: "@amazon"});
|
||||
});
|
||||
|
||||
it("should not pin shortcuts for the current default search engine", async () => {
|
||||
feed._currentSearchHostname = "google";
|
||||
await feed._maybeInsertSearchShortcuts(fakeNewTabUtils.pinnedLinks.links);
|
||||
assert.deepEqual(fakeNewTabUtils.pinnedLinks.links[3], {url: "https://amazon.com", searchTopSite: true, label: "@amazon"});
|
||||
});
|
||||
|
||||
it("should only pin the first shortcut if there's only one available slot", async () => {
|
||||
fakeNewTabUtils.pinnedLinks.links[3] = {url: ""};
|
||||
await feed._maybeInsertSearchShortcuts(fakeNewTabUtils.pinnedLinks.links);
|
||||
|
|
|
@ -1369,6 +1369,12 @@ BrowserGlue.prototype = {
|
|||
Services.prefs.addObserver("urlclassifier.trackingTable", this._matchCBCategory);
|
||||
Services.prefs.addObserver("network.cookie.cookieBehavior", this._matchCBCategory);
|
||||
Services.prefs.addObserver(ContentBlockingCategoriesPrefs.PREF_CB_CATEGORY, this._updateCBCategory);
|
||||
Services.prefs.addObserver("media.autoplay.default", this._updateAutoplayPref);
|
||||
},
|
||||
|
||||
_updateAutoplayPref() {
|
||||
let blocked = Services.prefs.getIntPref("media.autoplay.default", 1);
|
||||
Services.telemetry.scalarSet("media.autoplay_default_blocked", blocked);
|
||||
},
|
||||
|
||||
_matchCBCategory() {
|
||||
|
|
|
@ -8,12 +8,8 @@ var EXPORTED_SYMBOLS = ["ContentRestore"];
|
|||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
|
||||
|
||||
ChromeUtils.defineModuleGetter(this, "FormData",
|
||||
"resource://gre/modules/FormData.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "SessionHistory",
|
||||
"resource://gre/modules/sessionstore/SessionHistory.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "SessionStorage",
|
||||
"resource:///modules/sessionstore/SessionStorage.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
|
@ -141,7 +137,7 @@ ContentRestoreInternal.prototype = {
|
|||
|
||||
|
||||
if (tabData.storage && this.docShell instanceof Ci.nsIDocShell) {
|
||||
SessionStorage.restore(this.docShell, tabData.storage);
|
||||
SessionStoreUtils.restoreSessionStorage(this.docShell, tabData.storage);
|
||||
delete tabData.storage;
|
||||
}
|
||||
|
||||
|
@ -303,7 +299,7 @@ ContentRestoreInternal.prototype = {
|
|||
// restore() will return false, and thus abort restoration for the
|
||||
// current |frame| and its descendants, if |data.url| is given but
|
||||
// doesn't match the loaded document's URL.
|
||||
return FormData.restore(frame, data);
|
||||
return SessionStoreUtils.restoreFormData(frame.document, data);
|
||||
});
|
||||
|
||||
// Restore scroll data.
|
||||
|
|
|
@ -18,8 +18,6 @@ ChromeUtils.defineModuleGetter(this, "ContentRestore",
|
|||
"resource:///modules/sessionstore/ContentRestore.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "SessionHistory",
|
||||
"resource://gre/modules/sessionstore/SessionHistory.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "SessionStorage",
|
||||
"resource:///modules/sessionstore/SessionStorage.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Utils",
|
||||
"resource://gre/modules/sessionstore/Utils.jsm");
|
||||
|
||||
|
@ -533,7 +531,10 @@ class SessionStorageListener extends Handler {
|
|||
// messages.
|
||||
this.resetChanges();
|
||||
|
||||
this.messageQueue.push("storage", () => SessionStorage.collect(content));
|
||||
this.messageQueue.push("storage", () => {
|
||||
let data = SessionStoreUtils.collectSessionStorage(content);
|
||||
return Object.keys(data).length ? data : null;
|
||||
});
|
||||
}
|
||||
|
||||
onPageLoadCompleted() {
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["SessionStorage"];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// A bound to the size of data to store for DOM Storage.
|
||||
const DOM_STORAGE_LIMIT_PREF = "browser.sessionstore.dom_storage_limit";
|
||||
|
||||
// Returns the principal for a given |frame| contained in a given |docShell|.
|
||||
function getPrincipalForFrame(docShell, frame) {
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
let uri = frame.document.documentURIObject;
|
||||
return ssm.getDocShellCodebasePrincipal(uri, docShell);
|
||||
}
|
||||
|
||||
var SessionStorage = Object.freeze({
|
||||
/**
|
||||
* Updates all sessionStorage "super cookies"
|
||||
* @param content
|
||||
* A tab's global, i.e. the root frame we want to collect for.
|
||||
* @return Returns a nested object that will have hosts as keys and per-origin
|
||||
* session storage data as strings. For example:
|
||||
* {"https://example.com^userContextId=1": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
collect(content) {
|
||||
return SessionStorageInternal.collect(content);
|
||||
},
|
||||
|
||||
/**
|
||||
* Restores all sessionStorage "super cookies".
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
* @param aStorageData
|
||||
* A nested object with storage data to be restored that has hosts as
|
||||
* keys and per-origin session storage data as strings. For example:
|
||||
* {"https://example.com^userContextId=1": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
restore(aDocShell, aStorageData) {
|
||||
SessionStorageInternal.restore(aDocShell, aStorageData);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Calls the given callback |cb|, passing |frame| and each of its descendants.
|
||||
*/
|
||||
function forEachNonDynamicChildFrame(frame, cb) {
|
||||
// Call for current frame.
|
||||
cb(frame);
|
||||
|
||||
// Call the callback recursively for each descendant.
|
||||
SessionStoreUtils.forEachNonDynamicChildFrame(frame, subframe => {
|
||||
return forEachNonDynamicChildFrame(subframe, cb);
|
||||
});
|
||||
}
|
||||
|
||||
var SessionStorageInternal = {
|
||||
/**
|
||||
* Reads all session storage data from the given docShell.
|
||||
* @param content
|
||||
* A tab's global, i.e. the root frame we want to collect for.
|
||||
* @return Returns a nested object that will have hosts as keys and per-origin
|
||||
* session storage data as strings. For example:
|
||||
* {"https://example.com^userContextId=1": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
collect(content) {
|
||||
let data = {};
|
||||
let visitedOrigins = new Set();
|
||||
let docShell = content.docShell;
|
||||
|
||||
forEachNonDynamicChildFrame(content, frame => {
|
||||
let principal = getPrincipalForFrame(docShell, frame);
|
||||
if (!principal) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the origin of the current history entry
|
||||
// and use that as a key for the per-principal storage data.
|
||||
let origin;
|
||||
try {
|
||||
// The origin getter may throw for about:blank iframes as of bug 1340710,
|
||||
// but we should ignore them anyway.
|
||||
origin = principal.origin;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
if (visitedOrigins.has(origin)) {
|
||||
// Don't read a host twice.
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the current origin as visited.
|
||||
visitedOrigins.add(origin);
|
||||
|
||||
let originData = this._readEntry(principal, docShell);
|
||||
if (Object.keys(originData).length) {
|
||||
data[origin] = originData;
|
||||
}
|
||||
});
|
||||
|
||||
return Object.keys(data).length ? data : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Writes session storage data to the given tab.
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
* @param aStorageData
|
||||
* A nested object with storage data to be restored that has hosts as
|
||||
* keys and per-origin session storage data as strings. For example:
|
||||
* {"https://example.com^userContextId=1": {"key": "value", "my_number": "123"}}
|
||||
*/
|
||||
restore(aDocShell, aStorageData) {
|
||||
for (let origin of Object.keys(aStorageData)) {
|
||||
let data = aStorageData[origin];
|
||||
|
||||
let principal;
|
||||
|
||||
try {
|
||||
// NOTE: In capture() we record the full origin for the URI which the
|
||||
// sessionStorage is being captured for. As of bug 1235657 this code
|
||||
// stopped parsing any origins which have originattributes correctly, as
|
||||
// it decided to use the origin attributes from the docshell, and try to
|
||||
// interpret the origin as a URI. Since bug 1353844 this code now correctly
|
||||
// parses the full origin, and then discards the origin attributes, to
|
||||
// make the behavior line up with the original intentions in bug 1235657
|
||||
// while preserving the ability to read all session storage from
|
||||
// previous versions. In the future, if this behavior is desired, we may
|
||||
// want to use the spec instead of the origin as the key, and avoid
|
||||
// transmitting origin attribute information which we then discard when
|
||||
// restoring.
|
||||
//
|
||||
// If changing this logic, make sure to also change the principal
|
||||
// computation logic in SessionStore::_sendRestoreHistory.
|
||||
let attrs = aDocShell.getOriginAttributes();
|
||||
let dataPrincipal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(origin);
|
||||
principal = Services.scriptSecurityManager.createCodebasePrincipal(dataPrincipal.URI, attrs);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
|
||||
|
||||
// There is no need to pass documentURI, it's only used to fill
|
||||
// documentURI property of domstorage event, which in this case has no
|
||||
// consumer. Prevention of events in case of missing documentURI will be
|
||||
// solved in a followup bug to bug 600307.
|
||||
// Null window because the current window doesn't match the principal yet
|
||||
// and loads about:blank.
|
||||
let storage = storageManager.createStorage(null, principal, "", aDocShell.usePrivateBrowsing);
|
||||
|
||||
for (let key of Object.keys(data)) {
|
||||
try {
|
||||
storage.setItem(key, data[key]);
|
||||
} catch (e) {
|
||||
// throws e.g. for URIs that can't have sessionStorage
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads an entry in the session storage data contained in a tab's history.
|
||||
* @param aURI
|
||||
* That history entry uri
|
||||
* @param aDocShell
|
||||
* A tab's docshell (containing the sessionStorage)
|
||||
*/
|
||||
_readEntry(aPrincipal, aDocShell) {
|
||||
let hostData = {};
|
||||
let storage;
|
||||
|
||||
let window = aDocShell.domWindow;
|
||||
|
||||
try {
|
||||
let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
|
||||
storage = storageManager.getStorage(window, aPrincipal);
|
||||
storage.length; // XXX: Bug 1232955 - storage.length can throw, catch that failure
|
||||
} catch (e) {
|
||||
// sessionStorage might throw if it's turned off, see bug 458954
|
||||
storage = null;
|
||||
}
|
||||
|
||||
if (!storage || !storage.length) {
|
||||
return hostData;
|
||||
}
|
||||
|
||||
// If the DOMSessionStorage contains too much data, ignore it.
|
||||
let usage = window.windowUtils.getStorageUsage(storage);
|
||||
if (usage > Services.prefs.getIntPref(DOM_STORAGE_LIMIT_PREF)) {
|
||||
return hostData;
|
||||
}
|
||||
|
||||
for (let i = 0; i < storage.length; i++) {
|
||||
try {
|
||||
let key = storage.key(i);
|
||||
hostData[key] = storage.getItem(key);
|
||||
} catch (e) {
|
||||
// This currently throws for secured items (cf. bug 442048).
|
||||
}
|
||||
}
|
||||
|
||||
return hostData;
|
||||
},
|
||||
};
|
|
@ -20,7 +20,6 @@ EXTRA_JS_MODULES.sessionstore = [
|
|||
'SessionMigration.jsm',
|
||||
'SessionSaver.jsm',
|
||||
'SessionStartup.jsm',
|
||||
'SessionStorage.jsm',
|
||||
'SessionStore.jsm',
|
||||
'SessionWorker.js',
|
||||
'SessionWorker.jsm',
|
||||
|
|
|
@ -310,7 +310,7 @@ class UrlbarInput {
|
|||
let url = result.payload.url;
|
||||
|
||||
switch (result.type) {
|
||||
case UrlbarUtils.MATCH_TYPE.TAB_SWITCH: {
|
||||
case UrlbarUtils.RESULT_TYPE.TAB_SWITCH: {
|
||||
if (this._overrideDefaultAction(event)) {
|
||||
where = "current";
|
||||
break;
|
||||
|
@ -328,7 +328,7 @@ class UrlbarInput {
|
|||
}
|
||||
return;
|
||||
}
|
||||
case UrlbarUtils.MATCH_TYPE.SEARCH: {
|
||||
case UrlbarUtils.RESULT_TYPE.SEARCH: {
|
||||
url = this._maybeCanonizeURL(event,
|
||||
result.payload.suggestion || result.payload.query);
|
||||
if (url) {
|
||||
|
@ -346,7 +346,7 @@ class UrlbarInput {
|
|||
this._recordSearch(engine, event, actionDetails);
|
||||
break;
|
||||
}
|
||||
case UrlbarUtils.MATCH_TYPE.OMNIBOX:
|
||||
case UrlbarUtils.RESULT_TYPE.OMNIBOX:
|
||||
// Give the extension control of handling the command.
|
||||
ExtensionSearchHandler.handleInputEntered(result.payload.keyword,
|
||||
result.payload.content,
|
||||
|
@ -366,7 +366,7 @@ class UrlbarInput {
|
|||
let val;
|
||||
|
||||
switch (result.type) {
|
||||
case UrlbarUtils.MATCH_TYPE.SEARCH:
|
||||
case UrlbarUtils.RESULT_TYPE.SEARCH:
|
||||
val = result.payload.suggestion || result.payload.query;
|
||||
break;
|
||||
default: {
|
||||
|
|
|
@ -21,13 +21,13 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
XPCOMUtils.defineLazyGetter(this, "logger", () =>
|
||||
Log.repository.getLogger("Places.Urlbar.UrlbarMuxerUnifiedComplete"));
|
||||
|
||||
const MATCH_TYPE_TO_GROUP = new Map([
|
||||
[ UrlbarUtils.MATCH_TYPE.TAB_SWITCH, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.MATCH_TYPE.SEARCH, UrlbarUtils.MATCH_GROUP.SUGGESTION ],
|
||||
[ UrlbarUtils.MATCH_TYPE.URL, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.MATCH_TYPE.KEYWORD, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.MATCH_TYPE.OMNIBOX, UrlbarUtils.MATCH_GROUP.EXTENSION ],
|
||||
[ UrlbarUtils.MATCH_TYPE.REMOTE_TAB, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
const RESULT_TYPE_TO_GROUP = new Map([
|
||||
[ UrlbarUtils.RESULT_TYPE.TAB_SWITCH, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.RESULT_TYPE.SEARCH, UrlbarUtils.MATCH_GROUP.SUGGESTION ],
|
||||
[ UrlbarUtils.RESULT_TYPE.URL, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.RESULT_TYPE.KEYWORD, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
[ UrlbarUtils.RESULT_TYPE.OMNIBOX, UrlbarUtils.MATCH_GROUP.EXTENSION ],
|
||||
[ UrlbarUtils.RESULT_TYPE.REMOTE_TAB, UrlbarUtils.MATCH_GROUP.GENERAL ],
|
||||
]);
|
||||
|
||||
/**
|
||||
|
@ -54,7 +54,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
|||
// Check the first match, if it's a preselected search match, use search buckets.
|
||||
let firstMatch = context.results[0];
|
||||
let buckets = context.preselected &&
|
||||
firstMatch.type == UrlbarUtils.MATCH_TYPE.SEARCH ?
|
||||
firstMatch.type == UrlbarUtils.RESULT_TYPE.SEARCH ?
|
||||
UrlbarPrefs.get("matchBucketsSearch") :
|
||||
UrlbarPrefs.get("matchBuckets");
|
||||
logger.debug(`Buckets: ${buckets}`);
|
||||
|
@ -78,12 +78,12 @@ class MuxerUnifiedComplete extends UrlbarMuxer {
|
|||
sortedMatches.push(match);
|
||||
handled.add(match);
|
||||
count--;
|
||||
} else if (group == MATCH_TYPE_TO_GROUP.get(match.type)) {
|
||||
} else if (group == RESULT_TYPE_TO_GROUP.get(match.type)) {
|
||||
sortedMatches.push(match);
|
||||
handled.add(match);
|
||||
count--;
|
||||
} else if (!MATCH_TYPE_TO_GROUP.has(match.type)) {
|
||||
let errorMsg = `Match type ${match.type} is not mapped to a match group.`;
|
||||
} else if (!RESULT_TYPE_TO_GROUP.has(match.type)) {
|
||||
let errorMsg = `Result type ${match.type} is not mapped to a match group.`;
|
||||
logger.error(errorMsg);
|
||||
Cu.reportError(errorMsg);
|
||||
}
|
||||
|
|
|
@ -147,11 +147,11 @@ const PREF_TYPES = new Map([
|
|||
["number", "Int"],
|
||||
]);
|
||||
|
||||
// Buckets for match insertion.
|
||||
// Every time a new match is returned, we go through each bucket in array order,
|
||||
// and look for the first one having available space for the given match type.
|
||||
// Buckets for result insertion.
|
||||
// Every time a new result is returned, we go through each bucket in array order,
|
||||
// and look for the first one having available space for the given result type.
|
||||
// Each bucket is an array containing the following indices:
|
||||
// 0: The match type of the acceptable entries.
|
||||
// 0: The result type of the acceptable entries.
|
||||
// 1: available number of slots in this bucket.
|
||||
// There are different matchBuckets definition for different contexts, currently
|
||||
// a general one (matchBuckets) and a search one (matchBucketsSearch).
|
||||
|
|
|
@ -162,7 +162,7 @@ class ProviderOpenTabs extends UrlbarProvider {
|
|||
cancel();
|
||||
return;
|
||||
}
|
||||
addCallback(this, new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
addCallback(this, new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS, {
|
||||
url: row.getResultByName("url"),
|
||||
userContextId: row.getResultByName("userContextId"),
|
||||
|
|
|
@ -223,7 +223,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
switch (action.type) {
|
||||
case "searchengine":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.SEARCH,
|
||||
UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
UrlbarUtils.MATCH_SOURCE.SEARCH,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
engine: [action.params.engineName, true],
|
||||
|
@ -235,7 +235,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
);
|
||||
case "keyword":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.KEYWORD,
|
||||
UrlbarUtils.RESULT_TYPE.KEYWORD,
|
||||
UrlbarUtils.MATCH_SOURCE.BOOKMARKS,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
url: [action.params.url, true],
|
||||
|
@ -246,7 +246,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
);
|
||||
case "extension":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.OMNIBOX,
|
||||
UrlbarUtils.RESULT_TYPE.OMNIBOX,
|
||||
UrlbarUtils.MATCH_SOURCE.OTHER_NETWORK,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
title: [info.comment, true],
|
||||
|
@ -257,7 +257,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
);
|
||||
case "remotetab":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.REMOTE_TAB,
|
||||
UrlbarUtils.RESULT_TYPE.REMOTE_TAB,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
url: [action.params.url, true],
|
||||
|
@ -268,7 +268,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
);
|
||||
case "switchtab":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
url: [action.params.url, true],
|
||||
|
@ -279,7 +279,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
);
|
||||
case "visiturl":
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.URL,
|
||||
UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.MATCH_SOURCE.OTHER_LOCAL,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
title: [info.comment, true],
|
||||
|
@ -295,7 +295,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
|
||||
if (info.style.includes("priority-search")) {
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.SEARCH,
|
||||
UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
UrlbarUtils.MATCH_SOURCE.SEARCH,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
engine: [info.comment, true],
|
||||
|
@ -322,7 +322,7 @@ function makeUrlbarResult(tokens, info) {
|
|||
source = UrlbarUtils.MATCH_SOURCE.HISTORY;
|
||||
}
|
||||
return new UrlbarResult(
|
||||
UrlbarUtils.MATCH_TYPE.URL,
|
||||
UrlbarUtils.RESULT_TYPE.URL,
|
||||
source,
|
||||
...UrlbarResult.payloadAndSimpleHighlights(tokens, {
|
||||
url: [info.url, true],
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
/**
|
||||
* This module exports a urlbar result class, each representing a single result
|
||||
* found by a provider that can be passed from the model to the view through
|
||||
* the controller. It is mainly defined by a match type, and a payload,
|
||||
* the controller. It is mainly defined by a result type, and a payload,
|
||||
* containing the data. A few getters allow to retrieve information common to all
|
||||
* the match types.
|
||||
* the result types.
|
||||
*/
|
||||
|
||||
var EXPORTED_SYMBOLS = ["UrlbarResult"];
|
||||
|
@ -25,9 +25,9 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
class UrlbarResult {
|
||||
/**
|
||||
* Creates a result.
|
||||
* @param {integer} matchType one of UrlbarUtils.MATCH_TYPE.* values
|
||||
* @param {integer} resultType one of UrlbarUtils.RESULT_TYPE.* values
|
||||
* @param {integer} matchSource one of UrlbarUtils.MATCH_SOURCE.* values
|
||||
* @param {object} payload data for this match. A payload should always
|
||||
* @param {object} payload data for this result. A payload should always
|
||||
* contain a way to extract a final url to visit. The url getter
|
||||
* should have a case for each of the types.
|
||||
* @param {object} [payloadHighlights] payload highlights, if any. Each
|
||||
|
@ -36,13 +36,13 @@ class UrlbarResult {
|
|||
* length] tuples. Each tuple indicates a substring in the correspoding
|
||||
* payload property.
|
||||
*/
|
||||
constructor(matchType, matchSource, payload, payloadHighlights = {}) {
|
||||
constructor(resultType, matchSource, payload, payloadHighlights = {}) {
|
||||
// Type describes the payload and visualization that should be used for
|
||||
// this match.
|
||||
if (!Object.values(UrlbarUtils.MATCH_TYPE).includes(matchType)) {
|
||||
throw new Error("Invalid match type");
|
||||
// this result.
|
||||
if (!Object.values(UrlbarUtils.RESULT_TYPE).includes(resultType)) {
|
||||
throw new Error("Invalid result type");
|
||||
}
|
||||
this.type = matchType;
|
||||
this.type = resultType;
|
||||
|
||||
// Source describes which data has been used to derive this match. In case
|
||||
// multiple sources are involved, use the more privacy restricted.
|
||||
|
@ -51,15 +51,15 @@ class UrlbarResult {
|
|||
}
|
||||
this.source = matchSource;
|
||||
|
||||
// The payload contains match data. Some of the data is common across
|
||||
// The payload contains result data. Some of the data is common across
|
||||
// multiple types, but most of it will vary.
|
||||
if (!payload || (typeof payload != "object")) {
|
||||
throw new Error("Invalid match payload");
|
||||
throw new Error("Invalid result payload");
|
||||
}
|
||||
this.payload = payload;
|
||||
|
||||
if (!payloadHighlights || (typeof payloadHighlights != "object")) {
|
||||
throw new Error("Invalid match payload highlights");
|
||||
throw new Error("Invalid result payload highlights");
|
||||
}
|
||||
this.payloadHighlights = payloadHighlights;
|
||||
|
||||
|
@ -74,7 +74,7 @@ class UrlbarResult {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a title that could be used as a label for this match.
|
||||
* Returns a title that could be used as a label for this result.
|
||||
* @returns {string} The label to show in a simplified title / url view.
|
||||
*/
|
||||
get title() {
|
||||
|
@ -95,14 +95,14 @@ class UrlbarResult {
|
|||
*/
|
||||
get _titleAndHighlights() {
|
||||
switch (this.type) {
|
||||
case UrlbarUtils.MATCH_TYPE.TAB_SWITCH:
|
||||
case UrlbarUtils.MATCH_TYPE.URL:
|
||||
case UrlbarUtils.MATCH_TYPE.OMNIBOX:
|
||||
case UrlbarUtils.MATCH_TYPE.REMOTE_TAB:
|
||||
case UrlbarUtils.RESULT_TYPE.TAB_SWITCH:
|
||||
case UrlbarUtils.RESULT_TYPE.URL:
|
||||
case UrlbarUtils.RESULT_TYPE.OMNIBOX:
|
||||
case UrlbarUtils.RESULT_TYPE.REMOTE_TAB:
|
||||
return this.payload.title ?
|
||||
[this.payload.title, this.payloadHighlights.title] :
|
||||
[this.payload.url || "", this.payloadHighlights.url || []];
|
||||
case UrlbarUtils.MATCH_TYPE.SEARCH:
|
||||
case UrlbarUtils.RESULT_TYPE.SEARCH:
|
||||
return this.payload.suggestion ?
|
||||
[this.payload.suggestion, this.payloadHighlights.suggestion] :
|
||||
[this.payload.query, this.payloadHighlights.query];
|
||||
|
|
|
@ -45,7 +45,7 @@ var UrlbarUtils = {
|
|||
MAXIMUM_ALLOWED_EXTENSION_MATCHES: 6,
|
||||
|
||||
// This is used by UnifiedComplete, the new implementation will use
|
||||
// PROVIDER_TYPE and MATCH_TYPE
|
||||
// PROVIDER_TYPE and RESULT_TYPE
|
||||
MATCH_GROUP: {
|
||||
HEURISTIC: "heuristic",
|
||||
GENERAL: "general",
|
||||
|
@ -67,7 +67,7 @@ var UrlbarUtils = {
|
|||
},
|
||||
|
||||
// Defines UrlbarResult types.
|
||||
MATCH_TYPE: {
|
||||
RESULT_TYPE: {
|
||||
// An open tab.
|
||||
// Payload: { icon, url, userContextId }
|
||||
TAB_SWITCH: 1,
|
||||
|
|
|
@ -272,8 +272,8 @@ class UrlbarView {
|
|||
|
||||
let favicon = this._createElement("img");
|
||||
favicon.className = "urlbarView-favicon";
|
||||
if (result.type == UrlbarUtils.MATCH_TYPE.SEARCH ||
|
||||
result.type == UrlbarUtils.MATCH_TYPE.KEYWORD) {
|
||||
if (result.type == UrlbarUtils.RESULT_TYPE.SEARCH ||
|
||||
result.type == UrlbarUtils.RESULT_TYPE.KEYWORD) {
|
||||
favicon.src = "chrome://browser/skin/search-glass.svg";
|
||||
} else {
|
||||
favicon.src = result.payload.icon || "chrome://mozapps/skin/places/defaultFavicon.svg";
|
||||
|
@ -302,11 +302,11 @@ class UrlbarView {
|
|||
let secondary = this._createElement("span");
|
||||
secondary.className = "urlbarView-secondary";
|
||||
switch (result.type) {
|
||||
case UrlbarUtils.MATCH_TYPE.TAB_SWITCH:
|
||||
case UrlbarUtils.RESULT_TYPE.TAB_SWITCH:
|
||||
secondary.classList.add("urlbarView-action");
|
||||
secondary.textContent = bundle.GetStringFromName("switchToTab2");
|
||||
break;
|
||||
case UrlbarUtils.MATCH_TYPE.SEARCH:
|
||||
case UrlbarUtils.RESULT_TYPE.SEARCH:
|
||||
secondary.classList.add("urlbarView-action");
|
||||
secondary.textContent =
|
||||
bundle.formatStringFromName("searchWithEngine",
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
[DEFAULT]
|
||||
prefs=browser.urlbar.quantumbar=true
|
||||
tags=quantumbar
|
||||
support-files =
|
||||
dummy_page.html
|
||||
head.js
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[DEFAULT]
|
||||
prefs=browser.urlbar.quantumbar=false
|
||||
tags=urlbar
|
||||
support-files =
|
||||
../browser/dummy_page.html
|
||||
../browser/head-common.js
|
||||
|
|
|
@ -33,7 +33,7 @@ add_task(function losslessDecode() {
|
|||
let urlNoScheme = "example.com/\u30a2\u30a4\u30a6\u30a8\u30aa";
|
||||
let url = "http://" + urlNoScheme;
|
||||
if (Services.prefs.getBoolPref("browser.urlbar.quantumbar", true)) {
|
||||
const result = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
const result = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url });
|
||||
gURLBar.setValueFromResult(result);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
const TEST_URL = "http://example.com";
|
||||
const match = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
const match = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: TEST_URL });
|
||||
let controller;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"use strict";
|
||||
|
||||
const TEST_URL = "http://example.com";
|
||||
const MATCH = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
const MATCH = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: TEST_URL });
|
||||
const TELEMETRY_1ST_RESULT = "PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS";
|
||||
|
@ -156,7 +156,7 @@ add_task(async function test_n_autocomplete_results() {
|
|||
for (let i = 0; i < 5; i++) {
|
||||
resultsPromise = promiseControllerNotification(controller, "onQueryResults");
|
||||
provider.addResults([
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: TEST_URL + "/i" }),
|
||||
]);
|
||||
|
@ -178,7 +178,7 @@ add_task(async function test_n_autocomplete_results() {
|
|||
// Add one more, to check neither are updated.
|
||||
resultsPromise = promiseControllerNotification(controller, "onQueryResults");
|
||||
provider.addResults([
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: TEST_URL + "/6" }),
|
||||
]);
|
||||
|
|
|
@ -23,13 +23,13 @@ add_task(async function test_muxer() {
|
|||
"Should throw with invalid sort");
|
||||
|
||||
let matches = [
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: "http://mozilla.org/tab/" }),
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.URL,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.MATCH_SOURCE.BOOKMARKS,
|
||||
{ url: "http://mozilla.org/bookmark/" }),
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.URL,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.MATCH_SOURCE.HISTORY,
|
||||
{ url: "http://mozilla.org/history/" }),
|
||||
];
|
||||
|
|
|
@ -19,8 +19,8 @@ add_task(async function test_openTabs() {
|
|||
let callback = function(provider, match) {
|
||||
matchCount++;
|
||||
Assert.equal(provider, UrlbarProviderOpenTabs, "Got the expected provider");
|
||||
Assert.equal(match.type, UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
"Got the expected match type");
|
||||
Assert.equal(match.type, UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
"Got the expected result type");
|
||||
Assert.equal(match.payload.url, url, "Got the expected url");
|
||||
Assert.equal(match.payload.title, undefined, "Got the expected title");
|
||||
};
|
||||
|
|
|
@ -49,13 +49,13 @@ add_task(async function test_unifiedComplete() {
|
|||
Assert.equal(context.results.length, 6, "Found the expected number of matches");
|
||||
|
||||
Assert.deepEqual([
|
||||
UrlbarUtils.MATCH_TYPE.SEARCH,
|
||||
UrlbarUtils.MATCH_TYPE.SEARCH,
|
||||
UrlbarUtils.MATCH_TYPE.SEARCH,
|
||||
UrlbarUtils.MATCH_TYPE.URL,
|
||||
UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_TYPE.URL,
|
||||
], context.results.map(m => m.type), "Check match types");
|
||||
UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
UrlbarUtils.RESULT_TYPE.SEARCH,
|
||||
UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.RESULT_TYPE.URL,
|
||||
], context.results.map(m => m.type), "Check result types");
|
||||
|
||||
Assert.deepEqual([
|
||||
"moz",
|
||||
|
|
|
@ -29,7 +29,7 @@ add_task(async function test_providers() {
|
|||
/invalid provider/,
|
||||
"Should throw with invalid cancelQuery");
|
||||
|
||||
let match = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
let match = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: "http://mozilla.org/foo/" });
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"use strict";
|
||||
|
||||
add_task(async function test_filtering() {
|
||||
let match = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
let match = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: "http://mozilla.org/foo/" });
|
||||
let providerName = registerBasicTestProvider([match]);
|
||||
|
@ -29,7 +29,7 @@ add_task(async function test_filtering() {
|
|||
|
||||
let matches = [
|
||||
match,
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.HISTORY,
|
||||
{ url: "http://mozilla.org/foo/" }),
|
||||
];
|
||||
|
@ -67,10 +67,10 @@ add_task(async function test_filter_javascript() {
|
|||
},
|
||||
},
|
||||
});
|
||||
let match = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
let match = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: "http://mozilla.org/foo/" });
|
||||
let jsMatch = new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
let jsMatch = new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.HISTORY,
|
||||
{ url: "javascript:foo" });
|
||||
let providerName = registerBasicTestProvider([match, jsMatch]);
|
||||
|
@ -110,10 +110,10 @@ add_task(async function test_filter_sources() {
|
|||
});
|
||||
|
||||
let goodMatches = [
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: "http://mozilla.org/foo/" }),
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.URL,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.MATCH_SOURCE.HISTORY,
|
||||
{ url: "http://mozilla.org/foo/" }),
|
||||
];
|
||||
|
@ -144,7 +144,7 @@ add_task(async function test_filter_sources() {
|
|||
UrlbarProvidersManager.registerProvider(new TestProvider());
|
||||
|
||||
let badMatches = [
|
||||
new UrlbarResult(UrlbarUtils.MATCH_TYPE.URL,
|
||||
new UrlbarResult(UrlbarUtils.RESULT_TYPE.URL,
|
||||
UrlbarUtils.MATCH_SOURCE.BOOKMARKS,
|
||||
{ url: "http://mozilla.org/foo/" }),
|
||||
];
|
||||
|
|
|
@ -7,7 +7,7 @@ add_task(async function test_maxResults() {
|
|||
const MATCHES_LENGTH = 20;
|
||||
let matches = [];
|
||||
for (let i = 0; i < MATCHES_LENGTH; i++) {
|
||||
matches.push(new UrlbarResult(UrlbarUtils.MATCH_TYPE.TAB_SWITCH,
|
||||
matches.push(new UrlbarResult(UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
|
||||
UrlbarUtils.MATCH_SOURCE.TABS,
|
||||
{ url: `http://mozilla.org/foo/${i}` }));
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ Queries can be canceled.
|
|||
|
||||
The *searchString* gets tokenized by the `UrlbarTokenizer <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarTokenizer.jsm>`_
|
||||
component into tokens, some of these tokens have a special meaning and can be
|
||||
used by the user to restrict the search to specific match type (See the
|
||||
used by the user to restrict the search to specific result type (See the
|
||||
*UrlbarTokenizer::TYPE* enum).
|
||||
|
||||
.. caution::
|
||||
|
@ -355,29 +355,29 @@ UrlbarResult
|
|||
===========
|
||||
|
||||
An `UrlbarResult <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarResult.jsm>`_
|
||||
instance represents a single search result with a match type, that
|
||||
instance represents a single search result with a result type, that
|
||||
identifies specific kind of results.
|
||||
Each kind has its own properties, that the *View* may support, and a few common
|
||||
properties, supported by all of the results.
|
||||
|
||||
.. note::
|
||||
|
||||
Match types are also enumerated by *UrlbarUtils.MATCH_TYPE*.
|
||||
Result types are also enumerated by *UrlbarUtils.RESULT_TYPE*.
|
||||
|
||||
.. highlight:: JavaScript
|
||||
.. code::
|
||||
|
||||
UrlbarResult {
|
||||
constructor(matchType, payload);
|
||||
constructor(resultType, payload);
|
||||
|
||||
type: {integer} One of UrlbarUtils.MATCH_TYPE.
|
||||
type: {integer} One of UrlbarUtils.RESULT_TYPE.
|
||||
source: {integer} One of UrlbarUtils.MATCH_SOURCE.
|
||||
title: {string} A title that may be used as a label for this match.
|
||||
icon: {string} Url of an icon for this match.
|
||||
payload: {object} Object containing properties for the specific MATCH_TYPE.
|
||||
title: {string} A title that may be used as a label for this result.
|
||||
icon: {string} Url of an icon for this result.
|
||||
payload: {object} Object containing properties for the specific RESULT_TYPE.
|
||||
}
|
||||
|
||||
The following MATCH_TYPEs are supported:
|
||||
The following RESULT_TYPEs are supported:
|
||||
|
||||
.. highlight:: JavaScript
|
||||
.. code::
|
||||
|
|
|
@ -174,7 +174,6 @@
|
|||
#identity-popup-content-blocking-report-breakage,
|
||||
.identity-popup-content-blocking-category-label,
|
||||
.identity-popup-content-blocking-category-state-label,
|
||||
.identity-popup-content-blocking-category-add-blocking,
|
||||
.identity-popup-permission-label,
|
||||
.identity-popup-permission-state-label,
|
||||
.identity-popup-security-content > description,
|
||||
|
@ -676,7 +675,6 @@ description#identity-popup-content-verifier,
|
|||
}
|
||||
|
||||
.identity-popup-content-blocking-category-state-label,
|
||||
.identity-popup-content-blocking-category-add-blocking,
|
||||
.identity-popup-permission-state-label {
|
||||
margin-inline-end: 5px;
|
||||
text-align: end;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
background: var(--autocomplete-popup-background);
|
||||
color: var(--autocomplete-popup-color);
|
||||
border: 1px solid var(--autocomplete-popup-border-color);
|
||||
font: menu;
|
||||
}
|
||||
|
||||
.urlbarView-body-inner {
|
||||
|
|
|
@ -66,7 +66,6 @@ NS_INTERFACE_MAP_BEGIN(NullPrincipalURI)
|
|||
else
|
||||
NS_INTERFACE_MAP_ENTRY(nsIURI)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISizeOf)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -301,9 +300,6 @@ NullPrincipalURI::GetDisplayPrePath(nsACString& aPrePath) {
|
|||
return GetPrePath(aPrePath);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIIPCSerializableURI
|
||||
|
||||
void NullPrincipalURI::Serialize(mozilla::ipc::URIParams& aParams) {
|
||||
aParams = mozilla::ipc::NullPrincipalURIParams();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "nsISizeOf.h"
|
||||
#include "nsString.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIIPCSerializableURI.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "NullPrincipal.h"
|
||||
#include "nsID.h"
|
||||
|
@ -33,13 +32,10 @@ namespace mozilla {
|
|||
|
||||
class Encoding;
|
||||
|
||||
class NullPrincipalURI final : public nsIURI,
|
||||
public nsISizeOf,
|
||||
public nsIIPCSerializableURI {
|
||||
class NullPrincipalURI final : public nsIURI, public nsISizeOf {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSIIPCSERIALIZABLEURI
|
||||
|
||||
// nsISizeOf
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
/* Global layout vars */
|
||||
--page-width: 664px;
|
||||
--base-distance: 4px;
|
||||
--base-unit: 4px;
|
||||
|
||||
/* Global styles */
|
||||
--base-font-style: message-box;
|
||||
|
@ -52,12 +52,12 @@
|
|||
/*
|
||||
* Variables particular to about:debugging
|
||||
*/
|
||||
--alt-heading-icon-size: calc(var(--base-distance) * 6);
|
||||
--alt-heading-icon-gap: var(--base-distance);
|
||||
--main-heading-icon-size: calc(var(--base-distance) * 16);
|
||||
--main-heading-icon-gap: calc(var(--base-distance) * 3);
|
||||
--main-subheading-icon-size: calc(var(--base-distance) * 5);
|
||||
--main-subheading-heading-icon-gap: calc(var(--base-distance) * 2);
|
||||
--alt-heading-icon-size: calc(var(--base-unit) * 6);
|
||||
--alt-heading-icon-gap: var(--base-unit);
|
||||
--main-heading-icon-size: calc(var(--base-unit) * 16);
|
||||
--main-heading-icon-gap: calc(var(--base-unit) * 3);
|
||||
--main-subheading-icon-size: calc(var(--base-unit) * 5);
|
||||
--main-subheading-heading-icon-gap: calc(var(--base-unit) * 2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,7 +148,7 @@ a:active {
|
|||
* +--------+-------------+
|
||||
*/
|
||||
.main-subheading {
|
||||
margin-block-start: calc(var(--base-distance) * 4);
|
||||
margin-block-start: calc(var(--base-unit) * 4);
|
||||
font-weight: 600;
|
||||
font-size: 1.46em; /* import from .header-name in common.inc.css */
|
||||
line-height: 1.3em; /* import from .header-name in common.inc.css */
|
||||
|
@ -172,7 +172,7 @@ a:active {
|
|||
line-height: 1.2; /* odd value - from common.inc.css */
|
||||
|
||||
margin-block-start: 0;
|
||||
margin-block-end: calc(var(--base-distance) * 4);
|
||||
margin-block-end: calc(var(--base-unit) * 4);
|
||||
}
|
||||
|
||||
/* Alternative style for a subheading (i.e. h2). It features an icon */
|
||||
|
@ -181,7 +181,7 @@ a:active {
|
|||
* +--------+-------------+
|
||||
*/
|
||||
.alt-subheading {
|
||||
margin-block-start: calc(var(--base-distance) * 4);
|
||||
margin-block-start: calc(var(--base-unit) * 4);
|
||||
font-weight: 600;
|
||||
font-size: 1.14em;
|
||||
line-height: 1.4em; /* odd value - from common.inc.css */
|
||||
|
@ -210,13 +210,13 @@ a:active {
|
|||
|
||||
/* adds breathing space to the separator */
|
||||
.separator--breathe {
|
||||
margin: calc(var(--base-distance) * 4) 0;
|
||||
margin: calc(var(--base-unit) * 4) 0;
|
||||
}
|
||||
|
||||
/* a series of button-like elements, layed out horizontally */
|
||||
.toolbar {
|
||||
display: flex;
|
||||
column-gap: var(--base-distance);
|
||||
column-gap: var(--base-unit);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -235,12 +235,12 @@ Form controls
|
|||
background-color: var(--page-background);
|
||||
|
||||
margin: 0;
|
||||
height: calc(var(--base-distance) * 8); /* Note: this is from Photon, not common.css */
|
||||
padding-inline-start: calc(var(--base-distance) * 5);
|
||||
padding-inline-end: calc(var(--base-distance) * 5);
|
||||
height: calc(var(--base-unit) * 8); /* Note: this is from Photon, not common.css */
|
||||
padding-inline-start: calc(var(--base-unit) * 5);
|
||||
padding-inline-end: calc(var(--base-unit) * 5);
|
||||
|
||||
border: 1px solid var(--box-border-color);
|
||||
border-radius: calc(var(--base-distance) / 2);
|
||||
border-radius: calc(var(--base-unit) / 2);
|
||||
}
|
||||
|
||||
.default-button:enabled:hover {
|
||||
|
@ -253,16 +253,16 @@ Form controls
|
|||
|
||||
/* smaller size for a default button */
|
||||
.default-button--micro {
|
||||
padding-inline-start: calc(2 * var(--base-distance));
|
||||
padding-inline-end: calc(2 * var(--base-distance));
|
||||
padding-inline-start: calc(2 * var(--base-unit));
|
||||
padding-inline-end: calc(2 * var(--base-unit));
|
||||
font-size: var(--micro-font-size);
|
||||
height: calc(var(--base-distance) * 6);
|
||||
height: calc(var(--base-unit) * 6);
|
||||
}
|
||||
|
||||
/* standard inputs */
|
||||
.default-input {
|
||||
line-height: unset;
|
||||
padding: 0 calc(var(--base-distance) * 2);
|
||||
padding: 0 calc(var(--base-unit) * 2);
|
||||
height: 100%;
|
||||
|
||||
border: 1px solid var(--box-border-color);
|
||||
|
@ -282,8 +282,8 @@ Form controls
|
|||
.badge {
|
||||
font-size: var(--micro-font-size);
|
||||
background: var(--grey-30);
|
||||
border-radius: calc(var(--base-distance) / 2);
|
||||
padding: var(--base-distance) calc(2 * var(--base-distance));
|
||||
border-radius: calc(var(--base-unit) / 2);
|
||||
padding: var(--base-unit) calc(2 * var(--base-unit));
|
||||
}
|
||||
|
||||
.badge--info {
|
||||
|
|
|
@ -54,6 +54,6 @@
|
|||
}
|
||||
|
||||
.page__section {
|
||||
margin-block-end: calc(var(--base-distance) * 12);
|
||||
margin-block-end: calc(var(--base-unit) * 12);
|
||||
--section-inline-margin: calc(var(--alt-heading-icon-size) + var(--alt-heading-icon-gap));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.connection-prompt-setting {
|
||||
margin-block-end: var(--base-distance);
|
||||
margin-block-end: var(--base-unit);
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.connect-page__usb__toggle-button {
|
||||
margin-top: calc(var(--base-distance) * 4);
|
||||
margin-top: calc(var(--base-unit) * 4);
|
||||
}
|
||||
|
||||
.connect-page__disabled-section {
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
.connect-page__step-list {
|
||||
list-style-type: decimal;
|
||||
list-style-position: outside;
|
||||
margin-inline-start: calc(var(--section-inline-margin) + var(--base-distance) * 4);
|
||||
margin-inline-start: calc(var(--section-inline-margin) + var(--base-unit) * 4);
|
||||
}
|
||||
|
||||
.connect-page__step {
|
||||
padding-inline-start: var(--base-distance);
|
||||
padding-inline-start: var(--base-unit);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
.connect-page__network-form {
|
||||
display: grid;
|
||||
grid-column-gap: calc(var(--base-distance) * 2);
|
||||
grid-column-gap: calc(var(--base-unit) * 2);
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -12,5 +12,5 @@
|
|||
.connect-page__network-location {
|
||||
display: grid;
|
||||
grid-template-columns: auto max-content;
|
||||
margin: calc(var(--base-distance) * 2) 0;
|
||||
margin: calc(var(--base-unit) * 2) 0;
|
||||
}
|
|
@ -14,11 +14,11 @@
|
|||
*/
|
||||
.debug-target-item {
|
||||
display: grid;
|
||||
grid-template-columns: calc(var(--base-distance) * 9) 1fr max-content;
|
||||
grid-column-gap: calc(var(--base-distance) * 2);
|
||||
grid-template-columns: calc(var(--base-unit) * 9) 1fr max-content;
|
||||
grid-column-gap: calc(var(--base-unit) * 2);
|
||||
grid-template-areas: "icon name action"
|
||||
". detail detail";
|
||||
margin-block-end: calc(var(--base-distance) * 4);
|
||||
margin-block-end: calc(var(--base-unit) * 4);
|
||||
}
|
||||
|
||||
.debug-target-item__icon {
|
||||
|
@ -30,7 +30,7 @@
|
|||
grid-area: name;
|
||||
/* so as to ellipsis */
|
||||
min-width: 0;
|
||||
font-size: calc(var(--base-distance) * 5);
|
||||
font-size: calc(var(--base-unit) * 5);
|
||||
}
|
||||
|
||||
.debug-target-item__action {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.debug-target-list {
|
||||
margin-inline-start: calc(var(--base-distance) * 6);
|
||||
margin-inline-start: calc(var(--base-unit) * 6);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
.extension-detail {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-column-gap: calc(var(--base-distance) * 2);
|
||||
grid-column-gap: calc(var(--base-unit) * 2);
|
||||
}
|
||||
|
||||
.extension-detail__manifest {
|
||||
|
|
|
@ -51,7 +51,7 @@ class ServiceWorkerAction extends PureComponent {
|
|||
if (!isRunning) {
|
||||
const startLabel = this.props.getString("about-debugging-worker-action-start");
|
||||
return this._renderButton({
|
||||
className: "default-button",
|
||||
className: "default-button js-start-button",
|
||||
disabled: isMultiE10s,
|
||||
label: startLabel,
|
||||
onClick: this.start.bind(this),
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.temporary-extension-detail__temporary-id-message {
|
||||
padding: calc(var(--base-distance) * 2) 0;
|
||||
padding: calc(var(--base-unit) * 2) 0;
|
||||
}
|
|
@ -19,5 +19,5 @@
|
|||
.worker-detail {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-column-gap: calc(4 * var(--base-distance));
|
||||
grid-column-gap: calc(4 * var(--base-unit));
|
||||
}
|
||||
|
|
|
@ -24,18 +24,18 @@
|
|||
*/
|
||||
.message {
|
||||
background-color: var(--message-background-color);
|
||||
border-radius: var(--base-distance);
|
||||
border-radius: var(--base-unit);
|
||||
color: var(--message-color);
|
||||
display: grid;
|
||||
fill: var(--message-color);
|
||||
grid-column-gap: var(--base-distance);
|
||||
grid-template-columns: calc(var(--base-distance) * 6) 1fr;
|
||||
margin: calc(var(--base-distance) * 2) 0;
|
||||
padding: var(--base-distance);
|
||||
grid-column-gap: var(--base-unit);
|
||||
grid-template-columns: calc(var(--base-unit) * 6) 1fr;
|
||||
margin: calc(var(--base-unit) * 2) 0;
|
||||
padding: var(--base-unit);
|
||||
|
||||
-moz-context-properties: fill;
|
||||
}
|
||||
|
||||
.message__icon {
|
||||
margin: var(--base-distance);
|
||||
margin: var(--base-unit);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,6 @@
|
|||
}
|
||||
|
||||
.sidebar-item--breathe {
|
||||
margin-block-start: calc(2 * var(--base-distance));
|
||||
margin-block-end: calc(2 * var(--base-distance));
|
||||
margin-block-start: calc(2 * var(--base-unit));
|
||||
margin-block-end: calc(2 * var(--base-unit));
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
font-size: 0.8em;
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-column-gap: var(--base-distance);
|
||||
grid-template-columns: calc(var(--base-distance) * 6) 1fr auto;
|
||||
grid-column-gap: var(--base-unit);
|
||||
grid-template-columns: calc(var(--base-unit) * 6) 1fr auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче