зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1550300 - Add top source, unblank discovery and bug fixes to Activity Stream r=r1cky
Differential Revision: https://phabricator.services.mozilla.com/D30438 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
3fb822b110
Коммит
de6f8d5227
|
@ -132,6 +132,7 @@ for (const type of [
|
|||
"TOP_SITES_UPDATED",
|
||||
"TOTAL_BOOKMARKS_REQUEST",
|
||||
"TOTAL_BOOKMARKS_RESPONSE",
|
||||
"TRAILHEAD_ENROLL_EVENT",
|
||||
"UNINIT",
|
||||
"UPDATE_PINNED_SEARCH_SHORTCUTS",
|
||||
"UPDATE_SEARCH_SHORTCUTS",
|
||||
|
|
|
@ -8,7 +8,7 @@ export class ModalOverlayWrapper extends React.PureComponent {
|
|||
|
||||
onKeyDown(event) {
|
||||
if (event.key === "Escape") {
|
||||
this.props.onClose();
|
||||
this.props.onClose(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,13 +123,18 @@ export class _Trailhead extends React.PureComponent {
|
|||
global.addEventListener("visibilitychange", this.closeModal);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
closeModal(ev) {
|
||||
global.removeEventListener("visibilitychange", this.closeModal);
|
||||
this.props.document.body.classList.remove("welcome");
|
||||
this.props.document.getElementById("root").removeAttribute("aria-hidden");
|
||||
this.setState({isModalOpen: false});
|
||||
this.revealCards();
|
||||
this.props.dispatch(ac.UserEvent({event: "SKIPPED_SIGNIN", ...this._getFormInfo()}));
|
||||
|
||||
// If closeModal() was triggered by a visibilitychange event, the user actually
|
||||
// submitted the email form so we don't send a SKIPPED_SIGNIN ping.
|
||||
if (!ev || ev.type !== "visibilitychange") {
|
||||
this.props.dispatch(ac.UserEvent({event: "SKIPPED_SIGNIN", ...this._getFormInfo()}));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -223,7 +228,7 @@ export class _Trailhead extends React.PureComponent {
|
|||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<a className="trailheadLearn" data-l10n-id={content.learn.text.string_id} href={this.addUtmParams(content.learn.url)}>
|
||||
<a className="trailheadLearn" data-l10n-id={content.learn.text.string_id} href={this.addUtmParams(content.learn.url)} target="_blank" rel="noopener noreferrer">
|
||||
{this.getStringValue(content.learn.text)}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -247,13 +252,13 @@ export class _Trailhead extends React.PureComponent {
|
|||
placeholder={this.getStringValue(content.form.email)}
|
||||
name="email"
|
||||
type="email"
|
||||
required="true"
|
||||
required="required"
|
||||
onInvalid={this.onInputInvalid}
|
||||
onChange={this.onInputChange} />
|
||||
<p className="trailheadTerms" data-l10n-id="onboarding-join-form-legal">
|
||||
<a data-l10n-name="terms"
|
||||
<a data-l10n-name="terms" target="_blank" rel="noopener noreferrer"
|
||||
href={this.addUtmParams("https://accounts.firefox.com/legal/terms")} />
|
||||
<a data-l10n-name="privacy"
|
||||
<a data-l10n-name="privacy" target="_blank" rel="noopener noreferrer"
|
||||
href={this.addUtmParams("https://accounts.firefox.com/legal/privacy")} />
|
||||
</p>
|
||||
<button data-l10n-id={content.form.button.string_id} type="submit">
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
.trailheadContent {
|
||||
.trailheadBenefits {
|
||||
background: url('#{$image-path}sync-devices.svg');
|
||||
background: url('#{$image-path}sync-devices-trailhead.svg');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
@ -401,6 +401,14 @@
|
|||
}
|
||||
|
||||
.inline-onboarding {
|
||||
&.activity-stream.welcome {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.modalOverlayInner {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.outer-wrapper {
|
||||
position: relative;
|
||||
|
||||
|
@ -415,15 +423,3 @@
|
|||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
// If the window is too short or narrow, we need to allow scrolling so user can get to Start Browsing button.
|
||||
@media (max-height: 760px), (max-width: 924px) {
|
||||
.activity-stream.welcome.inline-onboarding {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.trailhead {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,18 +41,13 @@ export class DSCard extends React.PureComponent {
|
|||
</div>
|
||||
<div className="meta">
|
||||
<div className="info-wrap">
|
||||
<p className="source">{this.props.source}</p>
|
||||
<header className="title">{this.props.title}</header>
|
||||
{this.props.excerpt && <p className="excerpt">{this.props.excerpt}</p>}
|
||||
</div>
|
||||
<p>
|
||||
{this.props.context && (
|
||||
<span>
|
||||
<span className="context">{this.props.context}</span>
|
||||
<br />
|
||||
</span>
|
||||
)}
|
||||
<span className="source">{this.props.source}</span>
|
||||
</p>
|
||||
{this.props.context && (
|
||||
<p className="context">{this.props.context}</p>
|
||||
)}
|
||||
</div>
|
||||
<ImpressionStats
|
||||
campaignId={this.props.campaignId}
|
||||
|
|
|
@ -90,6 +90,10 @@ $excerpt-line-height: 20;
|
|||
@include limit-visibile-lines(3, $excerpt-line-height, $excerpt-font-size);
|
||||
}
|
||||
|
||||
.source {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.context,
|
||||
.source {
|
||||
@include dark-theme-only {
|
||||
|
|
|
@ -81,14 +81,14 @@ export class Hero extends React.PureComponent {
|
|||
</div>
|
||||
<div className="meta">
|
||||
<div className="header-and-excerpt">
|
||||
{heroRec.context ? (
|
||||
<p className="context">{heroRec.context}</p>
|
||||
) : (
|
||||
<p className="source">{heroRec.domain}</p>
|
||||
)}
|
||||
<header>{heroRec.title}</header>
|
||||
<p className="excerpt">{heroRec.excerpt}</p>
|
||||
</div>
|
||||
{heroRec.context ? (
|
||||
<p className="context">{heroRec.context}</p>
|
||||
) : (
|
||||
<p className="source">{heroRec.domain}</p>
|
||||
)}
|
||||
</div>
|
||||
<ImpressionStats
|
||||
campaignId={heroRec.campaignId}
|
||||
|
|
|
@ -127,6 +127,11 @@ $card-header-in-hero-line-height: 20;
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.context,
|
||||
.source {
|
||||
margin: 0 0 4px;
|
||||
}
|
||||
|
||||
.context {
|
||||
@include dark-theme-only {
|
||||
color: $teal-10;
|
||||
|
|
|
@ -99,13 +99,13 @@ export const selectLayoutRender = (state, prefs, rickRollCache) => {
|
|||
|
||||
const renderLayout = () => {
|
||||
const renderedLayoutArray = [];
|
||||
for (const row of layout.filter(r => r.components.length)) {
|
||||
for (const row of layout.filter(r => r.components.filter(c => !filterArray.includes(c.type)).length)) {
|
||||
let components = [];
|
||||
renderedLayoutArray.push({
|
||||
...row,
|
||||
components,
|
||||
});
|
||||
for (const component of row.components.filter(c => !filterArray.includes(c.type))) {
|
||||
for (const component of row.components) {
|
||||
if (component.feed) {
|
||||
const spocsConfig = component.spocs;
|
||||
// Are we still waiting on a feed/spocs, render what we have, and bail out early.
|
||||
|
|
|
@ -2038,6 +2038,9 @@ main {
|
|||
margin-bottom: 0; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
|
||||
color: #FFF; }
|
||||
.ds-hero .wrapper .meta .context,
|
||||
.ds-hero .wrapper .meta .source {
|
||||
margin: 0 0 4px; }
|
||||
.ds-hero .wrapper .meta .context {
|
||||
color: #008EA4; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
|
||||
|
@ -2643,6 +2646,8 @@ main {
|
|||
line-height: 20px;
|
||||
max-height: 4.28571em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .source {
|
||||
margin-bottom: 2px; }
|
||||
.ds-card .meta .context,
|
||||
.ds-card .meta .source {
|
||||
font-size: 13px;
|
||||
|
@ -3746,7 +3751,7 @@ a.firstrun-link {
|
|||
.trailhead.syncCohort .trailheadInner {
|
||||
grid-template-columns: 4fr 3fr; }
|
||||
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
|
||||
background: url("../data/content/assets/sync-devices.svg");
|
||||
background: url("../data/content/assets/sync-devices-trailhead.svg");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
@ -3970,6 +3975,12 @@ a.firstrun-link {
|
|||
width: 100%;
|
||||
text-align: center; }
|
||||
|
||||
.inline-onboarding.activity-stream.welcome {
|
||||
overflow: scroll; }
|
||||
|
||||
.inline-onboarding .modalOverlayInner {
|
||||
position: absolute; }
|
||||
|
||||
.inline-onboarding .outer-wrapper {
|
||||
position: relative; }
|
||||
.inline-onboarding .outer-wrapper .prefs-button button {
|
||||
|
@ -3977,10 +3988,3 @@ a.firstrun-link {
|
|||
|
||||
.inline-onboarding .asrouter-toggle {
|
||||
position: absolute; }
|
||||
|
||||
@media (max-height: 760px), (max-width: 924px) {
|
||||
.activity-stream.welcome.inline-onboarding {
|
||||
overflow: auto; }
|
||||
.trailhead {
|
||||
position: absolute;
|
||||
top: 20px; } }
|
||||
|
|
|
@ -2041,6 +2041,9 @@ main {
|
|||
margin-bottom: 0; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
|
||||
color: #FFF; }
|
||||
.ds-hero .wrapper .meta .context,
|
||||
.ds-hero .wrapper .meta .source {
|
||||
margin: 0 0 4px; }
|
||||
.ds-hero .wrapper .meta .context {
|
||||
color: #008EA4; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
|
||||
|
@ -2646,6 +2649,8 @@ main {
|
|||
line-height: 20px;
|
||||
max-height: 4.28571em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .source {
|
||||
margin-bottom: 2px; }
|
||||
.ds-card .meta .context,
|
||||
.ds-card .meta .source {
|
||||
font-size: 13px;
|
||||
|
@ -3749,7 +3754,7 @@ a.firstrun-link {
|
|||
.trailhead.syncCohort .trailheadInner {
|
||||
grid-template-columns: 4fr 3fr; }
|
||||
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
|
||||
background: url("../data/content/assets/sync-devices.svg");
|
||||
background: url("../data/content/assets/sync-devices-trailhead.svg");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
@ -3973,6 +3978,12 @@ a.firstrun-link {
|
|||
width: 100%;
|
||||
text-align: center; }
|
||||
|
||||
.inline-onboarding.activity-stream.welcome {
|
||||
overflow: scroll; }
|
||||
|
||||
.inline-onboarding .modalOverlayInner {
|
||||
position: absolute; }
|
||||
|
||||
.inline-onboarding .outer-wrapper {
|
||||
position: relative; }
|
||||
.inline-onboarding .outer-wrapper .prefs-button button {
|
||||
|
@ -3980,10 +3991,3 @@ a.firstrun-link {
|
|||
|
||||
.inline-onboarding .asrouter-toggle {
|
||||
position: absolute; }
|
||||
|
||||
@media (max-height: 760px), (max-width: 924px) {
|
||||
.activity-stream.welcome.inline-onboarding {
|
||||
overflow: auto; }
|
||||
.trailhead {
|
||||
position: absolute;
|
||||
top: 20px; } }
|
||||
|
|
|
@ -2038,6 +2038,9 @@ main {
|
|||
margin-bottom: 0; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta header {
|
||||
color: #FFF; }
|
||||
.ds-hero .wrapper .meta .context,
|
||||
.ds-hero .wrapper .meta .source {
|
||||
margin: 0 0 4px; }
|
||||
.ds-hero .wrapper .meta .context {
|
||||
color: #008EA4; }
|
||||
[lwt-newtab-brighttext] .ds-hero .wrapper .meta .context {
|
||||
|
@ -2643,6 +2646,8 @@ main {
|
|||
line-height: 20px;
|
||||
max-height: 4.28571em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .source {
|
||||
margin-bottom: 2px; }
|
||||
.ds-card .meta .context,
|
||||
.ds-card .meta .source {
|
||||
font-size: 13px;
|
||||
|
@ -3746,7 +3751,7 @@ a.firstrun-link {
|
|||
.trailhead.syncCohort .trailheadInner {
|
||||
grid-template-columns: 4fr 3fr; }
|
||||
.trailhead.syncCohort .trailheadContent .trailheadBenefits {
|
||||
background: url("../data/content/assets/sync-devices.svg");
|
||||
background: url("../data/content/assets/sync-devices-trailhead.svg");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
@ -3970,6 +3975,12 @@ a.firstrun-link {
|
|||
width: 100%;
|
||||
text-align: center; }
|
||||
|
||||
.inline-onboarding.activity-stream.welcome {
|
||||
overflow: scroll; }
|
||||
|
||||
.inline-onboarding .modalOverlayInner {
|
||||
position: absolute; }
|
||||
|
||||
.inline-onboarding .outer-wrapper {
|
||||
position: relative; }
|
||||
.inline-onboarding .outer-wrapper .prefs-button button {
|
||||
|
@ -3977,10 +3988,3 @@ a.firstrun-link {
|
|||
|
||||
.inline-onboarding .asrouter-toggle {
|
||||
position: absolute; }
|
||||
|
||||
@media (max-height: 760px), (max-width: 924px) {
|
||||
.activity-stream.welcome.inline-onboarding {
|
||||
overflow: auto; }
|
||||
.trailhead {
|
||||
position: absolute;
|
||||
top: 20px; } }
|
||||
|
|
|
@ -197,7 +197,7 @@ const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS :
|
|||
// }
|
||||
const actionTypes = {};
|
||||
|
||||
for (const type of ["ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_OPT_OUT", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PAGE_PRERENDERED", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
|
||||
for (const type of ["ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_OPT_OUT", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PAGE_PRERENDERED", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_PERFORMANCE_EVENT", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "TRAILHEAD_ENROLL_EVENT", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
|
||||
actionTypes[type] = type;
|
||||
} // These are acceptable actions for AS Router messages to have. They can show up
|
||||
// as call-to-action buttons in snippets, onboarding tour, etc.
|
||||
|
@ -2707,7 +2707,7 @@ class ModalOverlayWrapper extends react__WEBPACK_IMPORTED_MODULE_0___default.a.P
|
|||
|
||||
onKeyDown(event) {
|
||||
if (event.key === "Escape") {
|
||||
this.props.onClose();
|
||||
this.props.onClose(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3417,18 +3417,22 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
global.addEventListener("visibilitychange", this.closeModal);
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
closeModal(ev) {
|
||||
global.removeEventListener("visibilitychange", this.closeModal);
|
||||
this.props.document.body.classList.remove("welcome");
|
||||
this.props.document.getElementById("root").removeAttribute("aria-hidden");
|
||||
this.setState({
|
||||
isModalOpen: false
|
||||
});
|
||||
this.revealCards();
|
||||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({
|
||||
event: "SKIPPED_SIGNIN",
|
||||
...this._getFormInfo()
|
||||
}));
|
||||
this.revealCards(); // If closeModal() was triggered by a visibilitychange event, the user actually
|
||||
// submitted the email form so we don't send a SKIPPED_SIGNIN ping.
|
||||
|
||||
if (!ev || ev.type !== "visibilitychange") {
|
||||
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({
|
||||
event: "SKIPPED_SIGNIN",
|
||||
...this._getFormInfo()
|
||||
}));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Report to telemetry additional information about the form submission.
|
||||
|
@ -3556,7 +3560,9 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
}, this.getStringValue(item.text))))), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
|
||||
className: "trailheadLearn",
|
||||
"data-l10n-id": content.learn.text.string_id,
|
||||
href: this.addUtmParams(content.learn.url)
|
||||
href: this.addUtmParams(content.learn.url),
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer"
|
||||
}, this.getStringValue(content.learn.text))), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("div", {
|
||||
className: "trailheadForm"
|
||||
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("h3", {
|
||||
|
@ -3617,7 +3623,7 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
placeholder: this.getStringValue(content.form.email),
|
||||
name: "email",
|
||||
type: "email",
|
||||
required: "true",
|
||||
required: "required",
|
||||
onInvalid: this.onInputInvalid,
|
||||
onChange: this.onInputChange
|
||||
}), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("p", {
|
||||
|
@ -3625,9 +3631,13 @@ class _Trailhead extends react__WEBPACK_IMPORTED_MODULE_4___default.a.PureCompon
|
|||
"data-l10n-id": "onboarding-join-form-legal"
|
||||
}, react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
|
||||
"data-l10n-name": "terms",
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer",
|
||||
href: this.addUtmParams("https://accounts.firefox.com/legal/terms")
|
||||
}), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("a", {
|
||||
"data-l10n-name": "privacy",
|
||||
target: "_blank",
|
||||
rel: "noopener noreferrer",
|
||||
href: this.addUtmParams("https://accounts.firefox.com/legal/privacy")
|
||||
})), react__WEBPACK_IMPORTED_MODULE_4___default.a.createElement("button", {
|
||||
"data-l10n-id": content.form.button.string_id,
|
||||
|
@ -7907,15 +7917,15 @@ class DSCard_DSCard extends external_React_default.a.PureComponent {
|
|||
className: "meta"
|
||||
}, external_React_default.a.createElement("div", {
|
||||
className: "info-wrap"
|
||||
}, external_React_default.a.createElement("header", {
|
||||
}, external_React_default.a.createElement("p", {
|
||||
className: "source"
|
||||
}, this.props.source), external_React_default.a.createElement("header", {
|
||||
className: "title"
|
||||
}, this.props.title), this.props.excerpt && external_React_default.a.createElement("p", {
|
||||
className: "excerpt"
|
||||
}, this.props.excerpt)), external_React_default.a.createElement("p", null, this.props.context && external_React_default.a.createElement("span", null, external_React_default.a.createElement("span", {
|
||||
}, this.props.excerpt)), this.props.context && external_React_default.a.createElement("p", {
|
||||
className: "context"
|
||||
}, this.props.context), external_React_default.a.createElement("br", null)), external_React_default.a.createElement("span", {
|
||||
className: "source"
|
||||
}, this.props.source))), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
|
||||
}, this.props.context)), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
|
||||
campaignId: this.props.campaignId,
|
||||
rows: [{
|
||||
id: this.props.id,
|
||||
|
@ -8295,13 +8305,13 @@ class Hero_Hero extends external_React_default.a.PureComponent {
|
|||
className: "meta"
|
||||
}, external_React_default.a.createElement("div", {
|
||||
className: "header-and-excerpt"
|
||||
}, external_React_default.a.createElement("header", null, heroRec.title), external_React_default.a.createElement("p", {
|
||||
className: "excerpt"
|
||||
}, heroRec.excerpt)), heroRec.context ? external_React_default.a.createElement("p", {
|
||||
}, heroRec.context ? external_React_default.a.createElement("p", {
|
||||
className: "context"
|
||||
}, heroRec.context) : external_React_default.a.createElement("p", {
|
||||
className: "source"
|
||||
}, heroRec.domain)), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
|
||||
}, heroRec.domain), external_React_default.a.createElement("header", null, heroRec.title), external_React_default.a.createElement("p", {
|
||||
className: "excerpt"
|
||||
}, heroRec.excerpt))), external_React_default.a.createElement(ImpressionStats["ImpressionStats"], {
|
||||
campaignId: heroRec.campaignId,
|
||||
rows: [{
|
||||
id: heroRec.id,
|
||||
|
@ -8526,13 +8536,13 @@ const selectLayoutRender = (state, prefs, rickRollCache) => {
|
|||
const renderLayout = () => {
|
||||
const renderedLayoutArray = [];
|
||||
|
||||
for (const row of layout.filter(r => r.components.length)) {
|
||||
for (const row of layout.filter(r => r.components.filter(c => !filterArray.includes(c.type)).length)) {
|
||||
let components = [];
|
||||
renderedLayoutArray.push({ ...row,
|
||||
components
|
||||
});
|
||||
|
||||
for (const component of row.components.filter(c => !filterArray.includes(c.type))) {
|
||||
for (const component of row.components) {
|
||||
if (component.feed) {
|
||||
const spocsConfig = component.spocs; // Are we still waiting on a feed/spocs, render what we have, and bail out early.
|
||||
|
||||
|
@ -11909,7 +11919,7 @@ class CachedIterable {
|
|||
|
||||
}
|
||||
// CONCATENATED MODULE: ./node_modules/fluent/src/fallback.js
|
||||
function _asyncIterator(iterable) { var method; if (typeof Symbol === "function") { if (Symbol.asyncIterator) { method = iterable[Symbol.asyncIterator]; if (method != null) return method.call(iterable); } if (Symbol.iterator) { method = iterable[Symbol.iterator]; if (method != null) return method.call(iterable); } } throw new TypeError("Object is not async iterable"); }
|
||||
function _asyncIterator(iterable) { var method; if (typeof Symbol !== "undefined") { if (Symbol.asyncIterator) { method = iterable[Symbol.asyncIterator]; if (method != null) return method.call(iterable); } if (Symbol.iterator) { method = iterable[Symbol.iterator]; if (method != null) return method.call(iterable); } } throw new TypeError("Object is not async iterable"); }
|
||||
|
||||
/*
|
||||
* @overview
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
После Ширина: | Высота: | Размер: 12 KiB |
|
@ -1053,3 +1053,20 @@ This reports a failure in the Remote Settings loader to load messages for Activi
|
|||
"value": "REMOTE_PROVIDER_ID"
|
||||
}
|
||||
```
|
||||
|
||||
## Trailhead experiment enrollment ping
|
||||
|
||||
This reports an enrollment ping when a user gets enrolled in a Trailhead experiment. Note that this ping is only collected through the Mozilla Events telemetry pipeline.
|
||||
|
||||
```js
|
||||
{
|
||||
"category": "activity_stream",
|
||||
"method": "enroll",
|
||||
"object": "preference_study"
|
||||
"value": "activity-stream-firstup-trailhead-interrupts",
|
||||
"extra_keys": {
|
||||
"experimentType": "as-firstrun",
|
||||
"branch": ["supercharge" | "join" | "sync" | "privacy" ...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
|
@ -42,6 +42,7 @@ const TRAILHEAD_CONFIG = {
|
|||
OVERRIDE_PREF: "trailhead.firstrun.branches",
|
||||
DID_SEE_ABOUT_WELCOME_PREF: "trailhead.firstrun.didSeeAboutWelcome",
|
||||
INTERRUPTS_EXPERIMENT_PREF: "trailhead.firstrun.interruptsExperiment",
|
||||
TRIPLETS_ENROLLED_PREF: "trailhead.firstrun.tripletsEnrolled",
|
||||
BRANCHES: {
|
||||
interrupts: [
|
||||
["control"],
|
||||
|
@ -732,6 +733,14 @@ class _ASRouter {
|
|||
return {experiment, interrupt, triplet};
|
||||
}
|
||||
|
||||
// Dispatch a TRAILHEAD_ENROLL_EVENT action
|
||||
_sendTrailheadEnrollEvent(data) {
|
||||
this.dispatchToAS({
|
||||
type: at.TRAILHEAD_ENROLL_EVENT,
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
async setupTrailhead() {
|
||||
// Don't initialize
|
||||
if (this.state.trailheadInitialized || !Services.prefs.getBoolPref(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF, false)) {
|
||||
|
@ -742,18 +751,28 @@ class _ASRouter {
|
|||
await this.setState({trailheadInitialized: true, trailheadInterrupt: interrupt, trailheadTriplet: triplet});
|
||||
|
||||
if (experiment) {
|
||||
// In order for ping centre to pick this up, it MUST contain a substring activity-stream
|
||||
const experimentName = `activity-stream-firstrun-trailhead-${experiment}`;
|
||||
|
||||
TelemetryEnvironment.setExperimentActive(
|
||||
// In order for ping centre to pick this up, it MUST start with activity-stream
|
||||
`activity-stream-firstrun-trailhead-${experiment}`,
|
||||
experimentName,
|
||||
experiment === "interrupts" ? interrupt : triplet,
|
||||
{type: "as-firstrun"}
|
||||
);
|
||||
|
||||
// On the first time setting the interrupts experiment, expose the branch
|
||||
// for normandy to target for survey study.
|
||||
// for normandy to target for survey study, and send out the enrollment ping.
|
||||
if (experiment === "interrupts" &&
|
||||
!Services.prefs.prefHasUserValue(TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF)) {
|
||||
Services.prefs.setStringPref(TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF, interrupt);
|
||||
this._sendTrailheadEnrollEvent({experiment: experimentName, type: "as-firstrun", branch: interrupt});
|
||||
}
|
||||
|
||||
// On the first time setting the triplets experiment, send out the enrollment ping.
|
||||
if (experiment === "triplets" &&
|
||||
!Services.prefs.getBoolPref(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, false)) {
|
||||
Services.prefs.setBoolPref(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, true);
|
||||
this._sendTrailheadEnrollEvent({experiment: experimentName, type: "as-firstrun", branch: triplet});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -343,7 +343,7 @@ const ONBOARDING_MESSAGES = async () => ([
|
|||
label: {string_id: "onboarding-send-tabs-button"},
|
||||
action: {
|
||||
type: "OPEN_URL",
|
||||
data: {args: "https://blog.mozilla.org/firefox/send-tabs-a-better-way/", where: "tabshifted"},
|
||||
data: {args: "https://support.mozilla.org/kb/send-tab-firefox-desktop-mobile", where: "tabshifted"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -663,6 +663,14 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
this.sendEvent(this.createUndesiredEvent(action));
|
||||
}
|
||||
|
||||
handleTrailheadEnrollEvent(action) {
|
||||
// Unlike `sendUTEvent`, we always send the event if AS's telemetry is enabled
|
||||
// regardless of `this.eventTelemetryEnabled`.
|
||||
if (this.telemetryEnabled) {
|
||||
this.utEvents.sendTrailheadEnrollEvent(action.data);
|
||||
}
|
||||
}
|
||||
|
||||
async sendPageTakeoverData() {
|
||||
if (this.telemetryEnabled) {
|
||||
const value = {};
|
||||
|
@ -764,6 +772,9 @@ this.TelemetryFeed = class TelemetryFeed {
|
|||
case at.TELEMETRY_PERFORMANCE_EVENT:
|
||||
this.sendEvent(this.createPerformanceEvent(action));
|
||||
break;
|
||||
case at.TRAILHEAD_ENROLL_EVENT:
|
||||
this.handleTrailheadEnrollEvent(action);
|
||||
break;
|
||||
case at.UNINIT:
|
||||
this.uninit();
|
||||
break;
|
||||
|
|
|
@ -18,6 +18,7 @@ this.UTEventReporting = class UTEventReporting {
|
|||
Services.telemetry.setEventRecordingEnabled("activity_stream", true);
|
||||
this.sendUserEvent = this.sendUserEvent.bind(this);
|
||||
this.sendSessionEndEvent = this.sendSessionEndEvent.bind(this);
|
||||
this.sendTrailheadEnrollEvent = this.sendTrailheadEnrollEvent.bind(this);
|
||||
}
|
||||
|
||||
_createExtras(data) {
|
||||
|
@ -53,6 +54,19 @@ this.UTEventReporting = class UTEventReporting {
|
|||
this._createExtras(data));
|
||||
}
|
||||
|
||||
sendTrailheadEnrollEvent(data) {
|
||||
Services.telemetry.recordEvent(
|
||||
"activity_stream",
|
||||
"enroll",
|
||||
"preference_study",
|
||||
data.experiment,
|
||||
{
|
||||
experimentType: data.type,
|
||||
branch: data.branch,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
uninit() {
|
||||
Services.telemetry.setEventRecordingEnabled("activity_stream", false);
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ menu_action_open_new_window=פתיחה בחלון חדש
|
|||
menu_action_open_private_window=פתיחה בלשונית פרטית חדשה
|
||||
menu_action_dismiss=הסרה
|
||||
menu_action_delete=מחיקה מההיסטוריה
|
||||
menu_action_pin=הצמדה
|
||||
menu_action_unpin=ביטול הצמדה
|
||||
menu_action_pin=נעיצה
|
||||
menu_action_unpin=ביטול נעיצה
|
||||
confirm_history_delete_p1=למחוק כל עותק של העמוד הזה מההיסטוריה שלך?
|
||||
# LOCALIZATION NOTE (confirm_history_delete_notice_p2): this string is displayed in
|
||||
# the same dialog as confirm_history_delete_p1. "This action" refers to deleting a
|
||||
|
@ -93,6 +93,7 @@ prefs_home_header=תוכן מסך הבית של Firefox
|
|||
prefs_home_description=בחירת תוכן שיוצג במסך הבית של Firefox.
|
||||
|
||||
prefs_content_discovery_header=מסך הבית של Firefox
|
||||
|
||||
prefs_content_discovery_description=גילוי תוכן במסך הבית של Firefox מאפשר לך לגלות מאמרים רלוונטים ובאיכות גבוהה מכל רחבי הרשת.
|
||||
prefs_content_discovery_button=השבתת גילוי תוכן
|
||||
|
||||
|
@ -151,6 +152,7 @@ pocket_read_even_more=צפייה בחדשות נוספות
|
|||
pocket_more_reccommendations=המלצות נוספות
|
||||
pocket_how_it_works=איך זה עובד
|
||||
pocket_cta_button=קבלת Pocket
|
||||
pocket_cta_text=שמירת הסיפורים שאהבת ב־Pocket על מנת למלא את מחשבתך בקריאה מרתקת.
|
||||
|
||||
highlights_empty_state=ניתן להתחיל בגלישה ואנו נציג בפניך מספר כתבות, סרטונים ועמודים שונים מעולים בהם ביקרת לאחרונה או שהוספת לסימניות.
|
||||
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
|
||||
|
|
|
@ -102,8 +102,8 @@ section_menu_action_move_down=Sposta giù
|
|||
section_menu_action_privacy_notice=Informativa sulla privacy
|
||||
firstrun_title=Porta Firefox con te
|
||||
firstrun_content=Ritrova segnalibri, cronologia, password e altre impostazioni su tutti i tuoi dispositivi.
|
||||
firstrun_learn_more_link=Scopri di più sull’account Firefox
|
||||
firstrun_form_header=Inserisci email
|
||||
firstrun_learn_more_link=Ulteriori informazioni sull’account Firefox
|
||||
firstrun_form_header=Inserisci la tua email
|
||||
firstrun_form_sub_header=per utilizzare Firefox Sync.
|
||||
firstrun_email_input_placeholder=Email
|
||||
firstrun_invalid_input=Inserire un indirizzo email valido
|
||||
|
|
|
@ -93,6 +93,7 @@ prefs_home_header=Firefox 首頁內容
|
|||
prefs_home_description=選擇要在您的 Firefox 首頁顯示哪些內容。
|
||||
|
||||
prefs_content_discovery_header=Firefox 首頁
|
||||
|
||||
prefs_content_discovery_description=Firefox Home 的內容探索功能可隨您上網,為您尋找高品質而與您有關的文章。
|
||||
prefs_content_discovery_button=關閉內容探索功能
|
||||
|
||||
|
@ -190,7 +191,7 @@ section_menu_action_privacy_notice=隱私權公告
|
|||
# LOCALIZATION NOTE (firstrun_*). These strings are displayed only once, on the
|
||||
# firstrun of the browser, they give an introduction to Firefox and Sync.
|
||||
firstrun_title=Firefox 隨身帶著走
|
||||
firstrun_content=在您的任何裝置上取得書籤、瀏覽紀錄、密碼及其他設定。
|
||||
firstrun_content=在您的各種裝置上同步書籤、瀏覽紀錄、登入資訊及其他設定。
|
||||
firstrun_learn_more_link=了解 Firefox Accounts 的更多資訊
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_form_header and firstrun_form_sub_header):
|
||||
|
|
|
@ -17,8 +17,8 @@ window.gActivityStreamStrings = {
|
|||
"menu_action_open_private_window": "פתיחה בלשונית פרטית חדשה",
|
||||
"menu_action_dismiss": "הסרה",
|
||||
"menu_action_delete": "מחיקה מההיסטוריה",
|
||||
"menu_action_pin": "הצמדה",
|
||||
"menu_action_unpin": "ביטול הצמדה",
|
||||
"menu_action_pin": "נעיצה",
|
||||
"menu_action_unpin": "ביטול נעיצה",
|
||||
"confirm_history_delete_p1": "למחוק כל עותק של העמוד הזה מההיסטוריה שלך?",
|
||||
"confirm_history_delete_notice_p2": "לא ניתן לבטל פעולה זו.",
|
||||
"menu_action_save_to_pocket": "שמירה ל־Pocket",
|
||||
|
@ -78,7 +78,7 @@ window.gActivityStreamStrings = {
|
|||
"pocket_more_reccommendations": "המלצות נוספות",
|
||||
"pocket_how_it_works": "איך זה עובד",
|
||||
"pocket_cta_button": "קבלת Pocket",
|
||||
"pocket_cta_text": "Save the stories you love in Pocket, and fuel your mind with fascinating reads.",
|
||||
"pocket_cta_text": "שמירת הסיפורים שאהבת ב־Pocket על מנת למלא את מחשבתך בקריאה מרתקת.",
|
||||
"highlights_empty_state": "ניתן להתחיל בגלישה ואנו נציג בפניך מספר כתבות, סרטונים ועמודים שונים מעולים בהם ביקרת לאחרונה או שהוספת לסימניות.",
|
||||
"topstories_empty_state": "התעדכנת בכל הסיפורים. כדאי לנסות שוב מאוחר יותר כדי לקבל עוד סיפורים מובילים מאת {provider}. לא רוצה לחכות? ניתן לבחור נושא נפוץ כדי למצוא עוד סיפורים נפלאים מרחבי הרשת.",
|
||||
"error_fallback_default_info": "אופס, משהו השתבש בעת טעינת התוכן הזה.",
|
||||
|
|
|
@ -95,8 +95,8 @@ window.gActivityStreamStrings = {
|
|||
"section_menu_action_privacy_notice": "Informativa sulla privacy",
|
||||
"firstrun_title": "Porta Firefox con te",
|
||||
"firstrun_content": "Ritrova segnalibri, cronologia, password e altre impostazioni su tutti i tuoi dispositivi.",
|
||||
"firstrun_learn_more_link": "Scopri di più sull’account Firefox",
|
||||
"firstrun_form_header": "Inserisci email",
|
||||
"firstrun_learn_more_link": "Ulteriori informazioni sull’account Firefox",
|
||||
"firstrun_form_header": "Inserisci la tua email",
|
||||
"firstrun_form_sub_header": "per utilizzare Firefox Sync.",
|
||||
"firstrun_email_input_placeholder": "Email",
|
||||
"firstrun_invalid_input": "Inserire un indirizzo email valido",
|
||||
|
|
|
@ -94,7 +94,7 @@ window.gActivityStreamStrings = {
|
|||
"section_menu_action_move_down": "下移",
|
||||
"section_menu_action_privacy_notice": "隱私權公告",
|
||||
"firstrun_title": "Firefox 隨身帶著走",
|
||||
"firstrun_content": "在您的任何裝置上取得書籤、瀏覽紀錄、密碼及其他設定。",
|
||||
"firstrun_content": "在您的各種裝置上同步書籤、瀏覽紀錄、登入資訊及其他設定。",
|
||||
"firstrun_learn_more_link": "了解 Firefox Accounts 的更多資訊",
|
||||
"firstrun_form_header": "輸入您的電子郵件地址",
|
||||
"firstrun_form_sub_header": "繼續前往 Firefox Sync",
|
||||
|
|
|
@ -247,6 +247,19 @@ export const UTSessionPing = Joi.array().items(
|
|||
eventsTelemetryExtraKeys
|
||||
);
|
||||
|
||||
export const trailheadEnrollExtraKeys = Joi.object().keys({
|
||||
experimentType: Joi.string().required(),
|
||||
branch: Joi.string().required(),
|
||||
}).options({allowUnknown: false});
|
||||
|
||||
export const UTTrailheadEnrollPing = Joi.array().items(
|
||||
Joi.string().required().valid("activity_stream"),
|
||||
Joi.string().required().valid("enroll"),
|
||||
Joi.string().required().valid("preference_study"),
|
||||
Joi.string().required(),
|
||||
trailheadEnrollExtraKeys
|
||||
);
|
||||
|
||||
export function chaiAssertions(_chai, utils) {
|
||||
const {Assertion} = _chai;
|
||||
|
||||
|
|
|
@ -1601,13 +1601,18 @@ describe("ASRouter", () => {
|
|||
describe(".setupTrailhead", () => {
|
||||
let getBoolPrefStub;
|
||||
let setStringPrefStub;
|
||||
let setBoolPrefStub;
|
||||
|
||||
beforeEach(() => {
|
||||
getBoolPrefStub = sandbox.stub(global.Services.prefs, "getBoolPref").withArgs(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF).returns(true);
|
||||
getBoolPrefStub = sandbox.stub(global.Services.prefs, "getBoolPref");
|
||||
getBoolPrefStub.withArgs(TRAILHEAD_CONFIG.DID_SEE_ABOUT_WELCOME_PREF).returns(true);
|
||||
getBoolPrefStub.withArgs(TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF).returns(false);
|
||||
setStringPrefStub = sandbox.stub(global.Services.prefs, "setStringPref");
|
||||
setBoolPrefStub = sandbox.stub(global.Services.prefs, "setBoolPref");
|
||||
});
|
||||
|
||||
const configWithExperiment = {experiment: "interrupts", interrupt: "join", triplet: "privacy"};
|
||||
const configWithInterruptsExperiment = {experiment: "interrupts", interrupt: "join", triplet: "privacy"};
|
||||
const configWithTripletsExperiment = {experiment: "triplets", interrupt: "join", triplet: "privacy"};
|
||||
const configWithoutExperiment = {experiment: "", interrupt: "control", triplet: ""};
|
||||
|
||||
it("should generates an experiment/branch configuration and update Router.state", async () => {
|
||||
|
@ -1637,14 +1642,35 @@ describe("ASRouter", () => {
|
|||
sandbox.spy(Router, "setState");
|
||||
assert.notCalled(Router.setState);
|
||||
});
|
||||
it("should set active experiment if one is defined", async () => {
|
||||
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithExperiment);
|
||||
it("should set active interrupts experiment if one is defined", async () => {
|
||||
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithInterruptsExperiment);
|
||||
sandbox.stub(global.TelemetryEnvironment, "setExperimentActive");
|
||||
sandbox.spy(Router, "_sendTrailheadEnrollEvent");
|
||||
|
||||
await Router.setupTrailhead();
|
||||
|
||||
assert.calledOnce(global.TelemetryEnvironment.setExperimentActive);
|
||||
assert.calledWith(setStringPrefStub, TRAILHEAD_CONFIG.INTERRUPTS_EXPERIMENT_PREF, "join");
|
||||
assert.calledWith(Router._sendTrailheadEnrollEvent, {
|
||||
experiment: "activity-stream-firstrun-trailhead-interrupts",
|
||||
type: "as-firstrun",
|
||||
branch: "join",
|
||||
});
|
||||
});
|
||||
it("should set active triplets experiment if one is defined", async () => {
|
||||
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithTripletsExperiment);
|
||||
sandbox.stub(global.TelemetryEnvironment, "setExperimentActive");
|
||||
sandbox.spy(Router, "_sendTrailheadEnrollEvent");
|
||||
|
||||
await Router.setupTrailhead();
|
||||
|
||||
assert.calledOnce(global.TelemetryEnvironment.setExperimentActive);
|
||||
assert.calledWith(setBoolPrefStub, TRAILHEAD_CONFIG.TRIPLETS_ENROLLED_PREF, true);
|
||||
assert.calledWith(Router._sendTrailheadEnrollEvent, {
|
||||
experiment: "activity-stream-firstrun-trailhead-triplets",
|
||||
type: "as-firstrun",
|
||||
branch: "privacy",
|
||||
});
|
||||
});
|
||||
it("should not set an active experiment if no experiment is defined", async () => {
|
||||
sandbox.stub(Router, "_generateTrailheadBranches").resolves(configWithoutExperiment);
|
||||
|
|
|
@ -63,6 +63,11 @@ describe("<Trailhead>", () => {
|
|||
assert.calledWith(dispatch, ac.UserEvent({event: at.SKIPPED_SIGNIN, value: {has_flow_params: false}}));
|
||||
});
|
||||
|
||||
it("should NOT emit UserEvent SKIPPED_SIGNIN when closeModal is triggered by visibilitychange event", () => {
|
||||
wrapper.instance().closeModal({type: "visibilitychange"});
|
||||
assert.notCalled(dispatch);
|
||||
});
|
||||
|
||||
it("should emit UserEvent SUBMIT_EMAIL when you submit the form", () => {
|
||||
let form = wrapper.find("form");
|
||||
assert.ok(form.exists());
|
||||
|
|
|
@ -353,4 +353,23 @@ describe("selectLayoutRender", () => {
|
|||
|
||||
assert.deepEqual(layoutRender[0].components[2].data.recommendations[0], {name: "rec", pos: 0});
|
||||
});
|
||||
it("should not render a row if no components exist after filter in that row", () => {
|
||||
const fakeLayout = [{
|
||||
width: 3,
|
||||
components: [
|
||||
{type: "TopSites"},
|
||||
],
|
||||
}, {
|
||||
width: 3,
|
||||
components: [
|
||||
{type: "Message"},
|
||||
],
|
||||
}];
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
|
||||
|
||||
const {layoutRender} = selectLayoutRender(store.getState().DiscoveryStream, {"feeds.topsites": true}, []);
|
||||
|
||||
assert.equal(layoutRender[0].components[0].type, "TopSites");
|
||||
assert.equal(layoutRender[1], undefined);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,7 +29,12 @@ describe("TelemetryFeed", () => {
|
|||
let fakeHomePage;
|
||||
let fakeExtensionSettingsStore;
|
||||
class PingCentre {sendPing() {} uninit() {} sendStructuredIngestionPing() {}}
|
||||
class UTEventReporting {sendUserEvent() {} sendSessionEndEvent() {} uninit() {}}
|
||||
class UTEventReporting {
|
||||
sendUserEvent() {}
|
||||
sendSessionEndEvent() {}
|
||||
sendTrailheadEnrollEvent() {}
|
||||
uninit() {}
|
||||
}
|
||||
class PerfService {
|
||||
getMostRecentAbsMarkStartByName() { return 1234; }
|
||||
mark() {}
|
||||
|
@ -1132,6 +1137,15 @@ describe("TelemetryFeed", () => {
|
|||
assert.calledWith(eventCreator, action.data);
|
||||
assert.calledWith(sendEvent, eventCreator.returnValue);
|
||||
});
|
||||
it("should call .handleTrailheadEnrollEvent on a TRAILHEAD_ENROLL_EVENT action", () => {
|
||||
const data = {experiment: "foo", type: "bar", branch: "baz"};
|
||||
const action = {type: at.TRAILHEAD_ENROLL_EVENT, data};
|
||||
sandbox.spy(instance, "handleTrailheadEnrollEvent");
|
||||
|
||||
instance.onAction(action);
|
||||
|
||||
assert.calledWith(instance.handleTrailheadEnrollEvent, action);
|
||||
});
|
||||
});
|
||||
describe("#handlePagePrerendered", () => {
|
||||
it("should not throw if there is no session for the given port ID", () => {
|
||||
|
@ -1363,4 +1377,26 @@ describe("TelemetryFeed", () => {
|
|||
assert.equal(url, `${fakeEndpoint}/testPingType/1/${fakeUUIDWithoutBraces}`);
|
||||
});
|
||||
});
|
||||
describe("#handleTrailheadEnrollEvent", () => {
|
||||
it("should send a TRAILHEAD_ENROLL_EVENT if the telemetry is enabled", () => {
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = true;
|
||||
const data = {experiment: "foo", type: "bar", branch: "baz"};
|
||||
instance = new TelemetryFeed();
|
||||
sandbox.stub(instance.utEvents, "sendTrailheadEnrollEvent");
|
||||
|
||||
instance.handleTrailheadEnrollEvent({data});
|
||||
|
||||
assert.calledWith(instance.utEvents.sendTrailheadEnrollEvent, data);
|
||||
});
|
||||
it("should not send TRAILHEAD_ENROLL_EVENT if the telemetry is disabled", () => {
|
||||
FakePrefs.prototype.prefs[TELEMETRY_PREF] = false;
|
||||
const data = {experiment: "foo", type: "bar", branch: "baz"};
|
||||
instance = new TelemetryFeed();
|
||||
sandbox.stub(instance.utEvents, "sendTrailheadEnrollEvent");
|
||||
|
||||
instance.handleTrailheadEnrollEvent({data});
|
||||
|
||||
assert.notCalled(instance.utEvents.sendTrailheadEnrollEvent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
UTSessionPing,
|
||||
UTTrailheadEnrollPing,
|
||||
UTUserEventPing,
|
||||
} from "test/schemas/pings";
|
||||
import {GlobalOverrider} from "test/unit/utils";
|
||||
|
@ -40,6 +41,17 @@ const FAKE_SESSION_PING_UT = [
|
|||
"page": "about:newtab",
|
||||
},
|
||||
];
|
||||
const FAKE_TRAILHEAD_ENROLL_EVENT = {
|
||||
experiment: "activity-stream-trailhead-firstrun-interrupts",
|
||||
type: "as-firstrun",
|
||||
branch: "supercharge",
|
||||
};
|
||||
const FAKE_TRAILHEAD_ENROLL_EVENT_UT = [
|
||||
"activity_stream", "enroll", "preference_study", "activity-stream-trailhead-firstrun-interrupts", {
|
||||
experimentType: "as-firstrun",
|
||||
branch: "supercharge",
|
||||
},
|
||||
];
|
||||
|
||||
describe("UTEventReporting", () => {
|
||||
let globals;
|
||||
|
@ -79,6 +91,16 @@ describe("UTEventReporting", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("#sendTrailheadEnrollEvent()", () => {
|
||||
it("should queue up the correct data to send to Events Telemetry", async () => {
|
||||
utEvents.sendTrailheadEnrollEvent(FAKE_TRAILHEAD_ENROLL_EVENT);
|
||||
assert.calledWithExactly(global.Services.telemetry.recordEvent, ...FAKE_TRAILHEAD_ENROLL_EVENT_UT);
|
||||
|
||||
let ping = global.Services.telemetry.recordEvent.firstCall.args;
|
||||
assert.validate(ping, UTTrailheadEnrollPing);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#uninit()", () => {
|
||||
it("should call setEventRecordingEnabled with a false value", () => {
|
||||
assert.equal(global.Services.telemetry.setEventRecordingEnabled.firstCall.args[0], "activity_stream");
|
||||
|
|
Загрузка…
Ссылка в новой задаче