diff --git a/.eslintignore b/.eslintignore index 0bd1e7a1d584..3a4fa11ef33b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -55,7 +55,6 @@ browser/components/pocket/content/panels/js/main.bundle.js !browser/components/storybook/.storybook/*.js # Ignore newtab files -browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js browser/components/newtab/data/ browser/components/newtab/logs/ diff --git a/browser/components/aboutwelcome/.eslintrc.js b/browser/components/aboutwelcome/.eslintrc.js new file mode 100644 index 000000000000..a12110d0fe45 --- /dev/null +++ b/browser/components/aboutwelcome/.eslintrc.js @@ -0,0 +1,173 @@ +/* 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/. */ + +module.exports = { + // When adding items to this file please check for effects on sub-directories. + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + plugins: ["import", "react", "jsx-a11y"], + settings: { + react: { + version: "16.2.0", + }, + }, + extends: ["plugin:jsx-a11y/recommended"], + overrides: [ + { + // Only mark the files as modules which are actually modules. + files: ["content-src/**"], + parserOptions: { + sourceType: "module", + }, + }, + { + // These files use fluent-dom to insert content + files: [ + "content-src/components/Zap.jsx", + "content-src/components/MultiStageAboutWelcome.jsx", + "content-src/components/MultiStageScreen.jsx", + "content-src/components/MultiStageProtonScreen.jsx", + "content-src/components/MultiSelect.jsx", + "content-src/components/ReturnToAMO.jsx", + ], + rules: { + "jsx-a11y/anchor-has-content": "off", + "jsx-a11y/heading-has-content": "off", + "jsx-a11y/label-has-associated-control": "off", + "jsx-a11y/no-onchange": "off", + }, + }, + { + files: ["./*.js", "content-src/**"], + env: { + node: true, + }, + }, + { + // Use a configuration that's appropriate for modules, workers and + // non-production files. + files: ["tests/**"], + rules: { + "no-implicit-globals": "off", + }, + }, + { + files: ["content-src/**"], + rules: { + // Disallow commonjs in these directories. + "import/no-commonjs": 2, + // Allow JSX with arrow functions. + "react/jsx-no-bind": 0, + }, + }, + { + files: "tests/**", + rules: { + "func-name-matching": 0, + "lines-between-class-members": 0, + "require-await": 0, + }, + }, + ], + rules: { + "fetch-options/no-fetch-credentials": "error", + + "react/jsx-boolean-value": ["error", "always"], + "react/jsx-key": "error", + "react/jsx-no-bind": "error", + "react/jsx-no-comment-textnodes": "error", + "react/jsx-no-duplicate-props": "error", + "react/jsx-no-target-blank": "error", + "react/jsx-no-undef": "error", + "react/jsx-pascal-case": "error", + "react/jsx-uses-react": "error", + "react/jsx-uses-vars": "error", + "react/no-access-state-in-setstate": "error", + "react/no-danger": "error", + "react/no-deprecated": "error", + "react/no-did-mount-set-state": "error", + "react/no-did-update-set-state": "error", + "react/no-direct-mutation-state": "error", + "react/no-is-mounted": "error", + "react/no-unknown-property": "error", + "react/require-render-return": "error", + + "accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }], + "array-callback-return": "error", + "block-scoped-var": "error", + "consistent-this": ["error", "use-bind"], + eqeqeq: "error", + "for-direction": "error", + "func-name-matching": "error", + "getter-return": "error", + "guard-for-in": "error", + "handle-callback-err": "error", + "lines-between-class-members": "error", + "max-depth": ["error", 4], + "max-nested-callbacks": ["error", 4], + "max-params": ["error", 6], + "max-statements": ["error", 50], + "max-statements-per-line": ["error", { max: 2 }], + "new-cap": ["error", { newIsCap: true, capIsNew: false }], + "no-alert": "error", + "no-buffer-constructor": "error", + "no-console": ["error", { allow: ["error"] }], + "no-div-regex": "error", + "no-duplicate-imports": "error", + "no-eq-null": "error", + "no-extend-native": "error", + "no-extra-label": "error", + "no-implicit-coercion": ["error", { allow: ["!!"] }], + "no-implicit-globals": "error", + "no-loop-func": "error", + "no-mixed-requires": "error", + "no-multi-assign": "error", + "no-multi-str": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-require": "error", + "no-octal-escape": "error", + "no-param-reassign": "error", + "no-path-concat": "error", + "no-process-exit": "error", + "no-proto": "error", + "no-prototype-builtins": "error", + "no-return-assign": ["error", "except-parens"], + "no-script-url": "error", + "no-shadow": "error", + "no-template-curly-in-string": "error", + "no-undef-init": "error", + "no-unmodified-loop-condition": "error", + "no-unused-expressions": "error", + "no-use-before-define": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-useless-rename": "error", + "no-var": "error", + "no-void": ["error", { allowAsStatement: true }], + "one-var": ["error", "never"], + "operator-assignment": ["error", "always"], + "prefer-destructuring": [ + "error", + { + AssignmentExpression: { array: true }, + VariableDeclarator: { array: true, object: true }, + }, + ], + "prefer-numeric-literals": "error", + "prefer-promise-reject-errors": "error", + "prefer-rest-params": "error", + "prefer-spread": "error", + "prefer-template": "error", + radix: ["error", "always"], + "require-await": "error", + "sort-vars": "error", + "symbol-description": "error", + "vars-on-top": "error", + yoda: ["error", "never"], + }, +}; diff --git a/browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx b/browser/components/aboutwelcome/content-src/aboutwelcome.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx rename to browser/components/aboutwelcome/content-src/aboutwelcome.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/aboutwelcome.scss b/browser/components/aboutwelcome/content-src/aboutwelcome.scss similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/aboutwelcome.scss rename to browser/components/aboutwelcome/content-src/aboutwelcome.scss diff --git a/browser/components/newtab/content-src/aboutwelcome/components/AdditionalCTA.jsx b/browser/components/aboutwelcome/content-src/components/AdditionalCTA.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/AdditionalCTA.jsx rename to browser/components/aboutwelcome/content-src/components/AdditionalCTA.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/AddonsPicker.jsx b/browser/components/aboutwelcome/content-src/components/AddonsPicker.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/AddonsPicker.jsx rename to browser/components/aboutwelcome/content-src/components/AddonsPicker.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/CTAParagraph.jsx b/browser/components/aboutwelcome/content-src/components/CTAParagraph.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/CTAParagraph.jsx rename to browser/components/aboutwelcome/content-src/components/CTAParagraph.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/EmbeddedMigrationWizard.jsx b/browser/components/aboutwelcome/content-src/components/EmbeddedMigrationWizard.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/EmbeddedMigrationWizard.jsx rename to browser/components/aboutwelcome/content-src/components/EmbeddedMigrationWizard.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/HelpText.jsx b/browser/components/aboutwelcome/content-src/components/HelpText.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/HelpText.jsx rename to browser/components/aboutwelcome/content-src/components/HelpText.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/HeroImage.jsx b/browser/components/aboutwelcome/content-src/components/HeroImage.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/HeroImage.jsx rename to browser/components/aboutwelcome/content-src/components/HeroImage.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/LanguageSwitcher.jsx b/browser/components/aboutwelcome/content-src/components/LanguageSwitcher.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/LanguageSwitcher.jsx rename to browser/components/aboutwelcome/content-src/components/LanguageSwitcher.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/LinkParagraph.jsx b/browser/components/aboutwelcome/content-src/components/LinkParagraph.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/LinkParagraph.jsx rename to browser/components/aboutwelcome/content-src/components/LinkParagraph.jsx diff --git a/browser/components/aboutwelcome/content-src/components/MRColorways.jsx b/browser/components/aboutwelcome/content-src/components/MRColorways.jsx new file mode 100644 index 000000000000..758e6ddc4afe --- /dev/null +++ b/browser/components/aboutwelcome/content-src/components/MRColorways.jsx @@ -0,0 +1,200 @@ +/* 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/. */ + +import React, { useState, useEffect } from "react"; +import { Localized } from "./MSLocalized"; + +export const ColorwayDescription = props => { + const { colorway } = props; + if (!colorway) { + return null; + } + const { label, description } = colorway; + return ( + +
+ + ); +}; + +// Return colorway as "default" for default theme variations Automatic, Light, Dark, +// Alpenglow theme and legacy colorways which is not supported in Colorway picker. +// For themes other then default, theme names exist in +// format colorway-variationId inside LIGHT_WEIGHT_THEMES in AboutWelcomeParent +export function computeColorWay(themeName, systemVariations) { + return !themeName || + themeName === "alpenglow" || + systemVariations.includes(themeName) + ? "default" + : themeName.split("-")[0]; +} + +// Set variationIndex based off activetheme value e.g. 'light', 'expressionist-soft' +export function computeVariationIndex( + themeName, + systemVariations, + variations, + defaultVariationIndex +) { + // Check if themeName is in systemVariations, if yes choose variationIndex by themeName + let index = systemVariations.findIndex(theme => theme === themeName); + if (index >= 0) { + return index; + } + + // If themeName is one of the colorways, select variation index from colorways + let variation = themeName?.split("-")[1]; + index = variations.findIndex(element => element === variation); + if (index >= 0) { + return index; + } + return defaultVariationIndex; +} + +export function Colorways(props) { + let { + colorways, + darkVariation, + defaultVariationIndex, + systemVariations, + variations, + } = props.content.tiles; + let hasReverted = false; + + // Active theme id from JSON e.g. "expressionist" + const activeId = computeColorWay(props.activeTheme, systemVariations); + const [colorwayId, setState] = useState(activeId); + const [variationIndex, setVariationIndex] = useState(defaultVariationIndex); + + function revertToDefaultTheme() { + if (hasReverted) { + return; + } + + // Spoofing an event with current target value of "navigate_away" + // helps the handleAction method to read the colorways theme as "revert" + // which causes the initial theme to be activated. + // The "navigate_away" action is set in content in the colorways screen JSON config. + // Any value in the JSON for theme will work, provided it is not ``. + const event = { + currentTarget: { + value: "navigate_away", + }, + }; + props.handleAction(event); + hasReverted = true; + } + + // Revert to default theme if the user navigates away from the page or spotlight modal + // before clicking on the primary button to officially set theme. + useEffect(() => { + addEventListener("beforeunload", revertToDefaultTheme); + addEventListener("pagehide", revertToDefaultTheme); + + return () => { + removeEventListener("beforeunload", revertToDefaultTheme); + removeEventListener("pagehide", revertToDefaultTheme); + }; + }); + // Update state any time activeTheme changes. + useEffect(() => { + setState(computeColorWay(props.activeTheme, systemVariations)); + setVariationIndex( + computeVariationIndex( + props.activeTheme, + systemVariations, + variations, + defaultVariationIndex + ) + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [props.activeTheme]); + + //select a random colorway + useEffect(() => { + //We don't want the default theme to be selected + const randomIndex = Math.floor(Math.random() * (colorways.length - 1)) + 1; + const randomColorwayId = colorways[randomIndex].id; + + // Change the variation to be the dark variation if configured and dark. + // Additional colorway changes will remain dark while system is unchanged. + if ( + darkVariation !== undefined && + window.matchMedia("(prefers-color-scheme: dark)").matches + ) { + variations[variationIndex] = variations[darkVariation]; + } + const value = `${randomColorwayId}-${variations[variationIndex]}`; + props.handleAction({ currentTarget: { value } }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+
+
+ + + + {colorways.map(({ id, label, tooltip }) => ( + +
+
+ colorway.id === activeId)} + /> +
+ ); +} diff --git a/browser/components/newtab/content-src/aboutwelcome/components/MSLocalized.jsx b/browser/components/aboutwelcome/content-src/components/MSLocalized.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/MSLocalized.jsx rename to browser/components/aboutwelcome/content-src/components/MSLocalized.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/MobileDownloads.jsx b/browser/components/aboutwelcome/content-src/components/MobileDownloads.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/MobileDownloads.jsx rename to browser/components/aboutwelcome/content-src/components/MobileDownloads.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/MultiSelect.jsx b/browser/components/aboutwelcome/content-src/components/MultiSelect.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/MultiSelect.jsx rename to browser/components/aboutwelcome/content-src/components/MultiSelect.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/MultiStageAboutWelcome.jsx b/browser/components/aboutwelcome/content-src/components/MultiStageAboutWelcome.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/MultiStageAboutWelcome.jsx rename to browser/components/aboutwelcome/content-src/components/MultiStageAboutWelcome.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/MultiStageProtonScreen.jsx b/browser/components/aboutwelcome/content-src/components/MultiStageProtonScreen.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/MultiStageProtonScreen.jsx rename to browser/components/aboutwelcome/content-src/components/MultiStageProtonScreen.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/OnboardingVideo.jsx b/browser/components/aboutwelcome/content-src/components/OnboardingVideo.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/OnboardingVideo.jsx rename to browser/components/aboutwelcome/content-src/components/OnboardingVideo.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/ReturnToAMO.jsx b/browser/components/aboutwelcome/content-src/components/ReturnToAMO.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/ReturnToAMO.jsx rename to browser/components/aboutwelcome/content-src/components/ReturnToAMO.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/Themes.jsx b/browser/components/aboutwelcome/content-src/components/Themes.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/Themes.jsx rename to browser/components/aboutwelcome/content-src/components/Themes.jsx diff --git a/browser/components/newtab/content-src/aboutwelcome/components/Zap.jsx b/browser/components/aboutwelcome/content-src/components/Zap.jsx similarity index 100% rename from browser/components/newtab/content-src/aboutwelcome/components/Zap.jsx rename to browser/components/aboutwelcome/content-src/components/Zap.jsx diff --git a/browser/components/aboutwelcome/content/aboutwelcome.bundle.js b/browser/components/aboutwelcome/content/aboutwelcome.bundle.js new file mode 100644 index 000000000000..cfda9de8d0ee --- /dev/null +++ b/browser/components/aboutwelcome/content/aboutwelcome.bundle.js @@ -0,0 +1,4158 @@ +/*! + * + * NOTE: This file is generated by webpack from aboutwelcome.jsx + * using the npm bundle task. + * + */ +/******/ (() => { + // webpackBootstrap + /******/ "use strict"; + /******/ let __webpack_modules__ = [ + , + /* 0 */ /* 1 */ + /***/ module => { + module.exports = React; + + /***/ + }, + /* 2 */ + /***/ module => { + module.exports = ReactDOM; + + /***/ + }, + /* 3 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ AboutWelcomeUtils: () => + /* binding */ AboutWelcomeUtils, + /* harmony export */ DEFAULT_RTAMO_CONTENT: () => + /* binding */ DEFAULT_RTAMO_CONTENT, + /* harmony export */ + }); + let _document$querySelect; + + /* 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/. */ + // If the container has a "page" data attribute, then this is + // a Spotlight modal or Feature Callout. Otherwise, this is + // about:welcome and we should return the current page. + const page = + ((_document$querySelect = document.querySelector( + "#multi-stage-message-root.onboardingContainer[data-page]" + )) === null || _document$querySelect === void 0 + ? void 0 + : _document$querySelect.dataset.page) || document.location.href; + const AboutWelcomeUtils = { + handleUserAction(action) { + return window.AWSendToParent("SPECIAL_ACTION", action); + }, + + sendImpressionTelemetry(messageId, context) { + let _window; + let _window$AWSendEventTe; + + (_window$AWSendEventTe = (_window = window).AWSendEventTelemetry) === + null || _window$AWSendEventTe === void 0 + ? void 0 + : _window$AWSendEventTe.call(_window, { + event: "IMPRESSION", + event_context: { ...context, page }, + message_id: messageId, + }); + }, + + sendActionTelemetry(messageId, elementId, eventName = "CLICK_BUTTON") { + let _window$AWSendEventTe2; + let _window2; + + const ping = { + event: eventName, + event_context: { + source: elementId, + page, + }, + message_id: messageId, + }; + (_window$AWSendEventTe2 = (_window2 = window) + .AWSendEventTelemetry) === null || _window$AWSendEventTe2 === void 0 + ? void 0 + : _window$AWSendEventTe2.call(_window2, ping); + }, + + sendDismissTelemetry(messageId, elementId) { + // Don't send DISMISS telemetry in spotlight modals since they already send + // their own equivalent telemetry. + if (page !== "spotlight") { + this.sendActionTelemetry(messageId, elementId, "DISMISS"); + } + }, + + async fetchFlowParams(metricsFlowUri) { + let flowParams; + + try { + const response = await fetch(metricsFlowUri, { + credentials: "omit", + }); + + if (response.status === 200) { + const { deviceId, flowId, flowBeginTime } = await response.json(); + flowParams = { + deviceId, + flowId, + flowBeginTime, + }; + } else { + console.error("Non-200 response", response); + } + } catch (e) { + flowParams = null; + } + + return flowParams; + }, + + sendEvent(type, detail) { + document.dispatchEvent( + new CustomEvent(`AWPage:${type}`, { + bubbles: true, + detail, + }) + ); + }, + + getLoadingStrategyFor(url) { + return url !== null && url !== void 0 && url.startsWith("http") + ? "lazy" + : "eager"; + }, + }; + const DEFAULT_RTAMO_CONTENT = { + template: "return_to_amo", + utm_term: "rtamo", + content: { + position: "split", + title: { + string_id: "mr1-return-to-amo-subtitle", + }, + has_noodles: false, + subtitle: { + string_id: "mr1-return-to-amo-addon-title", + }, + backdrop: + "var(--mr-welcome-background-color) var(--mr-welcome-background-gradient)", + background: + "url('chrome://activity-stream/content/data/content/assets/mr-rtamo-background-image.svg') no-repeat center", + progress_bar: true, + primary_button: { + label: { + string_id: "mr1-return-to-amo-add-extension-label", + }, + source_id: "ADD_EXTENSION_BUTTON", + action: { + type: "INSTALL_ADDON_FROM_URL", + data: { + url: null, + telemetrySource: "rtamo", + }, + }, + }, + secondary_button: { + label: { + string_id: "onboarding-not-now-button-label", + }, + source_id: "RTAMO_START_BROWSING_BUTTON", + action: { + type: "OPEN_AWESOME_BAR", + }, + }, + secondary_button_top: { + label: { + string_id: "mr1-onboarding-sign-in-button-label", + }, + source_id: "RTAMO_FXA_SIGNIN_BUTTON", + action: { + data: { + entrypoint: "activity-stream-firstrun", + where: "tab", + }, + type: "SHOW_FIREFOX_ACCOUNTS", + addFlowParams: true, + }, + }, + }, + }; + + /***/ + }, + /* 4 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ MultiStageAboutWelcome: () => + /* binding */ MultiStageAboutWelcome, + /* harmony export */ SecondaryCTA: () => /* binding */ SecondaryCTA, + /* harmony export */ StepsIndicator: () => /* binding */ StepsIndicator, + /* harmony export */ ProgressBar: () => /* binding */ ProgressBar, + /* harmony export */ WelcomeScreen: () => /* binding */ WelcomeScreen, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(3); + /* harmony import */ let _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__(6); + /* harmony import */ let _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__(11); + /* harmony import */ let _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__(19); + /* 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/. */ + + // Amount of milliseconds for all transitions to complete (including delays). + + const TRANSITION_OUT_TIME = 1000; + const LANGUAGE_MISMATCH_SCREEN_ID = "AW_LANGUAGE_MISMATCH"; + const MultiStageAboutWelcome = props => { + let { defaultScreens } = props; + const didFilter = (0, react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false); + const [didMount, setDidMount] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); + const [screens, setScreens] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultScreens); + const [index, setScreenIndex] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.startScreen); + const [previousOrder, setPreviousOrder] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.startScreen - 1); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + (async () => { + // If we want to load index from history state, we don't want to send impression yet + if (!didMount) { + return; + } // On about:welcome first load, screensVisited should be empty + + let screensVisited = didFilter.current + ? screens.slice(0, index) + : []; + let upcomingScreens = defaultScreens + .filter(s => !screensVisited.find(v => v.id === s.id)) // Filter out Language Mismatch screen from upcoming + // screens if screens set from useLanguageSwitcher hook + // has filtered language screen + .filter( + upcomingScreen => + !( + !screens.find(s => s.id === LANGUAGE_MISMATCH_SCREEN_ID) && + upcomingScreen.id === LANGUAGE_MISMATCH_SCREEN_ID + ) + ); + let filteredScreens = screensVisited.concat( + (await window.AWEvaluateScreenTargeting(upcomingScreens)) ?? + upcomingScreens + ); // Use existing screen for the filtered screen to carry over any modification + // e.g. if AW_LANGUAGE_MISMATCH exists, use it from existing screens + + setScreens( + filteredScreens.map( + filtered => screens.find(s => s.id === filtered.id) ?? filtered + ) + ); + didFilter.current = true; + const screenInitials = filteredScreens + .map(({ id }) => { + let _id$split$; + + return id === null || id === void 0 + ? void 0 + : (_id$split$ = id.split("_")[1]) === null || + _id$split$ === void 0 + ? void 0 + : _id$split$[0]; + }) + .join(""); // Send impression ping when respective screen first renders + + filteredScreens.forEach((screen, order) => { + if (index === order) { + let _window; + let _window$AWAddScreenIm; + + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry( + `${props.message_id}_${order}_${screen.id}_${screenInitials}` + ); + (_window$AWAddScreenIm = (_window = window) + .AWAddScreenImpression) === null || + _window$AWAddScreenIm === void 0 + ? void 0 + : _window$AWAddScreenIm.call(_window, screen); + } + }); // Remember that a new screen has loaded for browser navigation + + if (props.updateHistory && index > window.history.state) { + window.history.pushState(index, ""); + } // Remember the previous screen index so we can animate the transition + + setPreviousOrder(index); + })(); + }, [index, didMount]); // eslint-disable-line react-hooks/exhaustive-deps + + const [flowParams, setFlowParams] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); + const { metricsFlowUri } = props; + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + (async () => { + if (metricsFlowUri) { + setFlowParams( + await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.fetchFlowParams( + metricsFlowUri + ) + ); + } + })(); + }, [metricsFlowUri]); // Allow "in" style to render to actually transition towards regular state, + // which also makes using browser back/forward navigation skip transitions. + + const [transition, setTransition] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)( + props.transitions ? "in" : "" + ); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + if (transition === "in") { + requestAnimationFrame(() => + requestAnimationFrame(() => setTransition("")) + ); + } + }, [transition]); // Transition to next screen, opening about:home on last screen button CTA + + const handleTransition = () => { + // Only handle transitioning out from a screen once. + if (transition === "out") { + return; + } // Start transitioning things "out" immediately when moving forwards. + + setTransition(props.transitions ? "out" : ""); // Actually move forwards after all transitions finish. + + setTimeout( + () => { + if (index < screens.length - 1) { + setTransition(props.transitions ? "in" : ""); + setScreenIndex(prevState => prevState + 1); + } else { + window.AWFinish(); + } + }, + props.transitions ? TRANSITION_OUT_TIME : 0 + ); + }; + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + // When about:welcome loads (on refresh or pressing back button + // from about:home), ensure history state usEffect runs before + // useEffect hook that send impression telemetry + setDidMount(true); + + if (props.updateHistory) { + // Switch to the screen tracked in state (null for initial state) + // or last screen index if a user navigates by pressing back + // button from about:home + const handler = ({ state }) => { + if (transition === "out") { + return; + } + + setTransition(props.transitions ? "out" : ""); + setTimeout( + () => { + setTransition(props.transitions ? "in" : ""); + setScreenIndex(Math.min(state, screens.length - 1)); + }, + props.transitions ? TRANSITION_OUT_TIME : 0 + ); + }; // Handle page load, e.g., going back to about:welcome from about:home + + const { state } = window.history; + + if (state) { + setScreenIndex(Math.min(state, screens.length - 1)); + setPreviousOrder(Math.min(state, screens.length - 1)); + } // Watch for browser back/forward button navigation events + + window.addEventListener("popstate", handler); + return () => window.removeEventListener("popstate", handler); + } + + return false; + }, []); // eslint-disable-line react-hooks/exhaustive-deps + // Save the active multi select state for each screen as an object keyed by + // screen id. Each screen id has an array containing checkbox ids used in + // handleAction to update MULTI_ACTION data. This allows us to remember the + // state of each screen's multi select checkboxes when navigating back and + // forth between screens, while also allowing a message to have more than one + // multi select screen. + + const [activeMultiSelects, setActiveMultiSelects] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)({}); // Get the active theme so the rendering code can make it selected + // by default. + + const [activeTheme, setActiveTheme] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); + const [initialTheme, setInitialTheme] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + (async () => { + let theme = await window.AWGetSelectedTheme(); + setInitialTheme(theme); + setActiveTheme(theme); + })(); + }, []); + const { + negotiatedLanguage, + langPackInstallPhase, + languageFilteredScreens, + } = (0, + _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__.useLanguageSwitcher)( + props.appAndSystemLocaleInfo, + screens, + index, + setScreenIndex + ); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + setScreens(languageFilteredScreens); + }, [languageFilteredScreens]); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + react__WEBPACK_IMPORTED_MODULE_0___default().Fragment, + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `outer-wrapper onboardingContainer proton transition-${transition}`, + style: props.backdrop + ? { + background: props.backdrop, + } + : {}, + }, + screens.map((screen, order) => { + const isFirstScreen = screen === screens[0]; + const isLastScreen = screen === screens[screens.length - 1]; + const totalNumberOfScreens = screens.length; + const isSingleScreen = totalNumberOfScreens === 1; + + const setActiveMultiSelect = valueOrFn => + setActiveMultiSelects(prevState => ({ + ...prevState, + [screen.id]: + typeof valueOrFn === "function" + ? valueOrFn(prevState[screen.id]) + : valueOrFn, + })); + + return index === order + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + WelcomeScreen, + { + key: screen.id + order, + id: screen.id, + totalNumberOfScreens, + isFirstScreen, + isLastScreen, + isSingleScreen, + order, + previousOrder, + content: screen.content, + navigate: handleTransition, + messageId: `${props.message_id}_${order}_${screen.id}`, + UTMTerm: props.utm_term, + flowParams, + activeTheme, + initialTheme, + setActiveTheme, + setInitialTheme, + activeMultiSelect: activeMultiSelects[screen.id], + setActiveMultiSelect, + autoAdvance: screen.auto_advance, + negotiatedLanguage, + langPackInstallPhase, + forceHideStepsIndicator: + screen.force_hide_steps_indicator, + ariaRole: props.ariaRole, + aboveButtonStepsIndicator: + screen.above_button_steps_indicator, + } + ) + : null; + }) + ) + ); + }; + const SecondaryCTA = props => { + let _props$content$second; + let _props$content$second2; + let _props$content$tiles; + + const targetElement = props.position + ? `secondary_button_${props.position}` + : `secondary_button`; + let buttonStyling = + (_props$content$second = props.content.secondary_button) !== null && + _props$content$second !== void 0 && + _props$content$second.has_arrow_icon + ? `secondary arrow-icon` + : `secondary`; + const isTextLink = + !["split", "callout"].includes(props.content.position) && + ((_props$content$tiles = props.content.tiles) === null || + _props$content$tiles === void 0 + ? void 0 + : _props$content$tiles.type) !== "addons-picker"; + const isPrimary = + ((_props$content$second2 = props.content.secondary_button) === null || + _props$content$second2 === void 0 + ? void 0 + : _props$content$second2.style) === "primary"; + + if (isTextLink) { + buttonStyling += " text-link"; + } + + if (isPrimary) { + let _props$content$second3; + + buttonStyling = + (_props$content$second3 = props.content.secondary_button) !== + null && + _props$content$second3 !== void 0 && + _props$content$second3.has_arrow_icon + ? `primary arrow-icon` + : `primary`; + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: props.position + ? `secondary-cta ${props.position}` + : "secondary-cta", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: props.content[targetElement].text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + null + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: props.content[targetElement].label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: buttonStyling, + value: targetElement, + onClick: props.handleAction, + } + ) + ) + ); + }; + const StepsIndicator = props => { + let steps = []; + + for (let i = 0; i < props.totalNumberOfScreens; i++) { + let className = `${i === props.order ? "current" : ""} ${ + i < props.order ? "complete" : "" + }`; + steps.push( + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + key: i, + className: `indicator ${className}`, + role: "presentation", + } + ) + ); + } + + return steps; + }; + const ProgressBar = ({ step, previousStep, totalNumberOfScreens }) => { + const [progress, setProgress] = + react__WEBPACK_IMPORTED_MODULE_0___default().useState( + previousStep / totalNumberOfScreens + ); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + // We don't need to hook any dependencies because any time the step changes, + // the screen's entire DOM tree will be re-rendered. + setProgress(step / totalNumberOfScreens); + }, []); // eslint-disable-line react-hooks/exhaustive-deps + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "indicator", + role: "presentation", + style: { + "--progress-bar-progress": `${progress * 100}%`, + }, + } + ); + }; + class WelcomeScreen extends react__WEBPACK_IMPORTED_MODULE_0___default() + .PureComponent { + constructor(props) { + super(props); + this.handleAction = this.handleAction.bind(this); + } + + handleOpenURL(action, flowParams, UTMTerm) { + let { type, data } = action; + + if (type === "SHOW_FIREFOX_ACCOUNTS") { + let params = { + ..._asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__.BASE_PARAMS, + utm_term: `${UTMTerm}-screen`, + }; + + if (action.addFlowParams && flowParams) { + params = { ...params, ...flowParams }; + } + + data = { ...data, extraParams: params }; + } else if (type === "OPEN_URL") { + let url = new URL(data.args); + (0, + _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__.addUtmParams)( + url, + `${UTMTerm}-screen` + ); + + if (action.addFlowParams && flowParams) { + url.searchParams.append("device_id", flowParams.deviceId); + url.searchParams.append("flow_id", flowParams.flowId); + url.searchParams.append( + "flow_begin_time", + flowParams.flowBeginTime + ); + } + + data = { ...data, args: url.toString() }; + } + + return _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction( + { + type, + data, + } + ); + } + + async handleAction(event) { + let { props } = this; + const value = + event.currentTarget.value ?? + event.currentTarget.getAttribute("value"); + const source = event.source || value; + let targetContent = + props.content[value] || + props.content.tiles || + props.content.languageSwitcher; + + if (!(targetContent && targetContent.action)) { + return; + } // Send telemetry before waiting on actions + + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry( + props.messageId, + source, + event.name + ); // Send additional telemetry if a messaging surface like feature callout is + // dismissed via the dismiss button. Other causes of dismissal will be + // handled separately by the messaging surface's own code. + + if (value === "dismiss_button" && !event.name) { + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry( + props.messageId, + source + ); + } + + let { action } = targetContent; + action = JSON.parse(JSON.stringify(action)); + + if (action.collectSelect) { + let _action$data; + + // Populate MULTI_ACTION data actions property with selected checkbox + // actions from tiles data + if (action.type !== "MULTI_ACTION") { + console.error( + "collectSelect is only supported for MULTI_ACTION type actions" + ); + action.type = "MULTI_ACTION"; + } + + if ( + !Array.isArray( + (_action$data = action.data) === null || _action$data === void 0 + ? void 0 + : _action$data.actions + ) + ) { + console.error( + "collectSelect is only supported for MULTI_ACTION type actions with an array of actions" + ); + action.data = { + actions: [], + }; + } // Prepend the multi-select actions to the CTA's actions array, but keep + // the actions in the same order they appear in. This way the CTA action + // can go last, after the multi-select actions are processed. For example, + // 1. checkbox action 1 + // 2. checkbox action 2 + // 3. radio action + // 4. CTA action (which perhaps depends on the radio action) + + let multiSelectActions = []; + + for (const checkbox of ((_props$content = props.content) === null || + _props$content === void 0 + ? void 0 + : (_props$content$tiles2 = _props$content.tiles) === null || + _props$content$tiles2 === void 0 + ? void 0 + : _props$content$tiles2.data) ?? []) { + var _props$content; + var _props$content$tiles2; + var _this$props$activeMul; + + let checkboxAction; + + if ( + (_this$props$activeMul = this.props.activeMultiSelect) !== + null && + _this$props$activeMul !== void 0 && + _this$props$activeMul.includes(checkbox.id) + ) { + checkboxAction = checkbox.checkedAction ?? checkbox.action; + } else { + checkboxAction = checkbox.uncheckedAction; + } + + if (checkboxAction) { + multiSelectActions.push(checkboxAction); + } + } + + action.data.actions.unshift(...multiSelectActions); // Send telemetry with selected checkbox ids + + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry( + props.messageId, + props.activeMultiSelect, + "SELECT_CHECKBOX" + ); + } + + let actionResult; + + if (["OPEN_URL", "SHOW_FIREFOX_ACCOUNTS"].includes(action.type)) { + actionResult = await this.handleOpenURL( + action, + props.flowParams, + props.UTMTerm + ); + } else if (action.type) { + actionResult = + await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction( + action + ); + + if (action.type === "FXA_SIGNIN_FLOW") { + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry( + props.messageId, + actionResult ? "sign_in" : "sign_in_cancel", + "FXA_SIGNIN_FLOW" + ); + } // Wait until migration closes to complete the action + + const hasMigrate = a => { + let _a$data; + let _a$data$actions; + + return ( + a.type === "SHOW_MIGRATION_WIZARD" || + (a.type === "MULTI_ACTION" && + ((_a$data = a.data) === null || _a$data === void 0 + ? void 0 + : (_a$data$actions = _a$data.actions) === null || + _a$data$actions === void 0 + ? void 0 + : _a$data$actions.some(hasMigrate))) + ); + }; + + if (hasMigrate(action)) { + await window.AWWaitForMigrationClose(); + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry( + props.messageId, + "migrate_close" + ); + } + } // A special tiles.action.theme value indicates we should use the event's value vs provided value. + + if (action.theme) { + let themeToUse = + action.theme === "" + ? event.currentTarget.value + : this.props.initialTheme || action.theme; + this.props.setActiveTheme(themeToUse); + window.AWSelectTheme(themeToUse); + } // If the action has persistActiveTheme: true, we set the initial theme to the currently active theme + // so that it can be reverted to in the event that the user navigates away from the screen + + if (action.persistActiveTheme) { + this.props.setInitialTheme(this.props.activeTheme); + } // `navigate` and `dismiss` can be true/false/undefined, or they can be a + // string "actionResult" in which case we should use the actionResult + // (boolean resolved by handleUserAction) + + const shouldDoBehavior = behavior => + behavior === "actionResult" ? actionResult : behavior; + + if (shouldDoBehavior(action.navigate)) { + props.navigate(); + } + + if (shouldDoBehavior(action.dismiss)) { + window.AWFinish(); + } + } + + render() { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__.MultiStageProtonScreen, + { + content: this.props.content, + id: this.props.id, + order: this.props.order, + previousOrder: this.props.previousOrder, + activeTheme: this.props.activeTheme, + activeMultiSelect: this.props.activeMultiSelect, + setActiveMultiSelect: this.props.setActiveMultiSelect, + totalNumberOfScreens: this.props.totalNumberOfScreens, + appAndSystemLocaleInfo: this.props.appAndSystemLocaleInfo, + negotiatedLanguage: this.props.negotiatedLanguage, + langPackInstallPhase: this.props.langPackInstallPhase, + handleAction: this.handleAction, + messageId: this.props.messageId, + isFirstScreen: this.props.isFirstScreen, + isLastScreen: this.props.isLastScreen, + isSingleScreen: this.props.isSingleScreen, + startsWithCorner: this.props.startsWithCorner, + autoAdvance: this.props.autoAdvance, + forceHideStepsIndicator: this.props.forceHideStepsIndicator, + ariaRole: this.props.ariaRole, + aboveButtonStepsIndicator: this.props.aboveButtonStepsIndicator, + } + ); + } + } + + /***/ + }, + /* 5 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ CONFIGURABLE_STYLES: () => + /* binding */ CONFIGURABLE_STYLES, + /* harmony export */ Localized: () => /* binding */ Localized, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ + + const CONFIGURABLE_STYLES = [ + "color", + "fontSize", + "fontWeight", + "letterSpacing", + "lineHeight", + "marginBlock", + "marginInline", + "paddingBlock", + "paddingInline", + "whiteSpace", + ]; + const ZAP_SIZE_THRESHOLD = 160; + /** + * Based on the .text prop, localizes an inner element if a string_id + * is provided, OR renders plain text, OR hides it if nothing is provided. + * Allows configuring of some styles including zap underline and color. + * + * Examples: + * + * Localized text + * ftl: + * title = Welcome + * jsx: + *

+ * output: + *

Welcome

+ * + * Unlocalized text + * jsx: + *

+ *

+ * output: + *

Welcome

+ */ + + const Localized = ({ text, children }) => { + // Dynamically determine the size of the zap style. + const zapRef = + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createRef(); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + const { current } = zapRef; + + if (current) { + requestAnimationFrame(() => + current === null || current === void 0 + ? void 0 + : current.classList.replace( + "short", + current.getBoundingClientRect().width > ZAP_SIZE_THRESHOLD + ? "long" + : "short" + ) + ); + } + }); // Skip rendering of children with no text. + + if (!text) { + return null; + } // Allow augmenting existing child container properties. + + const props = { + children: [], + className: "", + style: {}, + ...(children === null || children === void 0 + ? void 0 + : children.props), + }; // Support nested Localized by starting with their children. + + const textNodes = Array.isArray(props.children) + ? props.children + : [props.children]; // Pick desired fluent or raw/plain text to render. + + if (text.string_id) { + // Set the key so React knows not to reuse when switching to plain text. + props.key = text.string_id; + props["data-l10n-id"] = text.string_id; + + if (text.args) { + props["data-l10n-args"] = JSON.stringify(text.args); + } + } else if (text.raw) { + textNodes.push(text.raw); + } else if (typeof text === "string") { + textNodes.push(text); + } // Add zap style and content in a way that allows fluent to insert too. + + if (text.zap) { + props.className += " welcomeZap"; + textNodes.push( + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + { + className: "short zap", + "data-l10n-name": "zap", + ref: zapRef, + }, + text.zap + ) + ); + } + + if (text.aria_label) { + props["aria-label"] = text.aria_label; + } // Apply certain configurable styles. + + CONFIGURABLE_STYLES.forEach(style => { + if (text[style] !== undefined) { + props.style[style] = text[style]; + } + }); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().cloneElement( + // Provide a default container for the text if necessary. + children ?? + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + null + ), + props, // Conditionally pass in as void elements can't accept empty array. + textNodes.length ? textNodes : null + ); + }; + + /***/ + }, + /* 6 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ MultiStageProtonScreen: () => + /* binding */ MultiStageProtonScreen, + /* harmony export */ ProtonScreenActionButtons: () => + /* binding */ ProtonScreenActionButtons, + /* harmony export */ ProtonScreen: () => /* binding */ ProtonScreen, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(3); + /* harmony import */ let _MRColorways__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__(7); + /* harmony import */ let _MobileDownloads__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__(8); + /* harmony import */ let _MultiSelect__WEBPACK_IMPORTED_MODULE_5__ = + __webpack_require__(9); + /* harmony import */ let _Themes__WEBPACK_IMPORTED_MODULE_6__ = + __webpack_require__(10); + /* harmony import */ let _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__ = + __webpack_require__(4); + /* harmony import */ let _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_8__ = + __webpack_require__(11); + /* harmony import */ let _CTAParagraph__WEBPACK_IMPORTED_MODULE_9__ = + __webpack_require__(12); + /* harmony import */ let _HeroImage__WEBPACK_IMPORTED_MODULE_10__ = + __webpack_require__(13); + /* harmony import */ let _OnboardingVideo__WEBPACK_IMPORTED_MODULE_11__ = + __webpack_require__(14); + /* harmony import */ let _AdditionalCTA__WEBPACK_IMPORTED_MODULE_12__ = + __webpack_require__(15); + /* harmony import */ let _EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_13__ = + __webpack_require__(16); + /* harmony import */ let _AddonsPicker__WEBPACK_IMPORTED_MODULE_14__ = + __webpack_require__(17); + /* harmony import */ let _LinkParagraph__WEBPACK_IMPORTED_MODULE_15__ = + __webpack_require__(18); + /* 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/. */ + + const MultiStageProtonScreen = props => { + const { autoAdvance, handleAction, order } = props; + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + if (autoAdvance) { + const timer = setTimeout(() => { + handleAction({ + currentTarget: { + value: autoAdvance, + }, + name: "AUTO_ADVANCE", + }); + }, 20000); + return () => clearTimeout(timer); + } + + return () => {}; + }, [autoAdvance, handleAction, order]); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + ProtonScreen, + { + content: props.content, + id: props.id, + order: props.order, + activeTheme: props.activeTheme, + activeMultiSelect: props.activeMultiSelect, + setActiveMultiSelect: props.setActiveMultiSelect, + totalNumberOfScreens: props.totalNumberOfScreens, + handleAction: props.handleAction, + isFirstScreen: props.isFirstScreen, + isLastScreen: props.isLastScreen, + isSingleScreen: props.isSingleScreen, + previousOrder: props.previousOrder, + autoAdvance: props.autoAdvance, + isRtamo: props.isRtamo, + addonName: props.addonName, + isTheme: props.isTheme, + iconURL: props.iconURL, + messageId: props.messageId, + negotiatedLanguage: props.negotiatedLanguage, + langPackInstallPhase: props.langPackInstallPhase, + forceHideStepsIndicator: props.forceHideStepsIndicator, + ariaRole: props.ariaRole, + aboveButtonStepsIndicator: props.aboveButtonStepsIndicator, + } + ); + }; + const ProtonScreenActionButtons = props => { + let _content$additional_b; + let _content$checkbox; + let _content$primary_butt; + let _content$primary_butt2; + let _content$primary_butt3; + let _content$primary_butt4; + let _content$primary_butt5; + + const { content, addonName, activeMultiSelect } = props; + const defaultValue = + (_content$checkbox = content.checkbox) === null || + _content$checkbox === void 0 + ? void 0 + : _content$checkbox.defaultValue; + const [isChecked, setIsChecked] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultValue || false); + const buttonRef = + react__WEBPACK_IMPORTED_MODULE_0___default().useRef(null); + const shouldFocusButton = + content === null || content === void 0 + ? void 0 + : (_content$primary_butt = content.primary_button) === null || + _content$primary_butt === void 0 + ? void 0 + : _content$primary_butt.should_focus_button; + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + if (shouldFocusButton) { + let _buttonRef$current; + + (_buttonRef$current = buttonRef.current) === null || + _buttonRef$current === void 0 + ? void 0 + : _buttonRef$current.focus(); + } + }, [shouldFocusButton]); + + if ( + !content.primary_button && + !content.secondary_button && + !content.additional_button + ) { + return null; + } // If we have a multi-select screen, we want to disable the primary button + // until the user has selected at least one item. + + const isPrimaryDisabled = primaryDisabledValue => + primaryDisabledValue === "hasActiveMultiSelect" + ? !( + (activeMultiSelect === null || activeMultiSelect === void 0 + ? void 0 + : activeMultiSelect.length) > 0 + ) + : primaryDisabledValue; + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `action-buttons ${ + content.additional_button ? "additional-cta-container" : "" + }`, + flow: + (_content$additional_b = content.additional_button) === null || + _content$additional_b === void 0 + ? void 0 + : _content$additional_b.flow, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: + (_content$primary_butt2 = content.primary_button) === null || + _content$primary_butt2 === void 0 + ? void 0 + : _content$primary_butt2.label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + ref: buttonRef, + className: `${ + ((_content$primary_butt3 = content.primary_button) === null || + _content$primary_butt3 === void 0 + ? void 0 + : _content$primary_butt3.style) ?? "primary" + }${ + (_content$primary_butt4 = content.primary_button) !== null && + _content$primary_butt4 !== void 0 && + _content$primary_butt4.has_arrow_icon + ? " arrow-icon" + : "" + }`, // Whether or not the checkbox is checked determines which action + // should be handled. By setting value here, we indicate to + // this.handleAction() where in the content tree it should take + // the action to execute from. + value: isChecked ? "checkbox" : "primary_button", + disabled: isPrimaryDisabled( + (_content$primary_butt5 = content.primary_button) === null || + _content$primary_butt5 === void 0 + ? void 0 + : _content$primary_butt5.disabled + ), + onClick: props.handleAction, + "data-l10n-args": addonName + ? JSON.stringify({ + "addon-name": addonName, + }) + : "", + } + ) + ), + content.additional_button + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _AdditionalCTA__WEBPACK_IMPORTED_MODULE_12__.AdditionalCTA, + { + content, + handleAction: props.handleAction, + } + ) + : null, + content.checkbox + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "checkbox-container", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "input", + { + type: "checkbox", + id: "action-checkbox", + checked: isChecked, + onChange: () => { + setIsChecked(!isChecked); + }, + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.checkbox.label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "label", + { + htmlFor: "action-checkbox", + } + ) + ) + ) + : null, + content.secondary_button + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.SecondaryCTA, + { + content, + handleAction: props.handleAction, + } + ) + : null + ); + }; + class ProtonScreen extends react__WEBPACK_IMPORTED_MODULE_0___default() + .PureComponent { + componentDidMount() { + this.mainContentHeader.focus(); + } + + getScreenClassName( + isFirstScreen, + isLastScreen, + includeNoodles, + isVideoOnboarding, + isAddonsPicker + ) { + const screenClass = `screen-${this.props.order % 2 !== 0 ? 1 : 2}`; + + if (isVideoOnboarding) { + return "with-video"; + } + + if (isAddonsPicker) { + return "addons-picker"; + } + + return `${isFirstScreen ? `dialog-initial` : ``} ${ + isLastScreen ? `dialog-last` : `` + } ${includeNoodles ? `with-noodles` : ``} ${screenClass}`; + } + + renderTitle({ title, title_logo }) { + if (title_logo) { + const { alignment, ...rest } = title_logo; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "inline-icon-container", + alignment: alignment ?? "center", + }, + this.renderPicture({ ...rest }), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: title, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "h1", + { + id: "mainContentHeader", + } + ) + ) + ); + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: title, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "h1", + { + id: "mainContentHeader", + } + ) + ); + } + + renderPicture({ + imageURL = "chrome://branding/content/about-logo.svg", + darkModeImageURL, + reducedMotionImageURL, + darkModeReducedMotionImageURL, + alt = "", + width, + height, + marginBlock, + marginInline, + className = "logo-container", + }) { + function getLoadingStrategy() { + for (let url of [ + imageURL, + darkModeImageURL, + reducedMotionImageURL, + darkModeReducedMotionImageURL, + ]) { + if ( + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor( + url + ) === "lazy" + ) { + return "lazy"; + } + } + + return "eager"; + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "picture", + { + className, + style: { + marginInline, + marginBlock, + }, + }, + darkModeReducedMotionImageURL + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "source", + { + srcSet: darkModeReducedMotionImageURL, + media: + "(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)", + } + ) + : null, + darkModeImageURL + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "source", + { + srcSet: darkModeImageURL, + media: "(prefers-color-scheme: dark)", + } + ) + : null, + reducedMotionImageURL + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "source", + { + srcSet: reducedMotionImageURL, + media: "(prefers-reduced-motion: reduce)", + } + ) + : null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: alt, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "sr-only logo-alt", + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + className: "brand-logo", + style: { + height, + width, + }, + src: imageURL, + alt: "", + loading: getLoadingStrategy(), + role: alt ? null : "presentation", + } + ) + ); + } + + renderContentTiles() { + const { content } = this.props; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + react__WEBPACK_IMPORTED_MODULE_0___default().Fragment, + null, + content.tiles && + content.tiles.type === "addons-picker" && + content.tiles.data + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _AddonsPicker__WEBPACK_IMPORTED_MODULE_14__.AddonsPicker, + { + content, + message_id: this.props.messageId, + handleAction: this.props.handleAction, + } + ) + : null, + content.tiles && + content.tiles.type === "colorway" && + content.tiles.colorways + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MRColorways__WEBPACK_IMPORTED_MODULE_3__.Colorways, + { + content, + activeTheme: this.props.activeTheme, + handleAction: this.props.handleAction, + } + ) + : null, + content.tiles && + content.tiles.type === "theme" && + content.tiles.data + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _Themes__WEBPACK_IMPORTED_MODULE_6__.Themes, + { + content, + activeTheme: this.props.activeTheme, + handleAction: this.props.handleAction, + } + ) + : null, + content.tiles && + content.tiles.type === "mobile_downloads" && + content.tiles.data + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MobileDownloads__WEBPACK_IMPORTED_MODULE_4__.MobileDownloads, + { + data: content.tiles.data, + handleAction: this.props.handleAction, + } + ) + : null, + content.tiles && + content.tiles.type === "multiselect" && + content.tiles.data + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiSelect__WEBPACK_IMPORTED_MODULE_5__.MultiSelect, + { + content, + activeMultiSelect: this.props.activeMultiSelect, + setActiveMultiSelect: this.props.setActiveMultiSelect, + handleAction: this.props.handleAction, + } + ) + : null, + content.tiles && content.tiles.type === "migration-wizard" + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_13__.EmbeddedMigrationWizard, + { + handleAction: this.props.handleAction, + } + ) + : null + ); + } + + renderNoodles() { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + react__WEBPACK_IMPORTED_MODULE_0___default().Fragment, + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "noodle orange-L", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "noodle purple-C", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "noodle solid-L", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "noodle outline-L", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "noodle yellow-circle", + } + ) + ); + } + + renderLanguageSwitcher() { + return this.props.content.languageSwitcher + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_8__.LanguageSwitcher, + { + content: this.props.content, + handleAction: this.props.handleAction, + negotiatedLanguage: this.props.negotiatedLanguage, + langPackInstallPhase: this.props.langPackInstallPhase, + messageId: this.props.messageId, + } + ) + : null; + } + + renderDismissButton() { + const { size, marginBlock, marginInline, label } = + this.props.content.dismiss_button; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: "dismiss-button", + onClick: this.props.handleAction, + value: "dismiss_button", + "data-l10n-id": + (label === null || label === void 0 + ? void 0 + : label.string_id) || "spotlight-dialog-close-button", + "button-size": size, + style: { + marginBlock, + marginInline, + }, + } + ); + } + + renderStepsIndicator() { + let _content$steps_indica; + + const currentStep = (this.props.order ?? 0) + 1; + const previousStep = (this.props.previousOrder ?? -1) + 1; + const { content, totalNumberOfScreens: total } = this.props; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + id: "steps", + className: `steps${content.progress_bar ? " progress-bar" : ""}`, + "data-l10n-id": + ((_content$steps_indica = content.steps_indicator) === null || + _content$steps_indica === void 0 + ? void 0 + : _content$steps_indica.string_id) || + "onboarding-welcome-steps-indicator-label", + "data-l10n-args": JSON.stringify({ + current: currentStep, + total: total ?? 0, + }), + "data-l10n-attrs": "aria-label", + role: "progressbar", + "aria-valuenow": currentStep, + "aria-valuemin": 1, + "aria-valuemax": total, + }, + content.progress_bar + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.ProgressBar, + { + step: currentStep, + previousStep, + totalNumberOfScreens: total, + } + ) + : /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.StepsIndicator, + { + order: this.props.order, + totalNumberOfScreens: total, + } + ) + ); + } + + renderSecondarySection(content) { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `section-secondary ${ + content.hide_secondary_section + ? "with-secondary-section-hidden" + : "" + }`, + style: content.background + ? { + background: content.background, + "--mr-secondary-background-position-y": + content.split_narrow_bkg_position, + } + : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.image_alt_text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "sr-only image-alt", + role: "img", + } + ) + ), + content.hero_image + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _HeroImage__WEBPACK_IMPORTED_MODULE_10__.HeroImage, + { + url: content.hero_image.url, + } + ) + : /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + react__WEBPACK_IMPORTED_MODULE_0___default().Fragment, + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "message-text", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "spacer-top", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.hero_text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "h1", + null + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "spacer-bottom", + } + ) + ) + ) + ); + } + + renderOrderedContent(content) { + const elements = []; + + for (const item of content) { + switch (item.type) { + case "text": + elements.push( + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _LinkParagraph__WEBPACK_IMPORTED_MODULE_15__.LinkParagraph, + { + text_content: item, + handleAction: this.props.handleAction, + } + ) + ); + break; + + case "image": + elements.push( + this.renderPicture({ + imageURL: item.url, + darkModeImageURL: item.darkModeImageURL, + height: item.height, + width: item.width, + alt: item.alt_text, + marginInline: item.marginInline, + className: "inline-image", + }) + ); + } + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + react__WEBPACK_IMPORTED_MODULE_0___default().Fragment, + null, + elements + ); + } + + render() { + let _content$tiles; + let _content$tiles2; + let _this$props$appAndSys; + let _this$props$messageId; + + const { + autoAdvance, + content, + isRtamo, + isTheme, + isFirstScreen, + isLastScreen, + isSingleScreen, + forceHideStepsIndicator, + ariaRole, + aboveButtonStepsIndicator, + } = this.props; + const includeNoodles = content.has_noodles; // The default screen position is "center" + + const isCenterPosition = + content.position === "center" || !content.position; + const hideStepsIndicator = + autoAdvance || + (content === null || content === void 0 + ? void 0 + : content.video_container) || + isSingleScreen || + forceHideStepsIndicator; + const textColorClass = content.text_color + ? `${content.text_color}-text` + : ""; // Assign proton screen style 'screen-1' or 'screen-2' to centered screens + // by checking if screen order is even or odd. + + const screenClassName = isCenterPosition + ? this.getScreenClassName( + isFirstScreen, + isLastScreen, + includeNoodles, + content === null || content === void 0 + ? void 0 + : content.video_container, + ((_content$tiles = content.tiles) === null || + _content$tiles === void 0 + ? void 0 + : _content$tiles.type) === "addons-picker" + ) + : ""; + const isEmbeddedMigration = + ((_content$tiles2 = content.tiles) === null || + _content$tiles2 === void 0 + ? void 0 + : _content$tiles2.type) === "migration-wizard"; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "main", + { + className: `screen ${this.props.id || ""} + ${screenClassName} ${textColorClass}`, + role: ariaRole ?? "alertdialog", + layout: content.layout, + pos: content.position || "center", + tabIndex: "-1", + "aria-labelledby": "mainContentHeader", + ref: input => { + this.mainContentHeader = input; + }, + }, + isCenterPosition ? null : this.renderSecondarySection(content), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `section-main ${ + isEmbeddedMigration ? "embedded-migration" : "" + }`, + "hide-secondary-section": content.hide_secondary_section + ? String(content.hide_secondary_section) + : null, + role: "document", + }, + content.secondary_button_top + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_7__.SecondaryCTA, + { + content, + handleAction: this.props.handleAction, + position: "top", + } + ) + : null, + includeNoodles ? this.renderNoodles() : null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `main-content ${ + hideStepsIndicator ? "no-steps" : "" + }`, + style: { + background: + content.background && isCenterPosition + ? content.background + : null, + width: + content.width && content.position !== "split" + ? content.width + : null, + }, + }, + content.logo ? this.renderPicture(content.logo) : null, + isRtamo + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "rtamo-icon", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + className: `${ + isTheme ? "rtamo-theme-icon" : "brand-logo" + }`, + src: this.props.iconURL, + loading: + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor( + this.props.iconURL + ), + alt: "", + role: "presentation", + } + ) + ) + : null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "main-content-inner", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `welcome-text ${content.title_style || ""}`, + }, + content.title ? this.renderTitle(content) : null, + content.subtitle + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.subtitle, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "h2", + { + "data-l10n-args": JSON.stringify({ + "addon-name": this.props.addonName, + ...((_this$props$appAndSys = + this.props.appAndSystemLocaleInfo) === null || + _this$props$appAndSys === void 0 + ? void 0 + : _this$props$appAndSys.displayNames), + }), + "aria-flowto": + (_this$props$messageId = + this.props.messageId) !== null && + _this$props$messageId !== void 0 && + _this$props$messageId.includes("FEATURE_TOUR") + ? "steps" + : "", + } + ) + ) + : null, + content.cta_paragraph + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _CTAParagraph__WEBPACK_IMPORTED_MODULE_9__.CTAParagraph, + { + content: content.cta_paragraph, + handleAction: this.props.handleAction, + } + ) + : null + ), + content.video_container + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _OnboardingVideo__WEBPACK_IMPORTED_MODULE_11__.OnboardingVideo, + { + content: content.video_container, + handleAction: this.props.handleAction, + } + ) + : null, + content.above_button_content + ? this.renderOrderedContent(content.above_button_content) + : null, + this.renderContentTiles(), + this.renderLanguageSwitcher(), + !hideStepsIndicator && aboveButtonStepsIndicator + ? this.renderStepsIndicator() + : null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + ProtonScreenActionButtons, + { + content, + addonName: this.props.addonName, + handleAction: this.props.handleAction, + activeMultiSelect: this.props.activeMultiSelect, + } + ) + ), + !hideStepsIndicator && !aboveButtonStepsIndicator + ? this.renderStepsIndicator() + : null + ), + content.dismiss_button ? this.renderDismissButton() : null + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.info_text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + { + className: "info-text", + } + ) + ) + ); + } + } + + /***/ + }, + /* 7 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ ColorwayDescription: () => + /* binding */ ColorwayDescription, + /* harmony export */ computeColorWay: () => + /* binding */ computeColorWay, + /* harmony export */ computeVariationIndex: () => + /* binding */ computeVariationIndex, + /* harmony export */ Colorways: () => /* binding */ Colorways, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const ColorwayDescription = props => { + const { colorway } = props; + + if (!colorway) { + return null; + } + + const { label, description } = colorway; + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: description, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "colorway-text", + "data-l10n-args": JSON.stringify({ + colorwayName: label, + }), + } + ) + ); + }; // Return colorway as "default" for default theme variations Automatic, Light, Dark, + // Alpenglow theme and legacy colorways which is not supported in Colorway picker. + // For themes other then default, theme names exist in + // format colorway-variationId inside LIGHT_WEIGHT_THEMES in AboutWelcomeParent + + function computeColorWay(themeName, systemVariations) { + return !themeName || + themeName === "alpenglow" || + systemVariations.includes(themeName) + ? "default" + : themeName.split("-")[0]; + } // Set variationIndex based off activetheme value e.g. 'light', 'expressionist-soft' + + function computeVariationIndex( + themeName, + systemVariations, + variations, + defaultVariationIndex + ) { + // Check if themeName is in systemVariations, if yes choose variationIndex by themeName + let index = systemVariations.findIndex(theme => theme === themeName); + + if (index >= 0) { + return index; + } // If themeName is one of the colorways, select variation index from colorways + + let variation = + themeName === null || themeName === void 0 + ? void 0 + : themeName.split("-")[1]; + index = variations.findIndex(element => element === variation); + + if (index >= 0) { + return index; + } + + return defaultVariationIndex; + } + function Colorways(props) { + let { + colorways, + darkVariation, + defaultVariationIndex, + systemVariations, + variations, + } = props.content.tiles; + let hasReverted = false; // Active theme id from JSON e.g. "expressionist" + + const activeId = computeColorWay(props.activeTheme, systemVariations); + const [colorwayId, setState] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(activeId); + const [variationIndex, setVariationIndex] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultVariationIndex); + + function revertToDefaultTheme() { + if (hasReverted) { + return; + } // Spoofing an event with current target value of "navigate_away" + // helps the handleAction method to read the colorways theme as "revert" + // which causes the initial theme to be activated. + // The "navigate_away" action is set in content in the colorways screen JSON config. + // Any value in the JSON for theme will work, provided it is not ``. + + const event = { + currentTarget: { + value: "navigate_away", + }, + }; + props.handleAction(event); + hasReverted = true; + } // Revert to default theme if the user navigates away from the page or spotlight modal + // before clicking on the primary button to officially set theme. + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + addEventListener("beforeunload", revertToDefaultTheme); + addEventListener("pagehide", revertToDefaultTheme); + return () => { + removeEventListener("beforeunload", revertToDefaultTheme); + removeEventListener("pagehide", revertToDefaultTheme); + }; + }); // Update state any time activeTheme changes. + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + setState(computeColorWay(props.activeTheme, systemVariations)); + setVariationIndex( + computeVariationIndex( + props.activeTheme, + systemVariations, + variations, + defaultVariationIndex + ) + ); // eslint-disable-next-line react-hooks/exhaustive-deps + }, [props.activeTheme]); //select a random colorway + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + //We don't want the default theme to be selected + const randomIndex = + Math.floor(Math.random() * (colorways.length - 1)) + 1; + const randomColorwayId = colorways[randomIndex].id; // Change the variation to be the dark variation if configured and dark. + // Additional colorway changes will remain dark while system is unchanged. + + if ( + darkVariation !== undefined && + window.matchMedia("(prefers-color-scheme: dark)").matches + ) { + variations[variationIndex] = variations[darkVariation]; + } + + const value = `${randomColorwayId}-${variations[variationIndex]}`; + props.handleAction({ + currentTarget: { + value, + }, + }); // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "tiles-theme-container", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "fieldset", + { + className: "tiles-theme-section", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: props.content.subtitle, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "legend", + { + className: "sr-only", + } + ) + ), + colorways.map(({ id, label, tooltip }) => + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + key: id + label, + text: typeof tooltip === "object" ? tooltip : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "label", + { + className: "theme", + title: label, + "data-l10n-args": JSON.stringify({ + colorwayName: label, + }), + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: typeof tooltip === "object" ? tooltip : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + { + className: "sr-only colorway label", + id: `${id}-label`, + "data-l10n-args": JSON.stringify({ + colorwayName: tooltip, + }), + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: typeof label === "object" ? label : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "input", + { + type: "radio", + "data-colorway": id, + name: "theme", + value: + id === "default" + ? systemVariations[variationIndex] + : `${id}-${variations[variationIndex]}`, + checked: colorwayId === id, + className: "sr-only input", + onClick: props.handleAction, + "data-l10n-args": JSON.stringify({ + colorwayName: label, + }), + "aria-labelledby": `${id}-label`, + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `icon colorway ${ + colorwayId === id ? "selected" : "" + } ${id}`, + } + ) + ) + ) + ) + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + ColorwayDescription, + { + colorway: colorways.find(colorway => colorway.id === activeId), + } + ) + ); + } + + /***/ + }, + /* 8 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ MarketplaceButtons: () => + /* binding */ MarketplaceButtons, + /* harmony export */ MobileDownloads: () => + /* binding */ MobileDownloads, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(3); + /* 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/. */ + + const MarketplaceButtons = props => { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "ul", + { + className: "mobile-download-buttons", + }, + props.buttons.includes("ios") + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "li", + { + className: "ios", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + "data-l10n-id": "spotlight-ios-marketplace-button", + value: "ios", + onClick: props.handleAction, + } + ) + ) + : null, + props.buttons.includes("android") + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "li", + { + className: "android", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + "data-l10n-id": "spotlight-android-marketplace-button", + value: "android", + onClick: props.handleAction, + } + ) + ) + : null + ); + }; + const MobileDownloads = props => { + const { QR_code: QRCode } = props.data; + const showEmailLink = + props.data.email && window.AWSendToDeviceEmailsSupported(); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "mobile-downloads", + }, + QRCode + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + "data-l10n-id": QRCode.alt_text.string_id + ? QRCode.alt_text.string_id + : null, + className: "qr-code-image", + alt: + typeof QRCode.alt_text === "string" ? QRCode.alt_text : "", + src: QRCode.image_url, + loading: + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor( + QRCode.image_url + ), + } + ) + : null, + showEmailLink + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: props.data.email.link_text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: "email-link", + value: "email_link", + onClick: props.handleAction, + } + ) + ) + ) + : null, + props.data.marketplace_buttons + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + MarketplaceButtons, + { + buttons: props.data.marketplace_buttons, + handleAction: props.handleAction, + } + ) + : null + ); + }; + + /***/ + }, + /* 9 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ MultiSelect: () => /* binding */ MultiSelect, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const MULTI_SELECT_STYLES = [ + ..._MSLocalized__WEBPACK_IMPORTED_MODULE_1__.CONFIGURABLE_STYLES, + "flexDirection", + "flexWrap", + "flexFlow", + "flexGrow", + "flexShrink", + "justifyContent", + "alignItems", + "gap", + ]; + const MULTI_SELECT_ICON_STYLES = [ + ..._MSLocalized__WEBPACK_IMPORTED_MODULE_1__.CONFIGURABLE_STYLES, + "width", + "height", + "background", + "backgroundColor", + "backgroundImage", + "backgroundSize", + "backgroundPosition", + "backgroundRepeat", + "backgroundOrigin", + "backgroundClip", + "border", + "borderRadius", + "appearance", + "fill", + "stroke", + "outline", + "outlineOffset", + "boxShadow", + ]; + + function getValidStyle(style, validStyles, allowVars) { + if (!style) { + return null; + } + + return Object.keys(style) + .filter( + key => + validStyles.includes(key) || (allowVars && key.startsWith("--")) + ) + .reduce((obj, key) => { + obj[key] = style[key]; + return obj; + }, {}); + } + + const MultiSelect = ({ + content, + activeMultiSelect, + setActiveMultiSelect, + }) => { + const { data } = content.tiles; + const refs = (0, react__WEBPACK_IMPORTED_MODULE_0__.useRef)({}); + const handleChange = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => { + const newActiveMultiSelect = []; + Object.keys(refs.current).forEach(key => { + let _refs$current$key; + + if ( + (_refs$current$key = refs.current[key]) !== null && + _refs$current$key !== void 0 && + _refs$current$key.checked + ) { + newActiveMultiSelect.push(key); + } + }); + setActiveMultiSelect(newActiveMultiSelect); + }, [setActiveMultiSelect]); + const containerStyle = (0, react__WEBPACK_IMPORTED_MODULE_0__.useMemo)( + () => getValidStyle(content.tiles.style, MULTI_SELECT_STYLES, true), + [content.tiles.style] + ); // When screen renders for first time, update state + // with checkbox ids that has defaultvalue true + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + if (!activeMultiSelect) { + let newActiveMultiSelect = []; + data.forEach(({ id, defaultValue }) => { + if (defaultValue && id) { + newActiveMultiSelect.push(id); + } + }); + setActiveMultiSelect(newActiveMultiSelect); + } + }, []); // eslint-disable-line react-hooks/exhaustive-deps + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "multi-select-container", + style: containerStyle, + }, + data.map(({ id, label, icon, type = "checkbox", group, style }) => + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + key: id + label, + className: "checkbox-container multi-select-item", + style: getValidStyle(style, MULTI_SELECT_STYLES), + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "input", + { + type, // checkbox or radio + id, + value: id, + name: group, + checked: + activeMultiSelect === null || activeMultiSelect === void 0 + ? void 0 + : activeMultiSelect.includes(id), + style: getValidStyle( + icon === null || icon === void 0 ? void 0 : icon.style, + MULTI_SELECT_ICON_STYLES + ), + onChange: handleChange, + ref: el => (refs.current[id] = el), + } + ), + label + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "label", + { + htmlFor: id, + } + ) + ) + : null + ) + ) + ); + }; + + /***/ + }, + /* 10 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ Themes: () => /* binding */ Themes, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const Themes = props => { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "tiles-theme-container", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "fieldset", + { + className: "tiles-theme-section", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: props.content.subtitle, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "legend", + { + className: "sr-only", + } + ) + ), + props.content.tiles.data.map( + ({ theme, label, tooltip, description }) => + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + key: theme + label, + text: typeof tooltip === "object" ? tooltip : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "label", + { + className: "theme", + title: theme + label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: + typeof description === "object" ? description : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "input", + { + type: "radio", + value: theme, + name: "theme", + checked: theme === props.activeTheme, + className: "sr-only input", + onClick: props.handleAction, + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: `icon ${ + theme === props.activeTheme ? " selected" : "" + } ${theme}`, + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "text", + } + ) + ) + ) + ) + ) + ) + ) + ); + }; + + /***/ + }, + /* 11 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ useLanguageSwitcher: () => + /* binding */ useLanguageSwitcher, + /* harmony export */ LanguageSwitcher: () => + /* binding */ LanguageSwitcher, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(3); + /* 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 language switcher implements a hook that should be placed at a higher level + * than the actual language switcher component, as it needs to preemptively fetch + * and install langpacks for the user if there is a language mismatch screen. + */ + + function useLanguageSwitcher( + appAndSystemLocaleInfo, + screens, + screenIndex, + setScreenIndex + ) { + const languageMismatchScreenIndex = screens.findIndex( + ({ id }) => id === "AW_LANGUAGE_MISMATCH" + ); + const screen = screens[languageMismatchScreenIndex]; // Ensure fluent messages have the negotiatedLanguage args set, as they are rendered + // before the negotiatedLanguage is known. If the arg isn't present then Firefox will + // crash in development mode. + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + let _screen$content; + + if ( + screen !== null && + screen !== void 0 && + (_screen$content = screen.content) !== null && + _screen$content !== void 0 && + _screen$content.languageSwitcher + ) { + for (const text of Object.values(screen.content.languageSwitcher)) { + if ( + text !== null && + text !== void 0 && + text.args && + text.args.negotiatedLanguage === undefined + ) { + text.args.negotiatedLanguage = ""; + } + } + } + }, [screen]); // If there is a mismatch, then Firefox can negotiate a better langpack to offer + // the user. + + const [negotiatedLanguage, setNegotiatedLanguage] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)( + function getNegotiatedLanguage() { + if (!appAndSystemLocaleInfo) { + return; + } + + if (appAndSystemLocaleInfo.matchType !== "language-mismatch") { + // There is no language mismatch, so there is no need to negotiate a langpack. + return; + } + + (async () => { + const { langPack, langPackDisplayName } = + await window.AWNegotiateLangPackForLanguageMismatch( + appAndSystemLocaleInfo + ); + + if (langPack) { + setNegotiatedLanguage({ + langPackDisplayName, + appDisplayName: + appAndSystemLocaleInfo.displayNames.appLanguage, + langPack, + requestSystemLocales: [ + langPack.target_locale, + appAndSystemLocaleInfo.appLocaleRaw, + ], + originalAppLocales: [appAndSystemLocaleInfo.appLocaleRaw], + }); + } else { + setNegotiatedLanguage({ + langPackDisplayName: null, + appDisplayName: null, + langPack: null, + requestSystemLocales: null, + }); + } + })(); + }, + [appAndSystemLocaleInfo] + ); + /** + * @type { + * "before-installation" + * | "installing" + * | "installed" + * | "installation-error" + * | "none-available" + * } + */ + + const [langPackInstallPhase, setLangPackInstallPhase] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)("before-installation"); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)( + function ensureLangPackInstalled() { + if (!negotiatedLanguage) { + // There are no negotiated languages to download yet. + return; + } + + setLangPackInstallPhase("installing"); + window + .AWEnsureLangPackInstalled( + negotiatedLanguage, + screen === null || screen === void 0 ? void 0 : screen.content + ) + .then( + content => { + // Update screen content with strings that might have changed. + screen.content = content; + setLangPackInstallPhase("installed"); + }, + error => { + console.error(error); + setLangPackInstallPhase("installation-error"); + } + ); + }, + [negotiatedLanguage, screen] + ); + const [languageFilteredScreens, setLanguageFilteredScreens] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(screens); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)( + function filterScreen() { + // Remove the language screen if it exists (already removed for no live + // reload) and we either don't-need-to or can't switch. + if ( + screen && + ((appAndSystemLocaleInfo === null || + appAndSystemLocaleInfo === void 0 + ? void 0 + : appAndSystemLocaleInfo.matchType) !== "language-mismatch" || + (negotiatedLanguage === null || negotiatedLanguage === void 0 + ? void 0 + : negotiatedLanguage.langPack) === null) + ) { + if (screenIndex > languageMismatchScreenIndex) { + setScreenIndex(screenIndex - 1); + } + + setLanguageFilteredScreens( + screens.filter(s => s.id !== "AW_LANGUAGE_MISMATCH") + ); + } else { + setLanguageFilteredScreens(screens); + } + }, + [ + appAndSystemLocaleInfo === null || appAndSystemLocaleInfo === void 0 + ? void 0 + : appAndSystemLocaleInfo.matchType, + languageMismatchScreenIndex, + negotiatedLanguage, + screen, + screenIndex, + screens, + setScreenIndex, + ] + ); + return { + negotiatedLanguage, + langPackInstallPhase, + languageFilteredScreens, + }; + } + /** + * The language switcher is a separate component as it needs to perform some asynchronous + * network actions such as retrieving the list of langpacks available, and downloading + * a new langpack. On a fast connection, this won't be noticeable, but on slow or unreliable + * internet this may fail for a user. + */ + + function LanguageSwitcher(props) { + const { + content, + handleAction, + negotiatedLanguage, + langPackInstallPhase, + messageId, + } = props; + const [isAwaitingLangpack, setIsAwaitingLangpack] = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); // Determine the status of the langpack installation. + + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + if (isAwaitingLangpack && langPackInstallPhase !== "installing") { + window.AWSetRequestedLocales( + negotiatedLanguage.requestSystemLocales + ); + requestAnimationFrame(() => { + handleAction( + // Simulate the click event. + { + currentTarget: { + value: "download_complete", + }, + } + ); + }); + } + }, [ + handleAction, + isAwaitingLangpack, + langPackInstallPhase, + negotiatedLanguage === null || negotiatedLanguage === void 0 + ? void 0 + : negotiatedLanguage.requestSystemLocales, + ]); + let showWaitingScreen = false; + let showPreloadingScreen = false; + let showReadyScreen = false; + + if (isAwaitingLangpack && langPackInstallPhase !== "installed") { + showWaitingScreen = true; + } else if (langPackInstallPhase === "before-installation") { + showPreloadingScreen = true; + } else { + showReadyScreen = true; + } // Use {display: "none"} rather than if statements to prevent layout thrashing with + // the localized text elements rendering as blank, then filling in the text. + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "action-buttons language-switcher-container", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + style: { + display: showPreloadingScreen ? "block" : "none", + }, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: "primary", + value: "primary_button", + disabled: true, + type: "button", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + className: "language-loader", + src: "chrome://browser/skin/tabbrowser/tab-connecting.png", + alt: "", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.waiting, + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "secondary-cta", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.skip, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + value: "decline_waiting", + type: "button", + className: "secondary text-link arrow-icon", + onClick: handleAction, + } + ) + ) + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + style: { + display: showWaitingScreen ? "block" : "none", + }, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: "primary", + value: "primary_button", + disabled: true, + type: "button", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + className: "language-loader", + src: "chrome://browser/skin/tabbrowser/tab-connecting.png", + alt: "", + } + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.downloading, + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "secondary-cta", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.cancel, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + type: "button", + className: "secondary text-link", + onClick: () => { + setIsAwaitingLangpack(false); + handleAction({ + currentTarget: { + value: "cancel_waiting", + }, + }); + }, + } + ) + ) + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + style: { + display: showReadyScreen ? "block" : "none", + }, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: "primary", + value: "primary_button", + onClick: () => { + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry( + messageId, + "download_langpack" + ); + setIsAwaitingLangpack(true); + }, + }, + content.languageSwitcher.switch + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.switch, + } + ) // This is the localized name from the Intl.DisplayNames API. + : negotiatedLanguage === null || negotiatedLanguage === void 0 + ? void 0 + : negotiatedLanguage.langPackDisplayName + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + type: "button", + className: "primary", + value: "decline", + onClick: event => { + window.AWSetRequestedLocales( + negotiatedLanguage.originalAppLocales + ); + handleAction(event); + }, + }, + content.languageSwitcher.continue + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.languageSwitcher.continue, + } + ) // This is the localized name from the Intl.DisplayNames API. + : negotiatedLanguage === null || negotiatedLanguage === void 0 + ? void 0 + : negotiatedLanguage.appDisplayName + ) + ) + ) + ); + } + + /***/ + }, + /* 12 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ CTAParagraph: () => /* binding */ CTAParagraph, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const CTAParagraph = props => { + const { content, handleAction } = props; + + if (!(content !== null && content !== void 0 && content.text)) { + return null; + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "h2", + { + className: "cta-paragraph", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: content.text, + }, + content.text.string_name && typeof handleAction === "function" + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "span", + { + "data-l10n-id": content.text.string_id, + onClick: handleAction, + onKeyUp: event => + ["Enter", " "].includes(event.key) + ? handleAction(event) + : null, + value: "cta_paragraph", + role: "button", + tabIndex: "0", + }, + " ", + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "a", + { + role: "button", + tabIndex: "0", + "data-l10n-name": content.text.string_name, + }, + " " + ) + ) + : null + ) + ); + }; + + /***/ + }, + /* 13 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ HeroImage: () => /* binding */ HeroImage, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(3); + /* 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/. */ + + const HeroImage = props => { + const { height, url, alt } = props; + + if (!url) { + return null; + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "hero-image", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + style: height + ? { + height, + } + : null, + src: url, + loading: + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.getLoadingStrategyFor( + url + ), + alt: alt || "", + role: alt ? null : "presentation", + } + ) + ); + }; + + /***/ + }, + /* 14 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ OnboardingVideo: () => + /* binding */ OnboardingVideo, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ + + const OnboardingVideo = props => { + const vidUrl = props.content.video_url; + const autoplay = props.content.autoPlay; + + const handleVideoAction = event => { + props.handleAction({ + currentTarget: { + value: event, + }, + }); + }; + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + null, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "video", + { + // eslint-disable-line jsx-a11y/media-has-caption + controls: true, + autoPlay: autoplay, + src: vidUrl, + width: "604px", + height: "340px", + onPlay: () => handleVideoAction("video_start"), + onEnded: () => handleVideoAction("video_end"), + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "source", + { + src: vidUrl, + } + ) + ) + ); + }; + + /***/ + }, + /* 15 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ AdditionalCTA: () => /* binding */ AdditionalCTA, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const AdditionalCTA = ({ content, handleAction }) => { + let _content$additional_b; + let _content$additional_b4; + let _content$additional_b5; + + let buttonStyle = ""; + + if ( + !( + (_content$additional_b = content.additional_button) !== null && + _content$additional_b !== void 0 && + _content$additional_b.style + ) + ) { + buttonStyle = "primary"; + } else { + let _content$additional_b2; + let _content$additional_b3; + + buttonStyle = + ((_content$additional_b2 = content.additional_button) === null || + _content$additional_b2 === void 0 + ? void 0 + : _content$additional_b2.style) === "link" + ? "cta-link" + : (_content$additional_b3 = content.additional_button) === null || + _content$additional_b3 === void 0 + ? void 0 + : _content$additional_b3.style; + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: + (_content$additional_b4 = content.additional_button) === null || + _content$additional_b4 === void 0 + ? void 0 + : _content$additional_b4.label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + className: `${buttonStyle} additional-cta`, + onClick: handleAction, + value: "additional_button", + disabled: + ((_content$additional_b5 = content.additional_button) === + null || _content$additional_b5 === void 0 + ? void 0 + : _content$additional_b5.disabled) === true, + } + ) + ); + }; + + /***/ + }, + /* 16 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ EmbeddedMigrationWizard: () => + /* binding */ EmbeddedMigrationWizard, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ + + const EmbeddedMigrationWizard = ({ handleAction }) => { + const ref = (0, react__WEBPACK_IMPORTED_MODULE_0__.useRef)(); + (0, react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { + const handleBeginMigration = () => { + handleAction({ + currentTarget: { + value: "migrate_start", + }, + source: "primary_button", + }); + }; + + const handleClose = () => { + handleAction({ + currentTarget: { + value: "migrate_close", + }, + }); + }; + + const { current } = ref; + current === null || current === void 0 + ? void 0 + : current.addEventListener( + "MigrationWizard:BeginMigration", + handleBeginMigration + ); + current === null || current === void 0 + ? void 0 + : current.addEventListener("MigrationWizard:Close", handleClose); + return () => { + current === null || current === void 0 + ? void 0 + : current.removeEventListener( + "MigrationWizard:BeginMigration", + handleBeginMigration + ); + current === null || current === void 0 + ? void 0 + : current.removeEventListener( + "MigrationWizard:Close", + handleClose + ); + }; + }, []); // eslint-disable-line react-hooks/exhaustive-deps + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "migration-wizard", + { + "force-show-import-all": "false", + "auto-request-state": "", + ref, + } + ); + }; + + /***/ + }, + /* 17 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ AddonsPicker: () => /* binding */ AddonsPicker, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(3); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(5); + /* 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/. */ + + const AddonsPicker = props => { + const { content } = props; + + if (!content) { + return null; + } + + function handleAction(event) { + const { message_id } = props; + let { action, source_id } = + content.tiles.data[event.currentTarget.value]; + let { type, data } = action; + + if (type === "INSTALL_ADDON_FROM_URL") { + if (!data) { + return; + } + } + + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction( + { + type, + data, + } + ); + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry( + message_id, + source_id + ); + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "addons-picker-container", + }, + content.tiles.data.map( + ({ id, install_label, name, type, description, icon }, index) => + name + ? /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + key: id, + className: "addon-container", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "rtamo-icon", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "img", + { + className: `${ + type === "theme" ? "rtamo-theme-icon" : "brand-logo" + }`, + src: icon, + role: "presentation", + alt: "", + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "addon-details", + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, + { + text: name, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "addon-title", + } + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, + { + text: description, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "addon-description", + } + ) + ) + ), + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, + { + text: install_label, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "button", + { + id: name, + value: index, + onClick: handleAction, + className: "primary", + } + ) + ) + ) + : null + ) + ); + }; + + /***/ + }, + /* 18 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ LinkParagraph: () => /* binding */ LinkParagraph, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(5); + /* 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/. */ + + const LinkParagraph = props => { + let _text_content$link_ke; + + const { text_content, handleAction } = props; + const handleParagraphAction = (0, + react__WEBPACK_IMPORTED_MODULE_0__.useCallback)( + event => { + if (event.target.closest("a")) { + handleAction({ ...event, currentTarget: event.target }); + } + }, + [handleAction] + ); + const onKeyPress = (0, react__WEBPACK_IMPORTED_MODULE_0__.useCallback)( + event => { + if (event.key === "Enter" && !event.repeat) { + handleParagraphAction(event); + } + }, + [handleParagraphAction] + ); + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, + { + text: text_content.text, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "p", + { + className: + text_content.font_styles === "legal" + ? "legal-paragraph" + : "link-paragraph", + onClick: handleParagraphAction, + value: "link_paragraph", + onKeyPress, + }, + (_text_content$link_ke = text_content.link_keys) === null || + _text_content$link_ke === void 0 + ? void 0 + : _text_content$link_ke.map(link => + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "a", + { + key: link, + value: link, + role: "link", + className: "text-link", + "data-l10n-name": link, // must pass in tabIndex when no href is provided + tabIndex: "0", + }, + " " + ) + ) + ) + ); + }; + + /***/ + }, + /* 19 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ BASE_PARAMS: () => /* binding */ BASE_PARAMS, + /* harmony export */ addUtmParams: () => /* binding */ addUtmParams, + /* harmony export */ + }); + /* 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/. */ + + /** + * BASE_PARAMS keys/values can be modified from outside this file + */ + const BASE_PARAMS = { + utm_source: "activity-stream", + utm_campaign: "firstrun", + utm_medium: "referral", + }; + /** + * Takes in a url as a string or URL object and returns a URL object with the + * utm_* parameters added to it. If a URL object is passed in, the paraemeters + * are added to it (the return value can be ignored in that case as it's the + * same object). + */ + + function addUtmParams(url, utmTerm) { + let returnUrl = url; + + if (typeof returnUrl === "string") { + returnUrl = new URL(url); + } + + for (let [key, value] of Object.entries(BASE_PARAMS)) { + if (!returnUrl.searchParams.has(key)) { + returnUrl.searchParams.append(key, value); + } + } + + returnUrl.searchParams.append("utm_term", utmTerm); + return returnUrl; + } + + /***/ + }, + /* 20 */ + /***/ ( + __unused_webpack_module, + __webpack_exports__, + __webpack_require__ + ) => { + __webpack_require__.r(__webpack_exports__); + /* harmony export */ __webpack_require__.d(__webpack_exports__, { + /* harmony export */ ReturnToAMO: () => /* binding */ ReturnToAMO, + /* harmony export */ + }); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(3); + /* harmony import */ let _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(6); + /* harmony import */ let _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__(19); + /* 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/. */ + + class ReturnToAMO extends react__WEBPACK_IMPORTED_MODULE_0___default() + .PureComponent { + constructor(props) { + super(props); + this.fetchFlowParams = this.fetchFlowParams.bind(this); + this.handleAction = this.handleAction.bind(this); + } + + async fetchFlowParams() { + if (this.props.metricsFlowUri) { + this.setState({ + flowParams: + await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.fetchFlowParams( + this.props.metricsFlowUri + ), + }); + } + } + + componentDidUpdate() { + this.fetchFlowParams(); + } + + handleAction(event) { + const { content, message_id, url, utm_term } = this.props; + let { action, source_id } = content[event.currentTarget.value]; + let { type, data } = action; + + if (type === "INSTALL_ADDON_FROM_URL") { + if (!data) { + return; + } // Set add-on url in action.data.url property from JSON + + data = { ...data, url }; + } else if (type === "SHOW_FIREFOX_ACCOUNTS") { + let params = { + ..._asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__.BASE_PARAMS, + utm_term: `aboutwelcome-${utm_term}-screen`, + }; + + if (action.addFlowParams && this.state.flowParams) { + params = { ...params, ...this.state.flowParams }; + } + + data = { ...data, extraParams: params }; + } + + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction( + { + type, + data, + } + ); + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry( + message_id, + source_id + ); + } + + render() { + let _this$props$themeScre; + + const { content, type } = this.props; + + if (!content) { + return null; + } + + if ( + content !== null && + content !== void 0 && + content.primary_button.label + ) { + content.primary_button.label.string_id = type.includes("theme") + ? "return-to-amo-add-theme-label" + : "mr1-return-to-amo-add-extension-label"; + } // For experiments, when needed below rendered UI allows settings hard coded strings + // directly inside JSON except for ReturnToAMOText which picks add-on name and icon from fluent string + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + "div", + { + className: "outer-wrapper onboardingContainer proton", + style: content.backdrop + ? { + background: content.backdrop, + } + : {}, + }, + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__.MultiStageProtonScreen, + { + content, + isRtamo: true, + isTheme: type.includes("theme"), + id: this.props.message_id, + order: this.props.order || 0, + totalNumberOfScreens: 1, + isSingleScreen: true, + autoAdvance: this.props.auto_advance, + iconURL: type.includes("theme") + ? (_this$props$themeScre = this.props.themeScreenshots[0]) === + null || _this$props$themeScre === void 0 + ? void 0 + : _this$props$themeScre.url + : this.props.iconURL, + addonName: this.props.name, + handleAction: this.handleAction, + } + ) + ); + } + } + ReturnToAMO.defaultProps = + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_RTAMO_CONTENT; + + /***/ + }, + /******/ + ]; + /************************************************************************/ + /******/ // The module cache + /******/ let __webpack_module_cache__ = {}; + /******/ + /******/ // The require function + /******/ function __webpack_require__(moduleId) { + /******/ // Check if module is in cache + /******/ let cachedModule = __webpack_module_cache__[moduleId]; + /******/ if (cachedModule !== undefined) { + /******/ return cachedModule.exports; + /******/ + } + /******/ // Create a new module (and put it into the cache) + /******/ let module = (__webpack_module_cache__[moduleId] = { + /******/ // no module.id needed + /******/ // no module.loaded needed + /******/ exports: {}, + /******/ + }); + /******/ + /******/ // Execute the module function + /******/ __webpack_modules__[moduleId]( + module, + module.exports, + __webpack_require__ + ); + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ + } + /******/ + /************************************************************************/ + /******/ /* webpack/runtime/compat get default export */ + /******/ (() => { + /******/ // getDefaultExport function for compatibility with non-harmony modules + /******/ __webpack_require__.n = module => { + /******/ let getter = + module && module.__esModule + ? /******/ () => module.default + : /******/ () => module; + /******/ __webpack_require__.d(getter, { a: getter }); + /******/ return getter; + /******/ + }; + /******/ + })(); + /******/ + /******/ /* webpack/runtime/define property getters */ + /******/ (() => { + /******/ // define getter functions for harmony exports + /******/ __webpack_require__.d = (exports, definition) => { + /******/ for (let key in definition) { + /******/ if ( + __webpack_require__.o(definition, key) && + !__webpack_require__.o(exports, key) + ) { + /******/ Object.defineProperty(exports, key, { + enumerable: true, + get: definition[key], + }); + /******/ + } + /******/ + } + /******/ + }; + /******/ + })(); + /******/ + /******/ /* webpack/runtime/hasOwnProperty shorthand */ + /******/ (() => { + /******/ __webpack_require__.o = (obj, prop) => + Object.prototype.hasOwnProperty.call(obj, prop); + /******/ + })(); + /******/ + /******/ /* webpack/runtime/make namespace object */ + /******/ (() => { + /******/ // define __esModule on exports + /******/ __webpack_require__.r = exports => { + /******/ if (typeof Symbol !== "undefined" && Symbol.toStringTag) { + /******/ Object.defineProperty(exports, Symbol.toStringTag, { + value: "Module", + }); + /******/ + } + /******/ Object.defineProperty(exports, "__esModule", { value: true }); + /******/ + }; + /******/ + })(); + /******/ + /************************************************************************/ + let __webpack_exports__ = {}; + // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. + (() => { + __webpack_require__.r(__webpack_exports__); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0__ = + __webpack_require__(1); + /* harmony import */ let react__WEBPACK_IMPORTED_MODULE_0___default = + /*#__PURE__*/ __webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); + /* harmony import */ let react_dom__WEBPACK_IMPORTED_MODULE_1__ = + __webpack_require__(2); + /* harmony import */ let react_dom__WEBPACK_IMPORTED_MODULE_1___default = + /*#__PURE__*/ __webpack_require__.n( + react_dom__WEBPACK_IMPORTED_MODULE_1__ + ); + /* harmony import */ let _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = + __webpack_require__(3); + /* harmony import */ let _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__ = + __webpack_require__(4); + /* harmony import */ let _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__ = + __webpack_require__(20); + function _extends() { + _extends = + Object.assign || + function (target) { + for (let i = 1; i < arguments.length; i++) { + let source = arguments[i]; + for (let key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + return _extends.apply(this, arguments); + } + + /* 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/. */ + + class AboutWelcome extends react__WEBPACK_IMPORTED_MODULE_0___default() + .PureComponent { + constructor(props) { + super(props); + this.state = { + metricsFlowUri: null, + }; + this.fetchFxAFlowUri = this.fetchFxAFlowUri.bind(this); + } + + async fetchFxAFlowUri() { + let _window; + let _window$AWGetFxAMetri; + + this.setState({ + metricsFlowUri: await ((_window$AWGetFxAMetri = (_window = window) + .AWGetFxAMetricsFlowURI) === null || + _window$AWGetFxAMetri === void 0 + ? void 0 + : _window$AWGetFxAMetri.call(_window)), + }); + } + + componentDidMount() { + if (!this.props.skipFxA) { + this.fetchFxAFlowUri(); + } + + if (document.location.href === "about:welcome") { + // Record impression with performance data after allowing the page to load + const recordImpression = domState => { + const { domComplete, domInteractive } = performance + .getEntriesByType("navigation") + .pop(); + _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry( + this.props.messageId, + { + domComplete, + domInteractive, + mountStart: performance.getEntriesByName("mount").pop() + .startTime, + domState, + source: this.props.UTMTerm, + } + ); + }; + + if (document.readyState === "complete") { + // Page might have already triggered a load event because it waited for async data, + // e.g., attribution, so the dom load timing could be of a empty content + // with domState in telemetry captured as 'complete' + recordImpression(document.readyState); + } else { + window.addEventListener("load", () => recordImpression("load"), { + once: true, + }); + } // Captures user has seen about:welcome by setting + // firstrun.didSeeAboutWelcome pref to true and capturing welcome UI unique messageId + + window.AWSendToParent( + "SET_WELCOME_MESSAGE_SEEN", + this.props.messageId + ); + } + } + + render() { + const { props } = this; + + if (props.template === "return_to_amo") { + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__.ReturnToAMO, + { + message_id: props.messageId, + type: props.type, + name: props.name, + url: props.url, + iconURL: props.iconURL, + themeScreenshots: props.screenshots, + metricsFlowUri: this.state.metricsFlowUri, + } + ); + } + + return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__.MultiStageAboutWelcome, + { + message_id: props.messageId, + defaultScreens: props.screens, + updateHistory: !props.disableHistoryUpdates, + metricsFlowUri: this.state.metricsFlowUri, + utm_term: props.UTMTerm, + transitions: props.transitions, + backdrop: props.backdrop, + startScreen: props.startScreen || 0, + appAndSystemLocaleInfo: props.appAndSystemLocaleInfo, + ariaRole: props.aria_role, + } + ); + } + } // Computes messageId and UTMTerm info used in telemetry + + function ComputeTelemetryInfo(welcomeContent, experimentId, branchId) { + let messageId = + welcomeContent.template === "return_to_amo" + ? `RTAMO_DEFAULT_WELCOME_${welcomeContent.type.toUpperCase()}` + : "DEFAULT_ID"; + let UTMTerm = "aboutwelcome-default"; + + if (welcomeContent.id) { + messageId = welcomeContent.id.toUpperCase(); + } + + if (experimentId && branchId) { + UTMTerm = `aboutwelcome-${experimentId}-${branchId}`.toLowerCase(); + } + + return { + messageId, + UTMTerm, + }; + } + + async function retrieveRenderContent() { + // Feature config includes RTAMO attribution data if exists + // else below data in order specified + // user prefs + // experiment data + // defaults + let featureConfig = await window.AWGetFeatureConfig(); + let { messageId, UTMTerm } = ComputeTelemetryInfo( + featureConfig, + featureConfig.slug, + featureConfig.branch && featureConfig.branch.slug + ); + return { + featureConfig, + messageId, + UTMTerm, + }; + } + + async function mount() { + let { + featureConfig: aboutWelcomeProps, + messageId, + UTMTerm, + } = await retrieveRenderContent(); + react_dom__WEBPACK_IMPORTED_MODULE_1___default().render( + /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0___default().createElement( + AboutWelcome, + _extends( + { + messageId, + UTMTerm, + }, + aboutWelcomeProps + ) + ), + document.getElementById("multi-stage-message-root") + ); + } + + performance.mark("mount"); + mount(); + })(); + + /******/ +})(); diff --git a/browser/components/aboutwelcome/jar.mn b/browser/components/aboutwelcome/jar.mn index 5f5fe6cd42e9..99af5a3d6d46 100644 --- a/browser/components/aboutwelcome/jar.mn +++ b/browser/components/aboutwelcome/jar.mn @@ -6,3 +6,4 @@ browser.jar: res/activity-stream/aboutwelcome/lib/ (./modules/*) content/activity-stream/aboutwelcome/aboutwelcome.css (./content/aboutwelcome.css) res/activity-stream/aboutwelcome/aboutwelcome.html (./content/aboutwelcome.html) + res/activity-stream/aboutwelcome/aboutwelcome.bundle.js (./content/aboutwelcome.bundle.js) diff --git a/browser/components/newtab/webpack.aboutwelcome.config.js b/browser/components/aboutwelcome/webpack.aboutwelcome.config.js similarity index 100% rename from browser/components/newtab/webpack.aboutwelcome.config.js rename to browser/components/aboutwelcome/webpack.aboutwelcome.config.js diff --git a/browser/components/newtab/.eslintrc.js b/browser/components/newtab/.eslintrc.js index c28858797539..76c93036eedd 100644 --- a/browser/components/newtab/.eslintrc.js +++ b/browser/components/newtab/.eslintrc.js @@ -27,12 +27,6 @@ module.exports = { { // These files use fluent-dom to insert content files: [ - "content-src/aboutwelcome/components/Zap.jsx", - "content-src/aboutwelcome/components/MultiStageAboutWelcome.jsx", - "content-src/aboutwelcome/components/MultiStageScreen.jsx", - "content-src/aboutwelcome/components/MultiStageProtonScreen.jsx", - "content-src/aboutwelcome/components/MultiSelect.jsx", - "content-src/aboutwelcome/components/ReturnToAMO.jsx", "content-src/asrouter/templates/OnboardingMessage/**", "content-src/asrouter/templates/FirstRun/**", "content-src/components/TopSites/**", diff --git a/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js b/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js deleted file mode 100644 index 49c785e5a870..000000000000 --- a/browser/components/newtab/aboutwelcome/content/aboutwelcome.bundle.js +++ /dev/null @@ -1,2523 +0,0 @@ -/*! - * - * NOTE: This file is generated by webpack from aboutwelcome.jsx - * using the npm bundle task. - * - */ -/******/ (() => { // webpackBootstrap -/******/ "use strict"; -/******/ var __webpack_modules__ = ([ -/* 0 */, -/* 1 */ -/***/ ((module) => { - -module.exports = React; - -/***/ }), -/* 2 */ -/***/ ((module) => { - -module.exports = ReactDOM; - -/***/ }), -/* 3 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "AboutWelcomeUtils": () => (/* binding */ AboutWelcomeUtils), -/* harmony export */ "DEFAULT_RTAMO_CONTENT": () => (/* binding */ DEFAULT_RTAMO_CONTENT) -/* harmony export */ }); -var _document$querySelect; - -/* 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/. */ -// If the container has a "page" data attribute, then this is -// a Spotlight modal or Feature Callout. Otherwise, this is -// about:welcome and we should return the current page. -const page = ((_document$querySelect = document.querySelector("#multi-stage-message-root.onboardingContainer[data-page]")) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.dataset.page) || document.location.href; -const AboutWelcomeUtils = { - handleUserAction(action) { - return window.AWSendToParent("SPECIAL_ACTION", action); - }, - - sendImpressionTelemetry(messageId, context) { - var _window$AWSendEventTe, _window; - - (_window$AWSendEventTe = (_window = window).AWSendEventTelemetry) === null || _window$AWSendEventTe === void 0 ? void 0 : _window$AWSendEventTe.call(_window, { - event: "IMPRESSION", - event_context: { ...context, - page - }, - message_id: messageId - }); - }, - - sendActionTelemetry(messageId, elementId, eventName = "CLICK_BUTTON") { - var _window$AWSendEventTe2, _window2; - - const ping = { - event: eventName, - event_context: { - source: elementId, - page - }, - message_id: messageId - }; - (_window$AWSendEventTe2 = (_window2 = window).AWSendEventTelemetry) === null || _window$AWSendEventTe2 === void 0 ? void 0 : _window$AWSendEventTe2.call(_window2, ping); - }, - - sendDismissTelemetry(messageId, elementId) { - // Don't send DISMISS telemetry in spotlight modals since they already send - // their own equivalent telemetry. - if (page !== "spotlight") { - this.sendActionTelemetry(messageId, elementId, "DISMISS"); - } - }, - - async fetchFlowParams(metricsFlowUri) { - let flowParams; - - try { - const response = await fetch(metricsFlowUri, { - credentials: "omit" - }); - - if (response.status === 200) { - const { - deviceId, - flowId, - flowBeginTime - } = await response.json(); - flowParams = { - deviceId, - flowId, - flowBeginTime - }; - } else { - console.error("Non-200 response", response); - } - } catch (e) { - flowParams = null; - } - - return flowParams; - }, - - sendEvent(type, detail) { - document.dispatchEvent(new CustomEvent(`AWPage:${type}`, { - bubbles: true, - detail - })); - }, - - getLoadingStrategyFor(url) { - return url !== null && url !== void 0 && url.startsWith("http") ? "lazy" : "eager"; - } - -}; -const DEFAULT_RTAMO_CONTENT = { - template: "return_to_amo", - utm_term: "rtamo", - content: { - position: "split", - title: { - string_id: "mr1-return-to-amo-subtitle" - }, - has_noodles: false, - subtitle: { - string_id: "mr1-return-to-amo-addon-title" - }, - backdrop: "var(--mr-welcome-background-color) var(--mr-welcome-background-gradient)", - background: "url('chrome://activity-stream/content/data/content/assets/mr-rtamo-background-image.svg') no-repeat center", - progress_bar: true, - primary_button: { - label: { - string_id: "mr1-return-to-amo-add-extension-label" - }, - source_id: "ADD_EXTENSION_BUTTON", - action: { - type: "INSTALL_ADDON_FROM_URL", - data: { - url: null, - telemetrySource: "rtamo" - } - } - }, - secondary_button: { - label: { - string_id: "onboarding-not-now-button-label" - }, - source_id: "RTAMO_START_BROWSING_BUTTON", - action: { - type: "OPEN_AWESOME_BAR" - } - }, - secondary_button_top: { - label: { - string_id: "mr1-onboarding-sign-in-button-label" - }, - source_id: "RTAMO_FXA_SIGNIN_BUTTON", - action: { - data: { - entrypoint: "activity-stream-firstrun", - where: "tab" - }, - type: "SHOW_FIREFOX_ACCOUNTS", - addFlowParams: true - } - } - } -}; - -/***/ }), -/* 4 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "MultiStageAboutWelcome": () => (/* binding */ MultiStageAboutWelcome), -/* harmony export */ "SecondaryCTA": () => (/* binding */ SecondaryCTA), -/* harmony export */ "StepsIndicator": () => (/* binding */ StepsIndicator), -/* harmony export */ "ProgressBar": () => (/* binding */ ProgressBar), -/* harmony export */ "WelcomeScreen": () => (/* binding */ WelcomeScreen) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); -/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6); -/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10); -/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18); -/* 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/. */ - - - - - - // Amount of milliseconds for all transitions to complete (including delays). - -const TRANSITION_OUT_TIME = 1000; -const LANGUAGE_MISMATCH_SCREEN_ID = "AW_LANGUAGE_MISMATCH"; -const MultiStageAboutWelcome = props => { - let { - defaultScreens - } = props; - const didFilter = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false); - const [didMount, setDidMount] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); - const [screens, setScreens] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultScreens); - const [index, setScreenIndex] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.startScreen); - const [previousOrder, setPreviousOrder] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.startScreen - 1); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - (async () => { - // If we want to load index from history state, we don't want to send impression yet - if (!didMount) { - return; - } // On about:welcome first load, screensVisited should be empty - - - let screensVisited = didFilter.current ? screens.slice(0, index) : []; - let upcomingScreens = defaultScreens.filter(s => !screensVisited.find(v => v.id === s.id)) // Filter out Language Mismatch screen from upcoming - // screens if screens set from useLanguageSwitcher hook - // has filtered language screen - .filter(upcomingScreen => !(!screens.find(s => s.id === LANGUAGE_MISMATCH_SCREEN_ID) && upcomingScreen.id === LANGUAGE_MISMATCH_SCREEN_ID)); - let filteredScreens = screensVisited.concat((await window.AWEvaluateScreenTargeting(upcomingScreens)) ?? upcomingScreens); // Use existing screen for the filtered screen to carry over any modification - // e.g. if AW_LANGUAGE_MISMATCH exists, use it from existing screens - - setScreens(filteredScreens.map(filtered => screens.find(s => s.id === filtered.id) ?? filtered)); - didFilter.current = true; - const screenInitials = filteredScreens.map(({ - id - }) => { - var _id$split$; - - return id === null || id === void 0 ? void 0 : (_id$split$ = id.split("_")[1]) === null || _id$split$ === void 0 ? void 0 : _id$split$[0]; - }).join(""); // Send impression ping when respective screen first renders - - filteredScreens.forEach((screen, order) => { - if (index === order) { - var _window$AWAddScreenIm, _window; - - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(`${props.message_id}_${order}_${screen.id}_${screenInitials}`); - (_window$AWAddScreenIm = (_window = window).AWAddScreenImpression) === null || _window$AWAddScreenIm === void 0 ? void 0 : _window$AWAddScreenIm.call(_window, screen); - } - }); // Remember that a new screen has loaded for browser navigation - - if (props.updateHistory && index > window.history.state) { - window.history.pushState(index, ""); - } // Remember the previous screen index so we can animate the transition - - - setPreviousOrder(index); - })(); - }, [index, didMount]); // eslint-disable-line react-hooks/exhaustive-deps - - const [flowParams, setFlowParams] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); - const { - metricsFlowUri - } = props; - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - (async () => { - if (metricsFlowUri) { - setFlowParams(await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.fetchFlowParams(metricsFlowUri)); - } - })(); - }, [metricsFlowUri]); // Allow "in" style to render to actually transition towards regular state, - // which also makes using browser back/forward navigation skip transitions. - - const [transition, setTransition] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.transitions ? "in" : ""); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - if (transition === "in") { - requestAnimationFrame(() => requestAnimationFrame(() => setTransition(""))); - } - }, [transition]); // Transition to next screen, opening about:home on last screen button CTA - - const handleTransition = () => { - // Only handle transitioning out from a screen once. - if (transition === "out") { - return; - } // Start transitioning things "out" immediately when moving forwards. - - - setTransition(props.transitions ? "out" : ""); // Actually move forwards after all transitions finish. - - setTimeout(() => { - if (index < screens.length - 1) { - setTransition(props.transitions ? "in" : ""); - setScreenIndex(prevState => prevState + 1); - } else { - window.AWFinish(); - } - }, props.transitions ? TRANSITION_OUT_TIME : 0); - }; - - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - // When about:welcome loads (on refresh or pressing back button - // from about:home), ensure history state usEffect runs before - // useEffect hook that send impression telemetry - setDidMount(true); - - if (props.updateHistory) { - // Switch to the screen tracked in state (null for initial state) - // or last screen index if a user navigates by pressing back - // button from about:home - const handler = ({ - state - }) => { - if (transition === "out") { - return; - } - - setTransition(props.transitions ? "out" : ""); - setTimeout(() => { - setTransition(props.transitions ? "in" : ""); - setScreenIndex(Math.min(state, screens.length - 1)); - }, props.transitions ? TRANSITION_OUT_TIME : 0); - }; // Handle page load, e.g., going back to about:welcome from about:home - - - const { - state - } = window.history; - - if (state) { - setScreenIndex(Math.min(state, screens.length - 1)); - setPreviousOrder(Math.min(state, screens.length - 1)); - } // Watch for browser back/forward button navigation events - - - window.addEventListener("popstate", handler); - return () => window.removeEventListener("popstate", handler); - } - - return false; - }, []); // eslint-disable-line react-hooks/exhaustive-deps - // Save the active multi select state for each screen as an object keyed by - // screen id. Each screen id has an array containing checkbox ids used in - // handleAction to update MULTI_ACTION data. This allows us to remember the - // state of each screen's multi select checkboxes when navigating back and - // forth between screens, while also allowing a message to have more than one - // multi select screen. - - const [activeMultiSelects, setActiveMultiSelects] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({}); // Get the active theme so the rendering code can make it selected - // by default. - - const [activeTheme, setActiveTheme] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); - const [initialTheme, setInitialTheme] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - (async () => { - let theme = await window.AWGetSelectedTheme(); - setInitialTheme(theme); - setActiveTheme(theme); - })(); - }, []); - const { - negotiatedLanguage, - langPackInstallPhase, - languageFilteredScreens - } = (0,_LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__.useLanguageSwitcher)(props.appAndSystemLocaleInfo, screens, index, setScreenIndex); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - setScreens(languageFilteredScreens); - }, [languageFilteredScreens]); - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `outer-wrapper onboardingContainer proton transition-${transition}`, - style: props.backdrop ? { - background: props.backdrop - } : {} - }, screens.map((screen, order) => { - const isFirstScreen = screen === screens[0]; - const isLastScreen = screen === screens[screens.length - 1]; - const totalNumberOfScreens = screens.length; - const isSingleScreen = totalNumberOfScreens === 1; - - const setActiveMultiSelect = valueOrFn => setActiveMultiSelects(prevState => ({ ...prevState, - [screen.id]: typeof valueOrFn === "function" ? valueOrFn(prevState[screen.id]) : valueOrFn - })); - - return index === order ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(WelcomeScreen, { - key: screen.id + order, - id: screen.id, - totalNumberOfScreens: totalNumberOfScreens, - isFirstScreen: isFirstScreen, - isLastScreen: isLastScreen, - isSingleScreen: isSingleScreen, - order: order, - previousOrder: previousOrder, - content: screen.content, - navigate: handleTransition, - messageId: `${props.message_id}_${order}_${screen.id}`, - UTMTerm: props.utm_term, - flowParams: flowParams, - activeTheme: activeTheme, - initialTheme: initialTheme, - setActiveTheme: setActiveTheme, - setInitialTheme: setInitialTheme, - activeMultiSelect: activeMultiSelects[screen.id], - setActiveMultiSelect: setActiveMultiSelect, - autoAdvance: screen.auto_advance, - negotiatedLanguage: negotiatedLanguage, - langPackInstallPhase: langPackInstallPhase, - forceHideStepsIndicator: screen.force_hide_steps_indicator, - ariaRole: props.ariaRole, - aboveButtonStepsIndicator: screen.above_button_steps_indicator - }) : null; - }))); -}; -const SecondaryCTA = props => { - var _props$content$second, _props$content$tiles, _props$content$second2; - - const targetElement = props.position ? `secondary_button_${props.position}` : `secondary_button`; - let buttonStyling = (_props$content$second = props.content.secondary_button) !== null && _props$content$second !== void 0 && _props$content$second.has_arrow_icon ? `secondary arrow-icon` : `secondary`; - const isTextLink = !["split", "callout"].includes(props.content.position) && ((_props$content$tiles = props.content.tiles) === null || _props$content$tiles === void 0 ? void 0 : _props$content$tiles.type) !== "addons-picker"; - const isPrimary = ((_props$content$second2 = props.content.secondary_button) === null || _props$content$second2 === void 0 ? void 0 : _props$content$second2.style) === "primary"; - - if (isTextLink) { - buttonStyling += " text-link"; - } - - if (isPrimary) { - var _props$content$second3; - - buttonStyling = (_props$content$second3 = props.content.secondary_button) !== null && _props$content$second3 !== void 0 && _props$content$second3.has_arrow_icon ? `primary arrow-icon` : `primary`; - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: props.position ? `secondary-cta ${props.position}` : "secondary-cta" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: props.content[targetElement].text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: props.content[targetElement].label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: buttonStyling, - value: targetElement, - onClick: props.handleAction - }))); -}; -const StepsIndicator = props => { - let steps = []; - - for (let i = 0; i < props.totalNumberOfScreens; i++) { - let className = `${i === props.order ? "current" : ""} ${i < props.order ? "complete" : ""}`; - steps.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - key: i, - className: `indicator ${className}`, - role: "presentation" - })); - } - - return steps; -}; -const ProgressBar = ({ - step, - previousStep, - totalNumberOfScreens -}) => { - const [progress, setProgress] = react__WEBPACK_IMPORTED_MODULE_0___default().useState(previousStep / totalNumberOfScreens); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - // We don't need to hook any dependencies because any time the step changes, - // the screen's entire DOM tree will be re-rendered. - setProgress(step / totalNumberOfScreens); - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "indicator", - role: "presentation", - style: { - "--progress-bar-progress": `${progress * 100}%` - } - }); -}; -class WelcomeScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) { - constructor(props) { - super(props); - this.handleAction = this.handleAction.bind(this); - } - - handleOpenURL(action, flowParams, UTMTerm) { - let { - type, - data - } = action; - - if (type === "SHOW_FIREFOX_ACCOUNTS") { - let params = { ..._asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__.BASE_PARAMS, - utm_term: `${UTMTerm}-screen` - }; - - if (action.addFlowParams && flowParams) { - params = { ...params, - ...flowParams - }; - } - - data = { ...data, - extraParams: params - }; - } else if (type === "OPEN_URL") { - let url = new URL(data.args); - (0,_asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_5__.addUtmParams)(url, `${UTMTerm}-screen`); - - if (action.addFlowParams && flowParams) { - url.searchParams.append("device_id", flowParams.deviceId); - url.searchParams.append("flow_id", flowParams.flowId); - url.searchParams.append("flow_begin_time", flowParams.flowBeginTime); - } - - data = { ...data, - args: url.toString() - }; - } - - return _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction({ - type, - data - }); - } - - async handleAction(event) { - let { - props - } = this; - const value = event.currentTarget.value ?? event.currentTarget.getAttribute("value"); - const source = event.source || value; - let targetContent = props.content[value] || props.content.tiles || props.content.languageSwitcher; - - if (!(targetContent && targetContent.action)) { - return; - } // Send telemetry before waiting on actions - - - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name); // Send additional telemetry if a messaging surface like feature callout is - // dismissed via the dismiss button. Other causes of dismissal will be - // handled separately by the messaging surface's own code. - - if (value === "dismiss_button" && !event.name) { - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source); - } - - let { - action - } = targetContent; - action = JSON.parse(JSON.stringify(action)); - - if (action.collectSelect) { - var _action$data; - - // Populate MULTI_ACTION data actions property with selected checkbox - // actions from tiles data - if (action.type !== "MULTI_ACTION") { - console.error("collectSelect is only supported for MULTI_ACTION type actions"); - action.type = "MULTI_ACTION"; - } - - if (!Array.isArray((_action$data = action.data) === null || _action$data === void 0 ? void 0 : _action$data.actions)) { - console.error("collectSelect is only supported for MULTI_ACTION type actions with an array of actions"); - action.data = { - actions: [] - }; - } // Prepend the multi-select actions to the CTA's actions array, but keep - // the actions in the same order they appear in. This way the CTA action - // can go last, after the multi-select actions are processed. For example, - // 1. checkbox action 1 - // 2. checkbox action 2 - // 3. radio action - // 4. CTA action (which perhaps depends on the radio action) - - - let multiSelectActions = []; - - for (const checkbox of ((_props$content = props.content) === null || _props$content === void 0 ? void 0 : (_props$content$tiles2 = _props$content.tiles) === null || _props$content$tiles2 === void 0 ? void 0 : _props$content$tiles2.data) ?? []) { - var _props$content, _props$content$tiles2, _this$props$activeMul; - - let checkboxAction; - - if ((_this$props$activeMul = this.props.activeMultiSelect) !== null && _this$props$activeMul !== void 0 && _this$props$activeMul.includes(checkbox.id)) { - checkboxAction = checkbox.checkedAction ?? checkbox.action; - } else { - checkboxAction = checkbox.uncheckedAction; - } - - if (checkboxAction) { - multiSelectActions.push(checkboxAction); - } - } - - action.data.actions.unshift(...multiSelectActions); // Send telemetry with selected checkbox ids - - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, props.activeMultiSelect, "SELECT_CHECKBOX"); - } - - let actionResult; - - if (["OPEN_URL", "SHOW_FIREFOX_ACCOUNTS"].includes(action.type)) { - actionResult = await this.handleOpenURL(action, props.flowParams, props.UTMTerm); - } else if (action.type) { - actionResult = await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(action); - - if (action.type === "FXA_SIGNIN_FLOW") { - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, actionResult ? "sign_in" : "sign_in_cancel", "FXA_SIGNIN_FLOW"); - } // Wait until migration closes to complete the action - - - const hasMigrate = a => { - var _a$data, _a$data$actions; - - return a.type === "SHOW_MIGRATION_WIZARD" || a.type === "MULTI_ACTION" && ((_a$data = a.data) === null || _a$data === void 0 ? void 0 : (_a$data$actions = _a$data.actions) === null || _a$data$actions === void 0 ? void 0 : _a$data$actions.some(hasMigrate)); - }; - - if (hasMigrate(action)) { - await window.AWWaitForMigrationClose(); - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close"); - } - } // A special tiles.action.theme value indicates we should use the event's value vs provided value. - - - if (action.theme) { - let themeToUse = action.theme === "" ? event.currentTarget.value : this.props.initialTheme || action.theme; - this.props.setActiveTheme(themeToUse); - window.AWSelectTheme(themeToUse); - } // If the action has persistActiveTheme: true, we set the initial theme to the currently active theme - // so that it can be reverted to in the event that the user navigates away from the screen - - - if (action.persistActiveTheme) { - this.props.setInitialTheme(this.props.activeTheme); - } // `navigate` and `dismiss` can be true/false/undefined, or they can be a - // string "actionResult" in which case we should use the actionResult - // (boolean resolved by handleUserAction) - - - const shouldDoBehavior = behavior => behavior === "actionResult" ? actionResult : behavior; - - if (shouldDoBehavior(action.navigate)) { - props.navigate(); - } - - if (shouldDoBehavior(action.dismiss)) { - window.AWFinish(); - } - } - - render() { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__.MultiStageProtonScreen, { - content: this.props.content, - id: this.props.id, - order: this.props.order, - previousOrder: this.props.previousOrder, - activeTheme: this.props.activeTheme, - activeMultiSelect: this.props.activeMultiSelect, - setActiveMultiSelect: this.props.setActiveMultiSelect, - totalNumberOfScreens: this.props.totalNumberOfScreens, - appAndSystemLocaleInfo: this.props.appAndSystemLocaleInfo, - negotiatedLanguage: this.props.negotiatedLanguage, - langPackInstallPhase: this.props.langPackInstallPhase, - handleAction: this.handleAction, - messageId: this.props.messageId, - isFirstScreen: this.props.isFirstScreen, - isLastScreen: this.props.isLastScreen, - isSingleScreen: this.props.isSingleScreen, - startsWithCorner: this.props.startsWithCorner, - autoAdvance: this.props.autoAdvance, - forceHideStepsIndicator: this.props.forceHideStepsIndicator, - ariaRole: this.props.ariaRole, - aboveButtonStepsIndicator: this.props.aboveButtonStepsIndicator - }); - } - -} - -/***/ }), -/* 5 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "CONFIGURABLE_STYLES": () => (/* binding */ CONFIGURABLE_STYLES), -/* harmony export */ "Localized": () => (/* binding */ Localized) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ - -const CONFIGURABLE_STYLES = ["color", "fontSize", "fontWeight", "letterSpacing", "lineHeight", "marginBlock", "marginInline", "paddingBlock", "paddingInline", "whiteSpace"]; -const ZAP_SIZE_THRESHOLD = 160; -/** - * Based on the .text prop, localizes an inner element if a string_id - * is provided, OR renders plain text, OR hides it if nothing is provided. - * Allows configuring of some styles including zap underline and color. - * - * Examples: - * - * Localized text - * ftl: - * title = Welcome - * jsx: - *

- * output: - *

Welcome

- * - * Unlocalized text - * jsx: - *

- *

- * output: - *

Welcome

- */ - -const Localized = ({ - text, - children -}) => { - // Dynamically determine the size of the zap style. - const zapRef = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createRef(); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - const { - current - } = zapRef; - - if (current) { - requestAnimationFrame(() => current === null || current === void 0 ? void 0 : current.classList.replace("short", current.getBoundingClientRect().width > ZAP_SIZE_THRESHOLD ? "long" : "short")); - } - }); // Skip rendering of children with no text. - - if (!text) { - return null; - } // Allow augmenting existing child container properties. - - - const props = { - children: [], - className: "", - style: {}, - ...(children === null || children === void 0 ? void 0 : children.props) - }; // Support nested Localized by starting with their children. - - const textNodes = Array.isArray(props.children) ? props.children : [props.children]; // Pick desired fluent or raw/plain text to render. - - if (text.string_id) { - // Set the key so React knows not to reuse when switching to plain text. - props.key = text.string_id; - props["data-l10n-id"] = text.string_id; - - if (text.args) { - props["data-l10n-args"] = JSON.stringify(text.args); - } - } else if (text.raw) { - textNodes.push(text.raw); - } else if (typeof text === "string") { - textNodes.push(text); - } // Add zap style and content in a way that allows fluent to insert too. - - - if (text.zap) { - props.className += " welcomeZap"; - textNodes.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { - className: "short zap", - "data-l10n-name": "zap", - ref: zapRef - }, text.zap)); - } - - if (text.aria_label) { - props["aria-label"] = text.aria_label; - } // Apply certain configurable styles. - - - CONFIGURABLE_STYLES.forEach(style => { - if (text[style] !== undefined) { - props.style[style] = text[style]; - } - }); - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().cloneElement( // Provide a default container for the text if necessary. - children ?? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", null), props, // Conditionally pass in as void elements can't accept empty array. - textNodes.length ? textNodes : null); -}; - -/***/ }), -/* 6 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "MultiStageProtonScreen": () => (/* binding */ MultiStageProtonScreen), -/* harmony export */ "ProtonScreenActionButtons": () => (/* binding */ ProtonScreenActionButtons), -/* harmony export */ "ProtonScreen": () => (/* binding */ ProtonScreen) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); -/* harmony import */ var _MobileDownloads__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7); -/* harmony import */ var _MultiSelect__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8); -/* harmony import */ var _Themes__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9); -/* harmony import */ var _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4); -/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(10); -/* harmony import */ var _CTAParagraph__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(11); -/* harmony import */ var _HeroImage__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(12); -/* harmony import */ var _OnboardingVideo__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(13); -/* harmony import */ var _AdditionalCTA__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(14); -/* harmony import */ var _EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(15); -/* harmony import */ var _AddonsPicker__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(16); -/* harmony import */ var _LinkParagraph__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(17); -/* 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/. */ - - - - - - - - - - - - - - - -const MultiStageProtonScreen = props => { - const { - autoAdvance, - handleAction, - order - } = props; - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - if (autoAdvance) { - const timer = setTimeout(() => { - handleAction({ - currentTarget: { - value: autoAdvance - }, - name: "AUTO_ADVANCE" - }); - }, 20000); - return () => clearTimeout(timer); - } - - return () => {}; - }, [autoAdvance, handleAction, order]); - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ProtonScreen, { - content: props.content, - id: props.id, - order: props.order, - activeTheme: props.activeTheme, - activeMultiSelect: props.activeMultiSelect, - setActiveMultiSelect: props.setActiveMultiSelect, - totalNumberOfScreens: props.totalNumberOfScreens, - handleAction: props.handleAction, - isFirstScreen: props.isFirstScreen, - isLastScreen: props.isLastScreen, - isSingleScreen: props.isSingleScreen, - previousOrder: props.previousOrder, - autoAdvance: props.autoAdvance, - isRtamo: props.isRtamo, - addonName: props.addonName, - isTheme: props.isTheme, - iconURL: props.iconURL, - messageId: props.messageId, - negotiatedLanguage: props.negotiatedLanguage, - langPackInstallPhase: props.langPackInstallPhase, - forceHideStepsIndicator: props.forceHideStepsIndicator, - ariaRole: props.ariaRole, - aboveButtonStepsIndicator: props.aboveButtonStepsIndicator - }); -}; -const ProtonScreenActionButtons = props => { - var _content$checkbox, _content$primary_butt, _content$additional_b, _content$primary_butt2, _content$primary_butt3, _content$primary_butt4, _content$primary_butt5; - - const { - content, - addonName, - activeMultiSelect - } = props; - const defaultValue = (_content$checkbox = content.checkbox) === null || _content$checkbox === void 0 ? void 0 : _content$checkbox.defaultValue; - const [isChecked, setIsChecked] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(defaultValue || false); - const buttonRef = react__WEBPACK_IMPORTED_MODULE_0___default().useRef(null); - const shouldFocusButton = content === null || content === void 0 ? void 0 : (_content$primary_butt = content.primary_button) === null || _content$primary_butt === void 0 ? void 0 : _content$primary_butt.should_focus_button; - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - if (shouldFocusButton) { - var _buttonRef$current; - - (_buttonRef$current = buttonRef.current) === null || _buttonRef$current === void 0 ? void 0 : _buttonRef$current.focus(); - } - }, [shouldFocusButton]); - - if (!content.primary_button && !content.secondary_button && !content.additional_button) { - return null; - } // If we have a multi-select screen, we want to disable the primary button - // until the user has selected at least one item. - - - const isPrimaryDisabled = primaryDisabledValue => primaryDisabledValue === "hasActiveMultiSelect" ? !((activeMultiSelect === null || activeMultiSelect === void 0 ? void 0 : activeMultiSelect.length) > 0) : primaryDisabledValue; - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `action-buttons ${content.additional_button ? "additional-cta-container" : ""}`, - flow: (_content$additional_b = content.additional_button) === null || _content$additional_b === void 0 ? void 0 : _content$additional_b.flow - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: (_content$primary_butt2 = content.primary_button) === null || _content$primary_butt2 === void 0 ? void 0 : _content$primary_butt2.label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - ref: buttonRef, - className: `${((_content$primary_butt3 = content.primary_button) === null || _content$primary_butt3 === void 0 ? void 0 : _content$primary_butt3.style) ?? "primary"}${(_content$primary_butt4 = content.primary_button) !== null && _content$primary_butt4 !== void 0 && _content$primary_butt4.has_arrow_icon ? " arrow-icon" : ""}` // Whether or not the checkbox is checked determines which action - // should be handled. By setting value here, we indicate to - // this.handleAction() where in the content tree it should take - // the action to execute from. - , - value: isChecked ? "checkbox" : "primary_button", - disabled: isPrimaryDisabled((_content$primary_butt5 = content.primary_button) === null || _content$primary_butt5 === void 0 ? void 0 : _content$primary_butt5.disabled), - onClick: props.handleAction, - "data-l10n-args": addonName ? JSON.stringify({ - "addon-name": addonName - }) : "" - })), content.additional_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AdditionalCTA__WEBPACK_IMPORTED_MODULE_11__.AdditionalCTA, { - content: content, - handleAction: props.handleAction - }) : null, content.checkbox ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "checkbox-container" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { - type: "checkbox", - id: "action-checkbox", - checked: isChecked, - onChange: () => { - setIsChecked(!isChecked); - } - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.checkbox.label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", { - htmlFor: "action-checkbox" - }))) : null, content.secondary_button ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.SecondaryCTA, { - content: content, - handleAction: props.handleAction - }) : null); -}; -class ProtonScreen extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) { - componentDidMount() { - this.mainContentHeader.focus(); - } - - getScreenClassName(isFirstScreen, isLastScreen, includeNoodles, isVideoOnboarding, isAddonsPicker) { - const screenClass = `screen-${this.props.order % 2 !== 0 ? 1 : 2}`; - - if (isVideoOnboarding) { - return "with-video"; - } - - if (isAddonsPicker) { - return "addons-picker"; - } - - return `${isFirstScreen ? `dialog-initial` : ``} ${isLastScreen ? `dialog-last` : ``} ${includeNoodles ? `with-noodles` : ``} ${screenClass}`; - } - - renderTitle({ - title, - title_logo - }) { - if (title_logo) { - const { - alignment, - ...rest - } = title_logo; - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "inline-icon-container", - alignment: alignment ?? "center" - }, this.renderPicture({ ...rest - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: title - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h1", { - id: "mainContentHeader" - }))); - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: title - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h1", { - id: "mainContentHeader" - })); - } - - renderPicture({ - imageURL = "chrome://branding/content/about-logo.svg", - darkModeImageURL, - reducedMotionImageURL, - darkModeReducedMotionImageURL, - alt = "", - width, - height, - marginBlock, - marginInline, - className = "logo-container" - }) { - function getLoadingStrategy() { - for (let url of [imageURL, darkModeImageURL, reducedMotionImageURL, darkModeReducedMotionImageURL]) { - if (_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(url) === "lazy") { - return "lazy"; - } - } - - return "eager"; - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("picture", { - className: className, - style: { - marginInline, - marginBlock - } - }, darkModeReducedMotionImageURL ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("source", { - srcSet: darkModeReducedMotionImageURL, - media: "(prefers-color-scheme: dark) and (prefers-reduced-motion: reduce)" - }) : null, darkModeImageURL ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("source", { - srcSet: darkModeImageURL, - media: "(prefers-color-scheme: dark)" - }) : null, reducedMotionImageURL ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("source", { - srcSet: reducedMotionImageURL, - media: "(prefers-reduced-motion: reduce)" - }) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: alt - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "sr-only logo-alt" - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - className: "brand-logo", - style: { - height, - width - }, - src: imageURL, - alt: "", - loading: getLoadingStrategy(), - role: alt ? null : "presentation" - })); - } - - renderContentTiles() { - const { - content - } = this.props; - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, content.tiles && content.tiles.type === "addons-picker" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_AddonsPicker__WEBPACK_IMPORTED_MODULE_13__.AddonsPicker, { - content: content, - message_id: this.props.messageId, - handleAction: this.props.handleAction - }) : null, content.tiles && content.tiles.type === "theme" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Themes__WEBPACK_IMPORTED_MODULE_5__.Themes, { - content: content, - activeTheme: this.props.activeTheme, - handleAction: this.props.handleAction - }) : null, content.tiles && content.tiles.type === "mobile_downloads" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MobileDownloads__WEBPACK_IMPORTED_MODULE_3__.MobileDownloads, { - data: content.tiles.data, - handleAction: this.props.handleAction - }) : null, content.tiles && content.tiles.type === "multiselect" && content.tiles.data ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiSelect__WEBPACK_IMPORTED_MODULE_4__.MultiSelect, { - content: content, - activeMultiSelect: this.props.activeMultiSelect, - setActiveMultiSelect: this.props.setActiveMultiSelect, - handleAction: this.props.handleAction - }) : null, content.tiles && content.tiles.type === "migration-wizard" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_EmbeddedMigrationWizard__WEBPACK_IMPORTED_MODULE_12__.EmbeddedMigrationWizard, { - handleAction: this.props.handleAction - }) : null); - } - - renderNoodles() { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "noodle orange-L" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "noodle purple-C" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "noodle solid-L" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "noodle outline-L" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "noodle yellow-circle" - })); - } - - renderLanguageSwitcher() { - return this.props.content.languageSwitcher ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LanguageSwitcher__WEBPACK_IMPORTED_MODULE_7__.LanguageSwitcher, { - content: this.props.content, - handleAction: this.props.handleAction, - negotiatedLanguage: this.props.negotiatedLanguage, - langPackInstallPhase: this.props.langPackInstallPhase, - messageId: this.props.messageId - }) : null; - } - - renderDismissButton() { - const { - size, - marginBlock, - marginInline, - label - } = this.props.content.dismiss_button; - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: "dismiss-button", - onClick: this.props.handleAction, - value: "dismiss_button", - "data-l10n-id": (label === null || label === void 0 ? void 0 : label.string_id) || "spotlight-dialog-close-button", - "button-size": size, - style: { - marginBlock, - marginInline - } - }); - } - - renderStepsIndicator() { - var _content$steps_indica; - - const currentStep = (this.props.order ?? 0) + 1; - const previousStep = (this.props.previousOrder ?? -1) + 1; - const { - content, - totalNumberOfScreens: total - } = this.props; - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - id: "steps", - className: `steps${content.progress_bar ? " progress-bar" : ""}`, - "data-l10n-id": ((_content$steps_indica = content.steps_indicator) === null || _content$steps_indica === void 0 ? void 0 : _content$steps_indica.string_id) || "onboarding-welcome-steps-indicator-label", - "data-l10n-args": JSON.stringify({ - current: currentStep, - total: total ?? 0 - }), - "data-l10n-attrs": "aria-label", - role: "progressbar", - "aria-valuenow": currentStep, - "aria-valuemin": 1, - "aria-valuemax": total - }, content.progress_bar ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.ProgressBar, { - step: currentStep, - previousStep: previousStep, - totalNumberOfScreens: total - }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.StepsIndicator, { - order: this.props.order, - totalNumberOfScreens: total - })); - } - - renderSecondarySection(content) { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `section-secondary ${content.hide_secondary_section ? "with-secondary-section-hidden" : ""}`, - style: content.background ? { - background: content.background, - "--mr-secondary-background-position-y": content.split_narrow_bkg_position - } : {} - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.image_alt_text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "sr-only image-alt", - role: "img" - })), content.hero_image ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_HeroImage__WEBPACK_IMPORTED_MODULE_9__.HeroImage, { - url: content.hero_image.url - }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "message-text" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "spacer-top" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.hero_text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h1", null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "spacer-bottom" - })))); - } - - renderOrderedContent(content) { - const elements = []; - - for (const item of content) { - switch (item.type) { - case "text": - elements.push( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_LinkParagraph__WEBPACK_IMPORTED_MODULE_14__.LinkParagraph, { - text_content: item, - handleAction: this.props.handleAction - })); - break; - - case "image": - elements.push(this.renderPicture({ - imageURL: item.url, - darkModeImageURL: item.darkModeImageURL, - height: item.height, - width: item.width, - alt: item.alt_text, - marginInline: item.marginInline, - className: "inline-image" - })); - } - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, elements); - } - - render() { - var _content$tiles, _content$tiles2, _this$props$appAndSys, _this$props$messageId; - - const { - autoAdvance, - content, - isRtamo, - isTheme, - isFirstScreen, - isLastScreen, - isSingleScreen, - forceHideStepsIndicator, - ariaRole, - aboveButtonStepsIndicator - } = this.props; - const includeNoodles = content.has_noodles; // The default screen position is "center" - - const isCenterPosition = content.position === "center" || !content.position; - const hideStepsIndicator = autoAdvance || (content === null || content === void 0 ? void 0 : content.video_container) || isSingleScreen || forceHideStepsIndicator; - const textColorClass = content.text_color ? `${content.text_color}-text` : ""; // Assign proton screen style 'screen-1' or 'screen-2' to centered screens - // by checking if screen order is even or odd. - - const screenClassName = isCenterPosition ? this.getScreenClassName(isFirstScreen, isLastScreen, includeNoodles, content === null || content === void 0 ? void 0 : content.video_container, ((_content$tiles = content.tiles) === null || _content$tiles === void 0 ? void 0 : _content$tiles.type) === "addons-picker") : ""; - const isEmbeddedMigration = ((_content$tiles2 = content.tiles) === null || _content$tiles2 === void 0 ? void 0 : _content$tiles2.type) === "migration-wizard"; - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("main", { - className: `screen ${this.props.id || ""} - ${screenClassName} ${textColorClass}`, - role: ariaRole ?? "alertdialog", - layout: content.layout, - pos: content.position || "center", - tabIndex: "-1", - "aria-labelledby": "mainContentHeader", - ref: input => { - this.mainContentHeader = input; - } - }, isCenterPosition ? null : this.renderSecondarySection(content), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `section-main ${isEmbeddedMigration ? "embedded-migration" : ""}`, - "hide-secondary-section": content.hide_secondary_section ? String(content.hide_secondary_section) : null, - role: "document" - }, content.secondary_button_top ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__.SecondaryCTA, { - content: content, - handleAction: this.props.handleAction, - position: "top" - }) : null, includeNoodles ? this.renderNoodles() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `main-content ${hideStepsIndicator ? "no-steps" : ""}`, - style: { - background: content.background && isCenterPosition ? content.background : null, - width: content.width && content.position !== "split" ? content.width : null - } - }, content.logo ? this.renderPicture(content.logo) : null, isRtamo ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "rtamo-icon" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - className: `${isTheme ? "rtamo-theme-icon" : "brand-logo"}`, - src: this.props.iconURL, - loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(this.props.iconURL), - alt: "", - role: "presentation" - })) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "main-content-inner" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `welcome-text ${content.title_style || ""}` - }, content.title ? this.renderTitle(content) : null, content.subtitle ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.subtitle - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h2", { - "data-l10n-args": JSON.stringify({ - "addon-name": this.props.addonName, - ...((_this$props$appAndSys = this.props.appAndSystemLocaleInfo) === null || _this$props$appAndSys === void 0 ? void 0 : _this$props$appAndSys.displayNames) - }), - "aria-flowto": (_this$props$messageId = this.props.messageId) !== null && _this$props$messageId !== void 0 && _this$props$messageId.includes("FEATURE_TOUR") ? "steps" : "" - })) : null, content.cta_paragraph ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_CTAParagraph__WEBPACK_IMPORTED_MODULE_8__.CTAParagraph, { - content: content.cta_paragraph, - handleAction: this.props.handleAction - }) : null), content.video_container ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_OnboardingVideo__WEBPACK_IMPORTED_MODULE_10__.OnboardingVideo, { - content: content.video_container, - handleAction: this.props.handleAction - }) : null, content.above_button_content ? this.renderOrderedContent(content.above_button_content) : null, this.renderContentTiles(), this.renderLanguageSwitcher(), !hideStepsIndicator && aboveButtonStepsIndicator ? this.renderStepsIndicator() : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ProtonScreenActionButtons, { - content: content, - addonName: this.props.addonName, - handleAction: this.props.handleAction, - activeMultiSelect: this.props.activeMultiSelect - })), !hideStepsIndicator && !aboveButtonStepsIndicator ? this.renderStepsIndicator() : null), content.dismiss_button ? this.renderDismissButton() : null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.info_text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { - className: "info-text" - }))); - } - -} - -/***/ }), -/* 7 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "MarketplaceButtons": () => (/* binding */ MarketplaceButtons), -/* harmony export */ "MobileDownloads": () => (/* binding */ MobileDownloads) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); -/* 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/. */ - - - -const MarketplaceButtons = props => { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("ul", { - className: "mobile-download-buttons" - }, props.buttons.includes("ios") ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", { - className: "ios" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - "data-l10n-id": "spotlight-ios-marketplace-button", - value: "ios", - onClick: props.handleAction - })) : null, props.buttons.includes("android") ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", { - className: "android" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - "data-l10n-id": "spotlight-android-marketplace-button", - value: "android", - onClick: props.handleAction - })) : null); -}; -const MobileDownloads = props => { - const { - QR_code: QRCode - } = props.data; - const showEmailLink = props.data.email && window.AWSendToDeviceEmailsSupported(); - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "mobile-downloads" - }, QRCode ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - "data-l10n-id": QRCode.alt_text.string_id ? QRCode.alt_text.string_id : null, - className: "qr-code-image", - alt: typeof QRCode.alt_text === "string" ? QRCode.alt_text : "", - src: QRCode.image_url, - loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(QRCode.image_url) - }) : null, showEmailLink ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: props.data.email.link_text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: "email-link", - value: "email_link", - onClick: props.handleAction - }))) : null, props.data.marketplace_buttons ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(MarketplaceButtons, { - buttons: props.data.marketplace_buttons, - handleAction: props.handleAction - }) : null); -}; - -/***/ }), -/* 8 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "MultiSelect": () => (/* binding */ MultiSelect) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* 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/. */ - - -const MULTI_SELECT_STYLES = [..._MSLocalized__WEBPACK_IMPORTED_MODULE_1__.CONFIGURABLE_STYLES, "flexDirection", "flexWrap", "flexFlow", "flexGrow", "flexShrink", "justifyContent", "alignItems", "gap"]; -const MULTI_SELECT_ICON_STYLES = [..._MSLocalized__WEBPACK_IMPORTED_MODULE_1__.CONFIGURABLE_STYLES, "width", "height", "background", "backgroundColor", "backgroundImage", "backgroundSize", "backgroundPosition", "backgroundRepeat", "backgroundOrigin", "backgroundClip", "border", "borderRadius", "appearance", "fill", "stroke", "outline", "outlineOffset", "boxShadow"]; - -function getValidStyle(style, validStyles, allowVars) { - if (!style) { - return null; - } - - return Object.keys(style).filter(key => validStyles.includes(key) || allowVars && key.startsWith("--")).reduce((obj, key) => { - obj[key] = style[key]; - return obj; - }, {}); -} - -const MultiSelect = ({ - content, - activeMultiSelect, - setActiveMultiSelect -}) => { - const { - data - } = content.tiles; - const refs = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)({}); - const handleChange = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => { - const newActiveMultiSelect = []; - Object.keys(refs.current).forEach(key => { - var _refs$current$key; - - if ((_refs$current$key = refs.current[key]) !== null && _refs$current$key !== void 0 && _refs$current$key.checked) { - newActiveMultiSelect.push(key); - } - }); - setActiveMultiSelect(newActiveMultiSelect); - }, [setActiveMultiSelect]); - const containerStyle = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => getValidStyle(content.tiles.style, MULTI_SELECT_STYLES, true), [content.tiles.style]); // When screen renders for first time, update state - // with checkbox ids that has defaultvalue true - - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - if (!activeMultiSelect) { - let newActiveMultiSelect = []; - data.forEach(({ - id, - defaultValue - }) => { - if (defaultValue && id) { - newActiveMultiSelect.push(id); - } - }); - setActiveMultiSelect(newActiveMultiSelect); - } - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "multi-select-container", - style: containerStyle - }, data.map(({ - id, - label, - icon, - type = "checkbox", - group, - style - }) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - key: id + label, - className: "checkbox-container multi-select-item", - style: getValidStyle(style, MULTI_SELECT_STYLES) - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { - type: type // checkbox or radio - , - id: id, - value: id, - name: group, - checked: activeMultiSelect === null || activeMultiSelect === void 0 ? void 0 : activeMultiSelect.includes(id), - style: getValidStyle(icon === null || icon === void 0 ? void 0 : icon.style, MULTI_SELECT_ICON_STYLES), - onChange: handleChange, - ref: el => refs.current[id] = el - }), label ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", { - htmlFor: id - })) : null))); -}; - -/***/ }), -/* 9 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "Themes": () => (/* binding */ Themes) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* 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/. */ - - -const Themes = props => { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "tiles-theme-container" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("fieldset", { - className: "tiles-theme-section" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: props.content.subtitle - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("legend", { - className: "sr-only" - })), props.content.tiles.data.map(({ - theme, - label, - tooltip, - description - }) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - key: theme + label, - text: typeof tooltip === "object" ? tooltip : {} - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("label", { - className: "theme", - title: theme + label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: typeof description === "object" ? description : {} - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("input", { - type: "radio", - value: theme, - name: "theme", - checked: theme === props.activeTheme, - className: "sr-only input", - onClick: props.handleAction - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: `icon ${theme === props.activeTheme ? " selected" : ""} ${theme}` - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "text" - })))))))); -}; - -/***/ }), -/* 10 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "useLanguageSwitcher": () => (/* binding */ useLanguageSwitcher), -/* harmony export */ "LanguageSwitcher": () => (/* binding */ LanguageSwitcher) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); -/* 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 language switcher implements a hook that should be placed at a higher level - * than the actual language switcher component, as it needs to preemptively fetch - * and install langpacks for the user if there is a language mismatch screen. - */ - -function useLanguageSwitcher(appAndSystemLocaleInfo, screens, screenIndex, setScreenIndex) { - const languageMismatchScreenIndex = screens.findIndex(({ - id - }) => id === "AW_LANGUAGE_MISMATCH"); - const screen = screens[languageMismatchScreenIndex]; // Ensure fluent messages have the negotiatedLanguage args set, as they are rendered - // before the negotiatedLanguage is known. If the arg isn't present then Firefox will - // crash in development mode. - - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - var _screen$content; - - if (screen !== null && screen !== void 0 && (_screen$content = screen.content) !== null && _screen$content !== void 0 && _screen$content.languageSwitcher) { - for (const text of Object.values(screen.content.languageSwitcher)) { - if (text !== null && text !== void 0 && text.args && text.args.negotiatedLanguage === undefined) { - text.args.negotiatedLanguage = ""; - } - } - } - }, [screen]); // If there is a mismatch, then Firefox can negotiate a better langpack to offer - // the user. - - const [negotiatedLanguage, setNegotiatedLanguage] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function getNegotiatedLanguage() { - if (!appAndSystemLocaleInfo) { - return; - } - - if (appAndSystemLocaleInfo.matchType !== "language-mismatch") { - // There is no language mismatch, so there is no need to negotiate a langpack. - return; - } - - (async () => { - const { - langPack, - langPackDisplayName - } = await window.AWNegotiateLangPackForLanguageMismatch(appAndSystemLocaleInfo); - - if (langPack) { - setNegotiatedLanguage({ - langPackDisplayName, - appDisplayName: appAndSystemLocaleInfo.displayNames.appLanguage, - langPack, - requestSystemLocales: [langPack.target_locale, appAndSystemLocaleInfo.appLocaleRaw], - originalAppLocales: [appAndSystemLocaleInfo.appLocaleRaw] - }); - } else { - setNegotiatedLanguage({ - langPackDisplayName: null, - appDisplayName: null, - langPack: null, - requestSystemLocales: null - }); - } - })(); - }, [appAndSystemLocaleInfo]); - /** - * @type { - * "before-installation" - * | "installing" - * | "installed" - * | "installation-error" - * | "none-available" - * } - */ - - const [langPackInstallPhase, setLangPackInstallPhase] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("before-installation"); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function ensureLangPackInstalled() { - if (!negotiatedLanguage) { - // There are no negotiated languages to download yet. - return; - } - - setLangPackInstallPhase("installing"); - window.AWEnsureLangPackInstalled(negotiatedLanguage, screen === null || screen === void 0 ? void 0 : screen.content).then(content => { - // Update screen content with strings that might have changed. - screen.content = content; - setLangPackInstallPhase("installed"); - }, error => { - console.error(error); - setLangPackInstallPhase("installation-error"); - }); - }, [negotiatedLanguage, screen]); - const [languageFilteredScreens, setLanguageFilteredScreens] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(screens); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function filterScreen() { - // Remove the language screen if it exists (already removed for no live - // reload) and we either don't-need-to or can't switch. - if (screen && ((appAndSystemLocaleInfo === null || appAndSystemLocaleInfo === void 0 ? void 0 : appAndSystemLocaleInfo.matchType) !== "language-mismatch" || (negotiatedLanguage === null || negotiatedLanguage === void 0 ? void 0 : negotiatedLanguage.langPack) === null)) { - if (screenIndex > languageMismatchScreenIndex) { - setScreenIndex(screenIndex - 1); - } - - setLanguageFilteredScreens(screens.filter(s => s.id !== "AW_LANGUAGE_MISMATCH")); - } else { - setLanguageFilteredScreens(screens); - } - }, [appAndSystemLocaleInfo === null || appAndSystemLocaleInfo === void 0 ? void 0 : appAndSystemLocaleInfo.matchType, languageMismatchScreenIndex, negotiatedLanguage, screen, screenIndex, screens, setScreenIndex]); - return { - negotiatedLanguage, - langPackInstallPhase, - languageFilteredScreens - }; -} -/** - * The language switcher is a separate component as it needs to perform some asynchronous - * network actions such as retrieving the list of langpacks available, and downloading - * a new langpack. On a fast connection, this won't be noticeable, but on slow or unreliable - * internet this may fail for a user. - */ - -function LanguageSwitcher(props) { - const { - content, - handleAction, - negotiatedLanguage, - langPackInstallPhase, - messageId - } = props; - const [isAwaitingLangpack, setIsAwaitingLangpack] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); // Determine the status of the langpack installation. - - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - if (isAwaitingLangpack && langPackInstallPhase !== "installing") { - window.AWSetRequestedLocales(negotiatedLanguage.requestSystemLocales); - requestAnimationFrame(() => { - handleAction( // Simulate the click event. - { - currentTarget: { - value: "download_complete" - } - }); - }); - } - }, [handleAction, isAwaitingLangpack, langPackInstallPhase, negotiatedLanguage === null || negotiatedLanguage === void 0 ? void 0 : negotiatedLanguage.requestSystemLocales]); - let showWaitingScreen = false; - let showPreloadingScreen = false; - let showReadyScreen = false; - - if (isAwaitingLangpack && langPackInstallPhase !== "installed") { - showWaitingScreen = true; - } else if (langPackInstallPhase === "before-installation") { - showPreloadingScreen = true; - } else { - showReadyScreen = true; - } // Use {display: "none"} rather than if statements to prevent layout thrashing with - // the localized text elements rendering as blank, then filling in the text. - - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "action-buttons language-switcher-container" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - style: { - display: showPreloadingScreen ? "block" : "none" - } - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: "primary", - value: "primary_button", - disabled: true, - type: "button" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - className: "language-loader", - src: "chrome://browser/skin/tabbrowser/tab-connecting.png", - alt: "" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.waiting - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "secondary-cta" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.skip - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - value: "decline_waiting", - type: "button", - className: "secondary text-link arrow-icon", - onClick: handleAction - })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - style: { - display: showWaitingScreen ? "block" : "none" - } - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: "primary", - value: "primary_button", - disabled: true, - type: "button" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - className: "language-loader", - src: "chrome://browser/skin/tabbrowser/tab-connecting.png", - alt: "" - }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.downloading - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "secondary-cta" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.cancel - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - type: "button", - className: "secondary text-link", - onClick: () => { - setIsAwaitingLangpack(false); - handleAction({ - currentTarget: { - value: "cancel_waiting" - } - }); - } - })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - style: { - display: showReadyScreen ? "block" : "none" - } - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: "primary", - value: "primary_button", - onClick: () => { - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(messageId, "download_langpack"); - setIsAwaitingLangpack(true); - } - }, content.languageSwitcher.switch ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.switch - }) : // This is the localized name from the Intl.DisplayNames API. - negotiatedLanguage === null || negotiatedLanguage === void 0 ? void 0 : negotiatedLanguage.langPackDisplayName)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - type: "button", - className: "primary", - value: "decline", - onClick: event => { - window.AWSetRequestedLocales(negotiatedLanguage.originalAppLocales); - handleAction(event); - } - }, content.languageSwitcher.continue ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.languageSwitcher.continue - }) : // This is the localized name from the Intl.DisplayNames API. - negotiatedLanguage === null || negotiatedLanguage === void 0 ? void 0 : negotiatedLanguage.appDisplayName)))); -} - -/***/ }), -/* 11 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "CTAParagraph": () => (/* binding */ CTAParagraph) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* 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/. */ - - -const CTAParagraph = props => { - const { - content, - handleAction - } = props; - - if (!(content !== null && content !== void 0 && content.text)) { - return null; - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("h2", { - className: "cta-paragraph" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: content.text - }, content.text.string_name && typeof handleAction === "function" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("span", { - "data-l10n-id": content.text.string_id, - onClick: handleAction, - onKeyUp: event => ["Enter", " "].includes(event.key) ? handleAction(event) : null, - value: "cta_paragraph", - role: "button", - tabIndex: "0" - }, " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", { - role: "button", - tabIndex: "0", - "data-l10n-name": content.text.string_name - }, " ")) : null)); -}; - -/***/ }), -/* 12 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "HeroImage": () => (/* binding */ HeroImage) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); -/* 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/. */ - - -const HeroImage = props => { - const { - height, - url, - alt - } = props; - - if (!url) { - return null; - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "hero-image" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - style: height ? { - height - } : null, - src: url, - loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.getLoadingStrategyFor(url), - alt: alt || "", - role: alt ? null : "presentation" - })); -}; - -/***/ }), -/* 13 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "OnboardingVideo": () => (/* binding */ OnboardingVideo) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ - -const OnboardingVideo = props => { - const vidUrl = props.content.video_url; - const autoplay = props.content.autoPlay; - - const handleVideoAction = event => { - props.handleAction({ - currentTarget: { - value: event - } - }); - }; - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("video", { - // eslint-disable-line jsx-a11y/media-has-caption - controls: true, - autoPlay: autoplay, - src: vidUrl, - width: "604px", - height: "340px", - onPlay: () => handleVideoAction("video_start"), - onEnded: () => handleVideoAction("video_end") - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("source", { - src: vidUrl - }))); -}; - -/***/ }), -/* 14 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "AdditionalCTA": () => (/* binding */ AdditionalCTA) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* 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/. */ - - -const AdditionalCTA = ({ - content, - handleAction -}) => { - var _content$additional_b, _content$additional_b4, _content$additional_b5; - - let buttonStyle = ""; - - if (!((_content$additional_b = content.additional_button) !== null && _content$additional_b !== void 0 && _content$additional_b.style)) { - buttonStyle = "primary"; - } else { - var _content$additional_b2, _content$additional_b3; - - buttonStyle = ((_content$additional_b2 = content.additional_button) === null || _content$additional_b2 === void 0 ? void 0 : _content$additional_b2.style) === "link" ? "cta-link" : (_content$additional_b3 = content.additional_button) === null || _content$additional_b3 === void 0 ? void 0 : _content$additional_b3.style; - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: (_content$additional_b4 = content.additional_button) === null || _content$additional_b4 === void 0 ? void 0 : _content$additional_b4.label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - className: `${buttonStyle} additional-cta`, - onClick: handleAction, - value: "additional_button", - disabled: ((_content$additional_b5 = content.additional_button) === null || _content$additional_b5 === void 0 ? void 0 : _content$additional_b5.disabled) === true - })); -}; - -/***/ }), -/* 15 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "EmbeddedMigrationWizard": () => (/* binding */ EmbeddedMigrationWizard) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_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/. */ - -const EmbeddedMigrationWizard = ({ - handleAction -}) => { - const ref = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(); - (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { - const handleBeginMigration = () => { - handleAction({ - currentTarget: { - value: "migrate_start" - }, - source: "primary_button" - }); - }; - - const handleClose = () => { - handleAction({ - currentTarget: { - value: "migrate_close" - } - }); - }; - - const { - current - } = ref; - current === null || current === void 0 ? void 0 : current.addEventListener("MigrationWizard:BeginMigration", handleBeginMigration); - current === null || current === void 0 ? void 0 : current.addEventListener("MigrationWizard:Close", handleClose); - return () => { - current === null || current === void 0 ? void 0 : current.removeEventListener("MigrationWizard:BeginMigration", handleBeginMigration); - current === null || current === void 0 ? void 0 : current.removeEventListener("MigrationWizard:Close", handleClose); - }; - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("migration-wizard", { - "force-show-import-all": "false", - "auto-request-state": "", - ref: ref - }); -}; - -/***/ }), -/* 16 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "AddonsPicker": () => (/* binding */ AddonsPicker) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5); -/* 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/. */ - - - -const AddonsPicker = props => { - const { - content - } = props; - - if (!content) { - return null; - } - - function handleAction(event) { - const { - message_id - } = props; - let { - action, - source_id - } = content.tiles.data[event.currentTarget.value]; - let { - type, - data - } = action; - - if (type === "INSTALL_ADDON_FROM_URL") { - if (!data) { - return; - } - } - - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({ - type, - data - }); - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id); - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "addons-picker-container" - }, content.tiles.data.map(({ - id, - install_label, - name, - type, - description, - icon - }, index) => name ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - key: id, - className: "addon-container" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "rtamo-icon" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", { - className: `${type === "theme" ? "rtamo-theme-icon" : "brand-logo"}`, - src: icon, - role: "presentation", - alt: "" - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "addon-details" - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, { - text: name - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "addon-title" - })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, { - text: description - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "addon-description" - }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_2__.Localized, { - text: install_label - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", { - id: name, - value: index, - onClick: handleAction, - className: "primary" - }))) : null)); -}; - -/***/ }), -/* 17 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "LinkParagraph": () => (/* binding */ LinkParagraph) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); -/* 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/. */ - - -const LinkParagraph = props => { - var _text_content$link_ke; - - const { - text_content, - handleAction - } = props; - const handleParagraphAction = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(event => { - if (event.target.closest("a")) { - handleAction({ ...event, - currentTarget: event.target - }); - } - }, [handleAction]); - const onKeyPress = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(event => { - if (event.key === "Enter" && !event.repeat) { - handleParagraphAction(event); - } - }, [handleParagraphAction]); - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, { - text: text_content.text - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", { - className: text_content.font_styles === "legal" ? "legal-paragraph" : "link-paragraph", - onClick: handleParagraphAction, - value: "link_paragraph", - onKeyPress: onKeyPress - }, (_text_content$link_ke = text_content.link_keys) === null || _text_content$link_ke === void 0 ? void 0 : _text_content$link_ke.map(link => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", { - key: link, - value: link, - role: "link", - className: "text-link", - "data-l10n-name": link // must pass in tabIndex when no href is provided - , - tabIndex: "0" - }, " ")))); -}; - -/***/ }), -/* 18 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "BASE_PARAMS": () => (/* binding */ BASE_PARAMS), -/* harmony export */ "addUtmParams": () => (/* binding */ addUtmParams) -/* harmony export */ }); -/* 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/. */ - -/** - * BASE_PARAMS keys/values can be modified from outside this file - */ -const BASE_PARAMS = { - utm_source: "activity-stream", - utm_campaign: "firstrun", - utm_medium: "referral" -}; -/** - * Takes in a url as a string or URL object and returns a URL object with the - * utm_* parameters added to it. If a URL object is passed in, the paraemeters - * are added to it (the return value can be ignored in that case as it's the - * same object). - */ - -function addUtmParams(url, utmTerm) { - let returnUrl = url; - - if (typeof returnUrl === "string") { - returnUrl = new URL(url); - } - - for (let [key, value] of Object.entries(BASE_PARAMS)) { - if (!returnUrl.searchParams.has(key)) { - returnUrl.searchParams.append(key, value); - } - } - - returnUrl.searchParams.append("utm_term", utmTerm); - return returnUrl; -} - -/***/ }), -/* 19 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -__webpack_require__.r(__webpack_exports__); -/* harmony export */ __webpack_require__.d(__webpack_exports__, { -/* harmony export */ "ReturnToAMO": () => (/* binding */ ReturnToAMO) -/* harmony export */ }); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3); -/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6); -/* harmony import */ var _asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(18); -/* 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/. */ - - - - -class ReturnToAMO extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) { - constructor(props) { - super(props); - this.fetchFlowParams = this.fetchFlowParams.bind(this); - this.handleAction = this.handleAction.bind(this); - } - - async fetchFlowParams() { - if (this.props.metricsFlowUri) { - this.setState({ - flowParams: await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.fetchFlowParams(this.props.metricsFlowUri) - }); - } - } - - componentDidUpdate() { - this.fetchFlowParams(); - } - - handleAction(event) { - const { - content, - message_id, - url, - utm_term - } = this.props; - let { - action, - source_id - } = content[event.currentTarget.value]; - let { - type, - data - } = action; - - if (type === "INSTALL_ADDON_FROM_URL") { - if (!data) { - return; - } // Set add-on url in action.data.url property from JSON - - - data = { ...data, - url - }; - } else if (type === "SHOW_FIREFOX_ACCOUNTS") { - let params = { ..._asrouter_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__.BASE_PARAMS, - utm_term: `aboutwelcome-${utm_term}-screen` - }; - - if (action.addFlowParams && this.state.flowParams) { - params = { ...params, - ...this.state.flowParams - }; - } - - data = { ...data, - extraParams: params - }; - } - - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({ - type, - data - }); - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id); - } - - render() { - var _this$props$themeScre; - - const { - content, - type - } = this.props; - - if (!content) { - return null; - } - - if (content !== null && content !== void 0 && content.primary_button.label) { - content.primary_button.label.string_id = type.includes("theme") ? "return-to-amo-add-theme-label" : "mr1-return-to-amo-add-extension-label"; - } // For experiments, when needed below rendered UI allows settings hard coded strings - // directly inside JSON except for ReturnToAMOText which picks add-on name and icon from fluent string - - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", { - className: "outer-wrapper onboardingContainer proton", - style: content.backdrop ? { - background: content.backdrop - } : {} - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__.MultiStageProtonScreen, { - content: content, - isRtamo: true, - isTheme: type.includes("theme"), - id: this.props.message_id, - order: this.props.order || 0, - totalNumberOfScreens: 1, - isSingleScreen: true, - autoAdvance: this.props.auto_advance, - iconURL: type.includes("theme") ? (_this$props$themeScre = this.props.themeScreenshots[0]) === null || _this$props$themeScre === void 0 ? void 0 : _this$props$themeScre.url : this.props.iconURL, - addonName: this.props.name, - handleAction: this.handleAction - })); - } - -} -ReturnToAMO.defaultProps = _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_RTAMO_CONTENT; - -/***/ }) -/******/ ]); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/compat get default export */ -/******/ (() => { -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = (module) => { -/******/ var getter = module && module.__esModule ? -/******/ () => (module['default']) : -/******/ () => (module); -/******/ __webpack_require__.d(getter, { a: getter }); -/******/ return getter; -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __webpack_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __webpack_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); -/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); -/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3); -/* harmony import */ var _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); -/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(19); -function _extends() { _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; }; return _extends.apply(this, arguments); } - -/* 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/. */ - - - - - - -class AboutWelcome extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) { - constructor(props) { - super(props); - this.state = { - metricsFlowUri: null - }; - this.fetchFxAFlowUri = this.fetchFxAFlowUri.bind(this); - } - - async fetchFxAFlowUri() { - var _window$AWGetFxAMetri, _window; - - this.setState({ - metricsFlowUri: await ((_window$AWGetFxAMetri = (_window = window).AWGetFxAMetricsFlowURI) === null || _window$AWGetFxAMetri === void 0 ? void 0 : _window$AWGetFxAMetri.call(_window)) - }); - } - - componentDidMount() { - if (!this.props.skipFxA) { - this.fetchFxAFlowUri(); - } - - if (document.location.href === "about:welcome") { - // Record impression with performance data after allowing the page to load - const recordImpression = domState => { - const { - domComplete, - domInteractive - } = performance.getEntriesByType("navigation").pop(); - _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(this.props.messageId, { - domComplete, - domInteractive, - mountStart: performance.getEntriesByName("mount").pop().startTime, - domState, - source: this.props.UTMTerm - }); - }; - - if (document.readyState === "complete") { - // Page might have already triggered a load event because it waited for async data, - // e.g., attribution, so the dom load timing could be of a empty content - // with domState in telemetry captured as 'complete' - recordImpression(document.readyState); - } else { - window.addEventListener("load", () => recordImpression("load"), { - once: true - }); - } // Captures user has seen about:welcome by setting - // firstrun.didSeeAboutWelcome pref to true and capturing welcome UI unique messageId - - - window.AWSendToParent("SET_WELCOME_MESSAGE_SEEN", this.props.messageId); - } - } - - render() { - const { - props - } = this; - - if (props.template === "return_to_amo") { - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__.ReturnToAMO, { - message_id: props.messageId, - type: props.type, - name: props.name, - url: props.url, - iconURL: props.iconURL, - themeScreenshots: props.screenshots, - metricsFlowUri: this.state.metricsFlowUri - }); - } - - return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__.MultiStageAboutWelcome, { - message_id: props.messageId, - defaultScreens: props.screens, - updateHistory: !props.disableHistoryUpdates, - metricsFlowUri: this.state.metricsFlowUri, - utm_term: props.UTMTerm, - transitions: props.transitions, - backdrop: props.backdrop, - startScreen: props.startScreen || 0, - appAndSystemLocaleInfo: props.appAndSystemLocaleInfo, - ariaRole: props.aria_role - }); - } - -} // Computes messageId and UTMTerm info used in telemetry - - -function ComputeTelemetryInfo(welcomeContent, experimentId, branchId) { - let messageId = welcomeContent.template === "return_to_amo" ? `RTAMO_DEFAULT_WELCOME_${welcomeContent.type.toUpperCase()}` : "DEFAULT_ID"; - let UTMTerm = "aboutwelcome-default"; - - if (welcomeContent.id) { - messageId = welcomeContent.id.toUpperCase(); - } - - if (experimentId && branchId) { - UTMTerm = `aboutwelcome-${experimentId}-${branchId}`.toLowerCase(); - } - - return { - messageId, - UTMTerm - }; -} - -async function retrieveRenderContent() { - // Feature config includes RTAMO attribution data if exists - // else below data in order specified - // user prefs - // experiment data - // defaults - let featureConfig = await window.AWGetFeatureConfig(); - let { - messageId, - UTMTerm - } = ComputeTelemetryInfo(featureConfig, featureConfig.slug, featureConfig.branch && featureConfig.branch.slug); - return { - featureConfig, - messageId, - UTMTerm - }; -} - -async function mount() { - let { - featureConfig: aboutWelcomeProps, - messageId, - UTMTerm - } = await retrieveRenderContent(); - react_dom__WEBPACK_IMPORTED_MODULE_1___default().render( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(AboutWelcome, _extends({ - messageId: messageId, - UTMTerm: UTMTerm - }, aboutWelcomeProps)), document.getElementById("multi-stage-message-root")); -} - -performance.mark("mount"); -mount(); -})(); - -/******/ })() -; \ No newline at end of file diff --git a/browser/components/newtab/package.json b/browser/components/newtab/package.json index 3f862d6ba496..cb49825372af 100644 --- a/browser/components/newtab/package.json +++ b/browser/components/newtab/package.json @@ -83,16 +83,12 @@ "bundle": "npm-run-all bundle:*", "bundle:webpack": "webpack-cli --config webpack.system-addon.config.js", "bundle:css": "sass content-src/styles:css --no-source-map", - "bundle:welcomeBundle": "webpack-cli --config webpack.aboutwelcome.config.js", - "bundle:welcomeCss": "sass content-src/aboutwelcome:aboutwelcome/content --no-source-map", "bundle:html": "rimraf prerendered && node ./bin/render-activity-stream-html.js", "buildmc": "npm-run-all buildmc:*", "buildmc:bundle": "npm run bundle", "watchmc": "npm-run-all --parallel watchmc:*", "watchmc:webpack": "npm run bundle:webpack -- --env development -w", "watchmc:css": "npm run bundle:css -- --source-map --embed-sources --embed-source-map --load-path=content-src -w", - "watchmc:welcomeBundle": "npm run bundle:welcomeBundle -- --env development -w", - "watchmc:welcomeCss": "npm run bundle:welcomeCss -- --source-map --embed-sources --embed-source-map -w", "testmc": "npm-run-all testmc:*", "testmc:lint": "npm run lint", "testmc:build": "npm run bundle:webpack", diff --git a/browser/components/newtab/yamscripts.yml b/browser/components/newtab/yamscripts.yml index 7d94912a756e..7e9501751a1f 100644 --- a/browser/components/newtab/yamscripts.yml +++ b/browser/components/newtab/yamscripts.yml @@ -8,8 +8,6 @@ scripts: bundle: webpack: webpack-cli --config webpack.system-addon.config.js css: sass content-src/styles:css --no-source-map - welcomeBundle: webpack-cli --config webpack.aboutwelcome.config.js - welcomeCss: sass content-src/aboutwelcome:aboutwelcome/content --no-source-map html: rimraf prerendered && node ./bin/render-activity-stream-html.js # buildmc: Used to do stuff when this code was in GitHub, now just an @@ -22,8 +20,6 @@ scripts: _parallel: true webpack: =>bundle:webpack -- --env development -w css: =>bundle:css -- --source-map --embed-sources --embed-source-map --load-path=content-src -w - welcomeBundle: =>bundle:welcomeBundle -- --env development -w - welcomeCss: =>bundle:welcomeCss -- --source-map --embed-sources --embed-source-map -w testmc: lint: =>lint