diff --git a/browser/components/newtab/content-src/asrouter/templates/StartupOverlay/StartupOverlay.jsx b/browser/components/newtab/content-src/asrouter/templates/StartupOverlay/StartupOverlay.jsx index 11d2e91db309..87129fa4bbb5 100644 --- a/browser/components/newtab/content-src/asrouter/templates/StartupOverlay/StartupOverlay.jsx +++ b/browser/components/newtab/content-src/asrouter/templates/StartupOverlay/StartupOverlay.jsx @@ -18,6 +18,7 @@ export class _StartupOverlay extends React.PureComponent { this.state = { emailInput: "", overlayRemoved: false, + deviceId: "", flowId: "", flowBeginTime: 0, }; @@ -31,8 +32,8 @@ export class _StartupOverlay extends React.PureComponent { const fxaParams = "entrypoint=activity-stream-firstrun&form_type=email"; const response = await fetch(`${this.props.fxa_endpoint}/metrics-flow?${fxaParams}&${this.utmParams}`, {credentials: "omit"}); if (response.status === 200) { - const {flowId, flowBeginTime} = await response.json(); - this.setState({flowId, flowBeginTime}); + const {deviceId, flowId, flowBeginTime} = await response.json(); + this.setState({deviceId, flowId, flowBeginTime}); } else { this.props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_FETCH_ERROR", value: response.status}})); } @@ -132,6 +133,7 @@ export class _StartupOverlay extends React.PureComponent { + {this.props.intl.formatMessage({id: "firstrun_invalid_input"})} diff --git a/browser/components/newtab/content-src/asrouter/templates/Trailhead/Trailhead.jsx b/browser/components/newtab/content-src/asrouter/templates/Trailhead/Trailhead.jsx index 211c42a1fe77..1ed643b8a659 100644 --- a/browser/components/newtab/content-src/asrouter/templates/Trailhead/Trailhead.jsx +++ b/browser/components/newtab/content-src/asrouter/templates/Trailhead/Trailhead.jsx @@ -38,10 +38,12 @@ export class _Trailhead extends React.PureComponent { isModalOpen: true, showCardPanel: true, showCards: false, + // The params below are for FxA metrics + deviceId: "", flowId: "", flowBeginTime: 0, }; - this.didFetch = false; + this.fxaMetricsInitialized = false; } get dialog() { @@ -55,15 +57,15 @@ export class _Trailhead extends React.PureComponent { link.rel = "localization"; }); - if (this.props.fxaEndpoint && !this.didFetch) { + if (this.props.fxaEndpoint && !this.fxaMetricsInitialized) { try { - this.didFetch = true; + this.fxaMetricsInitialized = true; const url = new URL(`${this.props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`); this.addUtmParams(url); const response = await fetch(url, {credentials: "omit"}); if (response.status === 200) { - const {flowId, flowBeginTime} = await response.json(); - this.setState({flowId, flowBeginTime}); + const {deviceId, flowId, flowBeginTime} = await response.json(); + this.setState({deviceId, flowId, flowBeginTime}); } else { this.props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {event: "FXA_METRICS_FETCH_ERROR", value: response.status}})); } @@ -194,6 +196,7 @@ export class _Trailhead extends React.PureComponent { this.addUtmParams(url, true); if (action.addFlowParams) { + url.searchParams.append("device_id", this.state.deviceId); url.searchParams.append("flow_id", this.state.flowId); url.searchParams.append("flow_begin_time", this.state.flowBeginTime); } @@ -232,9 +235,9 @@ export class _Trailhead extends React.PureComponent { {this.getStringValue(content.learn.text)} -
-

{this.getStringValue(content.form.title)}

-

{this.getStringValue(content.form.text)}

+
+

{this.getStringValue(content.form.title)}

+

{this.getStringValue(content.form.text)}

@@ -243,6 +246,7 @@ export class _Trailhead extends React.PureComponent { + diff --git a/browser/components/newtab/content-src/asrouter/templates/Trailhead/_Trailhead.scss b/browser/components/newtab/content-src/asrouter/templates/Trailhead/_Trailhead.scss index bc3dd42f777c..ca713f0ff77f 100644 --- a/browser/components/newtab/content-src/asrouter/templates/Trailhead/_Trailhead.scss +++ b/browser/components/newtab/content-src/asrouter/templates/Trailhead/_Trailhead.scss @@ -402,7 +402,7 @@ .inline-onboarding { &.activity-stream.welcome { - overflow: scroll; + overflow-y: scroll; } .modalOverlayInner { diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx index 42044efdd982..0204076fa35a 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.jsx @@ -78,10 +78,15 @@ export class DSImage extends React.PureComponent { this.state.containerHeight * 2 ); - img = (); + img = (); } } else if (!this.state.nonOptimizedImageFailed) { - img = (); + img = (); } else { // Remove the img element if both sources fail. Render a placeholder instead. img = (
); diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/_DSImage.scss similarity index 100% rename from browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/DSImage.scss rename to browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSImage/_DSImage.scss diff --git a/browser/components/newtab/content-src/styles/_mixins.scss b/browser/components/newtab/content-src/styles/_mixins.scss index e63b61c8c7f5..a206fadb597b 100644 --- a/browser/components/newtab/content-src/styles/_mixins.scss +++ b/browser/components/newtab/content-src/styles/_mixins.scss @@ -10,7 +10,10 @@ // Note: lineHeight and fontSize should be unitless but can be derived from pixel values @mixin limit-visibile-lines($line-count, $line-height, $font-size) { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: $font-size * 1px; + -webkit-line-clamp: $line-count; line-height: $line-height * 1px; max-height: 1em * $line-count * $line-height / $font-size; overflow: hidden; diff --git a/browser/components/newtab/css/activity-stream-linux.css b/browser/components/newtab/css/activity-stream-linux.css index 002aaef4cbfd..0dc3a6224312 100644 --- a/browser/components/newtab/css/activity-stream-linux.css +++ b/browser/components/newtab/css/activity-stream-linux.css @@ -1946,7 +1946,10 @@ main { .ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 15px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4em; overflow: hidden; } @@ -1961,7 +1964,10 @@ main { line-height: 1.538; margin: 8px 0; } .ds-hero .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; @@ -2030,7 +2036,10 @@ main { flex-direction: column; justify-content: space-between; } .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 4; line-height: 28px; max-height: 5.09091em; overflow: hidden; @@ -2150,7 +2159,10 @@ main { .ds-column-10 .ds-hero .wrapper .meta header, .ds-column-11 .ds-hero .wrapper .meta header, .ds-column-12 .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 3; line-height: 28px; max-height: 3.81818em; overflow: hidden; } @@ -2186,7 +2198,10 @@ main { .ds-column-10 .ds-hero .cards .ds-card .title, .ds-column-11 .ds-hero .cards .ds-card .title, .ds-column-12 .ds-hero .cards .ds-card .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2215,7 +2230,10 @@ main { line-height: 20px; position: relative; } .ds-list:not(.ds-list-full-width) .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2329,7 +2347,10 @@ main { position: relative; } .ds-list-full-width .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; } @@ -2356,7 +2377,10 @@ main { justify-content: space-between; height: 100%; } .ds-list-item .ds-list-item-excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 2; line-height: 20px; max-height: 2.85714em; overflow: hidden; @@ -2368,7 +2392,10 @@ main { margin: 0; } .ds-list-item .ds-list-item-info, .ds-list-item .ds-list-item-context { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 1; line-height: 20px; max-height: 1.42857em; overflow: hidden; @@ -2636,13 +2663,19 @@ main { flex-grow: 1; margin: 0 0 12px; } .ds-card .meta .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; font-weight: 600; } .ds-card .meta .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -3976,7 +4009,7 @@ a.firstrun-link { text-align: center; } .inline-onboarding.activity-stream.welcome { - overflow: scroll; } + overflow-y: scroll; } .inline-onboarding .modalOverlayInner { position: absolute; } diff --git a/browser/components/newtab/css/activity-stream-mac.css b/browser/components/newtab/css/activity-stream-mac.css index f54e5c263236..23bd56df449c 100644 --- a/browser/components/newtab/css/activity-stream-mac.css +++ b/browser/components/newtab/css/activity-stream-mac.css @@ -1949,7 +1949,10 @@ main { .ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 15px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4em; overflow: hidden; } @@ -1964,7 +1967,10 @@ main { line-height: 1.538; margin: 8px 0; } .ds-hero .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; @@ -2033,7 +2039,10 @@ main { flex-direction: column; justify-content: space-between; } .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 4; line-height: 28px; max-height: 5.09091em; overflow: hidden; @@ -2153,7 +2162,10 @@ main { .ds-column-10 .ds-hero .wrapper .meta header, .ds-column-11 .ds-hero .wrapper .meta header, .ds-column-12 .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 3; line-height: 28px; max-height: 3.81818em; overflow: hidden; } @@ -2189,7 +2201,10 @@ main { .ds-column-10 .ds-hero .cards .ds-card .title, .ds-column-11 .ds-hero .cards .ds-card .title, .ds-column-12 .ds-hero .cards .ds-card .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2218,7 +2233,10 @@ main { line-height: 20px; position: relative; } .ds-list:not(.ds-list-full-width) .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2332,7 +2350,10 @@ main { position: relative; } .ds-list-full-width .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; } @@ -2359,7 +2380,10 @@ main { justify-content: space-between; height: 100%; } .ds-list-item .ds-list-item-excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 2; line-height: 20px; max-height: 2.85714em; overflow: hidden; @@ -2371,7 +2395,10 @@ main { margin: 0; } .ds-list-item .ds-list-item-info, .ds-list-item .ds-list-item-context { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 1; line-height: 20px; max-height: 1.42857em; overflow: hidden; @@ -2639,13 +2666,19 @@ main { flex-grow: 1; margin: 0 0 12px; } .ds-card .meta .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; font-weight: 600; } .ds-card .meta .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -3979,7 +4012,7 @@ a.firstrun-link { text-align: center; } .inline-onboarding.activity-stream.welcome { - overflow: scroll; } + overflow-y: scroll; } .inline-onboarding .modalOverlayInner { position: absolute; } diff --git a/browser/components/newtab/css/activity-stream-windows.css b/browser/components/newtab/css/activity-stream-windows.css index 2ab228ee77d2..469efa7db41b 100644 --- a/browser/components/newtab/css/activity-stream-windows.css +++ b/browser/components/newtab/css/activity-stream-windows.css @@ -1946,7 +1946,10 @@ main { .ds-column-10 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-11 .ds-card-grid.ds-card-grid-divisible-by-4 .title, .ds-column-12 .ds-card-grid.ds-card-grid-divisible-by-4 .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 15px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4em; overflow: hidden; } @@ -1961,7 +1964,10 @@ main { line-height: 1.538; margin: 8px 0; } .ds-hero .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; @@ -2030,7 +2036,10 @@ main { flex-direction: column; justify-content: space-between; } .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 4; line-height: 28px; max-height: 5.09091em; overflow: hidden; @@ -2150,7 +2159,10 @@ main { .ds-column-10 .ds-hero .wrapper .meta header, .ds-column-11 .ds-hero .wrapper .meta header, .ds-column-12 .ds-hero .wrapper .meta header { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 22px; + -webkit-line-clamp: 3; line-height: 28px; max-height: 3.81818em; overflow: hidden; } @@ -2186,7 +2198,10 @@ main { .ds-column-10 .ds-hero .cards .ds-card .title, .ds-column-11 .ds-hero .cards .ds-card .title, .ds-column-12 .ds-hero .cards .ds-card .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2215,7 +2230,10 @@ main { line-height: 20px; position: relative; } .ds-list:not(.ds-list-full-width) .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -2329,7 +2347,10 @@ main { position: relative; } .ds-list-full-width .ds-list-item-title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; } @@ -2356,7 +2377,10 @@ main { justify-content: space-between; height: 100%; } .ds-list-item .ds-list-item-excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 2; line-height: 20px; max-height: 2.85714em; overflow: hidden; @@ -2368,7 +2392,10 @@ main { margin: 0; } .ds-list-item .ds-list-item-info, .ds-list-item .ds-list-item-context { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 1; line-height: 20px; max-height: 1.42857em; overflow: hidden; @@ -2636,13 +2663,19 @@ main { flex-grow: 1; margin: 0 0 12px; } .ds-card .meta .title { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 17px; + -webkit-line-clamp: 3; line-height: 24px; max-height: 4.23529em; overflow: hidden; font-weight: 600; } .ds-card .meta .excerpt { + -webkit-box-orient: vertical; + display: -webkit-box; font-size: 14px; + -webkit-line-clamp: 3; line-height: 20px; max-height: 4.28571em; overflow: hidden; } @@ -3976,7 +4009,7 @@ a.firstrun-link { text-align: center; } .inline-onboarding.activity-stream.welcome { - overflow: scroll; } + overflow-y: scroll; } .inline-onboarding .modalOverlayInner { position: absolute; } diff --git a/browser/components/newtab/data/content/activity-stream.bundle.js b/browser/components/newtab/data/content/activity-stream.bundle.js index ba2b9f1ed96c..8faf1c008d1a 100644 --- a/browser/components/newtab/data/content/activity-stream.bundle.js +++ b/browser/components/newtab/data/content/activity-stream.bundle.js @@ -2996,6 +2996,7 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC this.state = { emailInput: "", overlayRemoved: false, + deviceId: "", flowId: "", flowBeginTime: 0 }; @@ -3013,10 +3014,12 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC if (response.status === 200) { const { + deviceId, flowId, flowBeginTime } = await response.json(); this.setState({ + deviceId, flowId, flowBeginTime }); @@ -3212,6 +3215,10 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC name: "utm_term", type: "hidden", value: "trailhead-control" + }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { + name: "device_id", + type: "hidden", + value: this.state.deviceId }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "flow_id", type: "hidden", @@ -3310,10 +3317,12 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon isModalOpen: true, showCardPanel: true, showCards: false, + // The params below are for FxA metrics + deviceId: "", flowId: "", flowBeginTime: 0 }; - this.didFetch = false; + this.fxaMetricsInitialized = false; } get dialog() { @@ -3327,9 +3336,9 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon link.rel = "localization"; }); - if (this.props.fxaEndpoint && !this.didFetch) { + if (this.props.fxaEndpoint && !this.fxaMetricsInitialized) { try { - this.didFetch = true; + this.fxaMetricsInitialized = true; const url = new URL(`${this.props.fxaEndpoint}/metrics-flow?entrypoint=activity-stream-firstrun&form_type=email`); this.addUtmParams(url); const response = await fetch(url, { @@ -3338,10 +3347,12 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon if (response.status === 200) { const { + deviceId, flowId, flowBeginTime } = await response.json(); this.setState({ + deviceId, flowId, flowBeginTime }); @@ -3508,6 +3519,7 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon this.addUtmParams(url, true); if (action.addFlowParams) { + url.searchParams.append("device_id", this.state.deviceId); url.searchParams.append("flow_id", this.state.flowId); url.searchParams.append("flow_begin_time", this.state.flowBeginTime); } @@ -3564,10 +3576,15 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon target: "_blank", rel: "noopener noreferrer" }, this.getStringValue(content.learn.text))), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", { + role: "group", + "aria-labelledby": "joinFormHeader", + "aria-describedby": "joinFormBody", className: "trailheadForm" }, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("h3", { + id: "joinFormHeader", "data-l10n-id": content.form.title.string_id }, this.getStringValue(content.form.title)), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("p", { + id: "joinFormBody", "data-l10n-id": content.form.text.string_id }, this.getStringValue(content.form.text)), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("form", { method: "get", @@ -3603,6 +3620,10 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon name: "utm_term", type: "hidden", value: utm_term + }), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("input", { + name: "device_id", + type: "hidden", + value: this.state.deviceId }), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("input", { name: "flow_id", type: "hidden", @@ -7645,6 +7666,7 @@ class DSImage_DSImage extends external_React_default.a.PureComponent { source = this.reformatImageURL(baseSource, this.state.containerWidth, this.state.containerHeight); source2x = this.reformatImageURL(baseSource, this.state.containerWidth * 2, this.state.containerHeight * 2); img = external_React_default.a.createElement("img", { + crossOrigin: "anonymous", onError: this.onOptimizedImageError, src: source, srcSet: `${source2x} 2x` @@ -7652,6 +7674,7 @@ class DSImage_DSImage extends external_React_default.a.PureComponent { } } else if (!this.state.nonOptimizedImageFailed) { img = external_React_default.a.createElement("img", { + crossOrigin: "anonymous", onError: this.onNonOptimizedImageError, src: this.props.source }); diff --git a/browser/components/newtab/data/content/assets/trailhead/card-illo-mobile.png b/browser/components/newtab/data/content/assets/trailhead/card-illo-mobile.png index eff9628ed8fd..4a8fbcb7e403 100644 Binary files a/browser/components/newtab/data/content/assets/trailhead/card-illo-mobile.png and b/browser/components/newtab/data/content/assets/trailhead/card-illo-mobile.png differ diff --git a/browser/components/newtab/data/trailhead.wip b/browser/components/newtab/data/trailhead.wip deleted file mode 100644 index b4690a80064f..000000000000 --- a/browser/components/newtab/data/trailhead.wip +++ /dev/null @@ -1,142 +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/. - -## The following feature names must be treated as a brand, and kept in English. -## They cannot be: -## - Declined to adapt to grammatical case. -## - Transliterated. -## - Translated. - --facebook-container-brand-name = Facebook Container --lockwise-brand-name = Firefox Lockwise --monitor-brand-name = Firefox Monitor --pocket-brand-name = Pocket --send-brand-name = Firefox Send -# 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/. - -## UI strings for the simplified onboarding modal - -onboarding-button-label-learn-more = Learn More -onboarding-button-label-try-now = Try It Now -onboarding-button-label-get-started = Get Started - -onboarding-welcome-header = Welcome to { -brand-short-name } -onboarding-welcome-body = You’ve got the browser.
Meet the rest of { -brand-product-name }. -onboarding-welcome-learn-more = Learn more about the benefits. - -onboarding-join-form-header = Join { -brand-product-name } -onboarding-join-form-body = Enter your email address to get started. -onboarding-join-form-email = - .placeholder = Enter email -onboarding-join-form-email-error = Valid email required -onboarding-join-form-legal = By proceeding, you agree to the Terms of Service and Privacy Notice. -onboarding-join-form-continue = Continue - -onboarding-start-browsing-button-label = Start Browsing - -## These are individual benefit messages shown with an image, title and -## description. - -onboarding-benefit-products-title = Useful Products -onboarding-benefit-products-text = Get things done with a family of tools that respects your privacy across your devices. - -onboarding-benefit-knowledge-title = Practical Knowledge -onboarding-benefit-knowledge-text = Learn everything you need to know to stay smarter and safer online. - -onboarding-benefit-privacy-title = True Privacy -# "Personal Data Promise" should be treated as a brand and refers to a concept -# shown elsewhere to the user: "The Firefox Personal Data Promise is the way we -# honor your data in everything we make and do. We take less data. We keep it -# safe. And we make sure that we are transparent about how we use it." -onboarding-benefit-privacy-text = Everything we do honors our Personal Data Promise: Take less. Keep it safe. No secrets. - - -## These strings belong to the individual onboarding messages. - -## Each message has a title and a description of what the browser feature is. -## Each message also has an associated button for the user to try the feature. -## The string for the button is found above, in the UI strings section -onboarding-private-browsing-title = Private Browsing -onboarding-private-browsing-text = Browse by yourself. Private Browsing with Content Blocking blocks online trackers that follow you around the web. - -onboarding-screenshots-title = Screenshots -onboarding-screenshots-text = Take, save and share screenshots - without leaving { -brand-short-name }. Capture a region or an entire page as you browse. Then save to the web for easy access and sharing. - -onboarding-addons-title = Add-ons -onboarding-addons-text = Add even more features that make { -brand-short-name } work harder for you. Compare prices, check the weather or express your personality with a custom theme. - -onboarding-ghostery-title = Ghostery -onboarding-ghostery-text = Browse faster, smarter, or safer with extensions like Ghostery, which lets you block annoying ads. - -# Note: "Sync" in this case is a generic verb, as in "to synchronize" -onboarding-fxa-title = Sync -onboarding-fxa-text = Sign up for a { -fxaccount-brand-name } and sync your bookmarks, passwords, and open tabs everywhere you use { -brand-short-name }. - -onboarding-tracking-protection-title = Control How You’re Tracked -onboarding-tracking-protection-text = Don’t like when ads follow you around? { -brand-short-name } helps you control how advertisers track your activity online. -onboarding-tracking-protection-button = { PLATFORM() -> - [windows] Update Options - *[other] Update Preferences -} - -onboarding-data-sync-title = Take Your Settings with You -# "Sync" is short for synchronize. -onboarding-data-sync-text = Sync your bookmarks and passwords everywhere you use { -brand-product-name }. -onboarding-data-sync-button = Turn on { -sync-brand-short-name } - -onboarding-firefox-monitor-title = Stay Alert to Data Breaches -onboarding-firefox-monitor-text = { -monitor-brand-name } monitors if your email has appeared in a data breach and alerts you if it appears in a new breach. -onboarding-firefox-monitor-button = Sign up for Alerts - -onboarding-private-browsing-title = Browse Privately -onboarding-private-browsing-text = Private Browsing clears your search and browsing history to keep it secret from anyone who uses your computer. -onboarding-private-browsing-button = Open a Private Window - -onboarding-firefox-send-title = Keep Your Shared Files Private -onboarding-firefox-send-text = { -send-brand-name } protects the files you share with end-to-end encryption and a link that automatically expires. -onboarding-firefox-send-button = Try { -send-brand-name } - -onboarding-mobile-phone-title = Get { -brand-product-name } on Your Phone -onboarding-mobile-phone-text = Download { -brand-product-name } for iOS or Android and sync your data across devices. -# "Mobile" is short for mobile/cellular phone, "Browser" is short for web -# browser. -onboarding-mobile-phone-button = Download Mobile Browser - -onboarding-privacy-right-title = Privacy is Your Right -onboarding-privacy-right-text = { -brand-short-name } treats your data with respect by taking less, protecting it, and being clear about how we use it. -onboarding-privacy-right-button = Learn More - -onboarding-send-tabs-title = Instantly Send Yourself Tabs -# "Send Tabs" refers to "Send Tab to Device" feature that appears when opening a -# tab's context menu. -onboarding-send-tabs-text = Send Tabs instantly shares pages between your devices without having to copy, paste, or leave the browser. -onboarding-send-tabs-button = Start Using Send Tabs - -onboarding-pocket-anywhere-title = Read and Listen Anywhere -# "downtime" refers to the user's free/spare time. -onboarding-pocket-anywhere-text = { -pocket-brand-name } saves your favorite stories so you can read, listen, and watch during your downtime, even if you’re offline. -onboarding-pocket-anywhere-button = Try { -pocket-brand-name } - -onboarding-lockwise-passwords-title = Take Your Passwords Everywhere -# "many places" conveys that Lockwise is available outside of Firefox. -onboarding-lockwise-passwords-text = { -lockwise-brand-name } saves your passwords in a secure place so you can easily log into your accounts. -onboarding-lockwise-passwords-button = Get { -lockwise-brand-name } - -onboarding-facebook-container-title = Set Boundaries with Facebook -onboarding-facebook-container-text = { -facebook-container-brand-name } keeps your Facebook identity separate from everything else, making it harder to track you across the web. -onboarding-facebook-container-button = Add the Extension - - -## Message strings belonging to the Return to AMO flow -return-to-amo-sub-header = Great, you’ve got { -brand-short-name } - -# will be replaced with the icon belonging to the extension -# -# Variables: -# $addon-name (String) - Name of the add-on -return-to-amo-addon-header = Now let’s get you { $addon-name }. -return-to-amo-extension-button = Add the Extension -return-to-amo-get-started-button = Get Started with { -brand-short-name } diff --git a/browser/components/newtab/lib/OnboardingMessageProvider.jsm b/browser/components/newtab/lib/OnboardingMessageProvider.jsm index 757f58f58557..b18493eb7837 100644 --- a/browser/components/newtab/lib/OnboardingMessageProvider.jsm +++ b/browser/components/newtab/lib/OnboardingMessageProvider.jsm @@ -485,6 +485,16 @@ const OnboardingMessageProvider = { } catch (e) { continue; } + + // We know we want to show this message, so translate message strings + const [primary_button_string, title_string, text_string] = await L10N.formatMessages([ + {id: msg.content.primary_button.label.string_id}, + {id: msg.content.title.string_id}, + {id: msg.content.text.string_id, args: msg.content.text.args}, + ]); + translatedMessage.content.primary_button.label = primary_button_string.value; + translatedMessage.content.title = title_string.value; + translatedMessage.content.text = text_string.value; } // Translate any secondary buttons separately diff --git a/browser/components/newtab/locales-src/cs/strings.properties b/browser/components/newtab/locales-src/cs/strings.properties index 4247cbf47c86..76e48bf5879d 100644 --- a/browser/components/newtab/locales-src/cs/strings.properties +++ b/browser/components/newtab/locales-src/cs/strings.properties @@ -192,7 +192,7 @@ section_menu_action_privacy_notice=Zásady ochrany osobních údajů # firstrun of the browser, they give an introduction to Firefox and Sync. firstrun_title=Vezměte si Firefox s sebou firstrun_content=Mějte své záložky, historii i uložená hesla s sebou na všech svých zařízeních. -firstrun_learn_more_link=Zjistěte více o účtech Firefoxu +firstrun_learn_more_link=Zjistit více o účtech Firefoxu # LOCALIZATION NOTE (firstrun_form_header and firstrun_form_sub_header): # firstrun_form_sub_header is a continuation of firstrun_form_header, they are one sentence. diff --git a/browser/components/newtab/prerendered/locales/cs/activity-stream-strings.js b/browser/components/newtab/prerendered/locales/cs/activity-stream-strings.js index 206a11602508..e3ff99bd43c6 100644 --- a/browser/components/newtab/prerendered/locales/cs/activity-stream-strings.js +++ b/browser/components/newtab/prerendered/locales/cs/activity-stream-strings.js @@ -95,7 +95,7 @@ window.gActivityStreamStrings = { "section_menu_action_privacy_notice": "Zásady ochrany osobních údajů", "firstrun_title": "Vezměte si Firefox s sebou", "firstrun_content": "Mějte své záložky, historii i uložená hesla s sebou na všech svých zařízeních.", - "firstrun_learn_more_link": "Zjistěte více o účtech Firefoxu", + "firstrun_learn_more_link": "Zjistit více o účtech Firefoxu", "firstrun_form_header": "Zadejte svoji e-mailovou adresu", "firstrun_form_sub_header": "a používejte službu Firefox Sync.", "firstrun_email_input_placeholder": "E-mail", diff --git a/browser/components/newtab/test/unit/asrouter/templates/Trailhead.test.jsx b/browser/components/newtab/test/unit/asrouter/templates/Trailhead.test.jsx index e89e144c58a2..2bfbb872a7ed 100644 --- a/browser/components/newtab/test/unit/asrouter/templates/Trailhead.test.jsx +++ b/browser/components/newtab/test/unit/asrouter/templates/Trailhead.test.jsx @@ -93,13 +93,14 @@ describe("", () => { data: {args: "https://example.com/path?foo=bar"}, }; wrapper.setState({ + deviceId: "abc", flowId: "123", flowBeginTime: 456, }); wrapper.instance().onCardAction(action); assert.calledOnce(onAction); const url = onAction.firstCall.args[0].data.args; - assert.equal(url, "https://example.com/path?foo=bar&utm_source=activity-stream&utm_campaign=firstrun&utm_medium=referral&utm_term=trailhead-join-card&flow_id=123&flow_begin_time=456"); + assert.equal(url, "https://example.com/path?foo=bar&utm_source=activity-stream&utm_campaign=firstrun&utm_medium=referral&utm_term=trailhead-join-card&device_id=abc&flow_id=123&flow_begin_time=456"); }); it("should keep focus in dialog when blurring start button", () => { diff --git a/browser/components/newtab/test/unit/unit-entry.js b/browser/components/newtab/test/unit/unit-entry.js index 884f4c2a262d..9179fa52c1b0 100644 --- a/browser/components/newtab/test/unit/unit-entry.js +++ b/browser/components/newtab/test/unit/unit-entry.js @@ -286,7 +286,7 @@ const TEST_GLOBAL = { }, Sampling: { ratioSample(seed, ratios) { - return 0; + return Promise.resolve(0); }, }, };