зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1499886 - Add send-to-device snippet, right-to-left robustness and bug fixes to Activity Stream r=k88hudson
Differential Revision: https://phabricator.services.mozilla.com/D9045 --HG-- rename : browser/components/newtab/locales/ach/strings.properties => browser/components/newtab/locales-src/ach/strings.properties rename : browser/components/newtab/locales/an/strings.properties => browser/components/newtab/locales-src/an/strings.properties rename : browser/components/newtab/locales/ar/strings.properties => browser/components/newtab/locales-src/ar/strings.properties rename : browser/components/newtab/locales/ast/strings.properties => browser/components/newtab/locales-src/ast/strings.properties rename : browser/components/newtab/locales/az/strings.properties => browser/components/newtab/locales-src/az/strings.properties rename : browser/components/newtab/locales/be/strings.properties => browser/components/newtab/locales-src/be/strings.properties rename : browser/components/newtab/locales/bg/strings.properties => browser/components/newtab/locales-src/bg/strings.properties rename : browser/components/newtab/locales/bn-BD/strings.properties => browser/components/newtab/locales-src/bn-BD/strings.properties rename : browser/components/newtab/locales/bn-IN/strings.properties => browser/components/newtab/locales-src/bn-IN/strings.properties rename : browser/components/newtab/locales/br/strings.properties => browser/components/newtab/locales-src/br/strings.properties rename : browser/components/newtab/locales/bs/strings.properties => browser/components/newtab/locales-src/bs/strings.properties rename : browser/components/newtab/locales/ca/strings.properties => browser/components/newtab/locales-src/ca/strings.properties rename : browser/components/newtab/locales/cak/strings.properties => browser/components/newtab/locales-src/cak/strings.properties rename : browser/components/newtab/locales/crh/strings.properties => browser/components/newtab/locales-src/crh/strings.properties rename : browser/components/newtab/locales/cs/strings.properties => browser/components/newtab/locales-src/cs/strings.properties rename : browser/components/newtab/locales/cy/strings.properties => browser/components/newtab/locales-src/cy/strings.properties rename : browser/components/newtab/locales/da/strings.properties => browser/components/newtab/locales-src/da/strings.properties rename : browser/components/newtab/locales/de/strings.properties => browser/components/newtab/locales-src/de/strings.properties rename : browser/components/newtab/locales/dsb/strings.properties => browser/components/newtab/locales-src/dsb/strings.properties rename : browser/components/newtab/locales/el/strings.properties => browser/components/newtab/locales-src/el/strings.properties rename : browser/components/newtab/locales/en-CA/strings.properties => browser/components/newtab/locales-src/en-CA/strings.properties rename : browser/components/newtab/locales/en-GB/strings.properties => browser/components/newtab/locales-src/en-GB/strings.properties rename : browser/components/newtab/locales/en-US/strings.properties => browser/components/newtab/locales-src/en-US/strings.properties rename : browser/components/newtab/locales/eo/strings.properties => browser/components/newtab/locales-src/eo/strings.properties rename : browser/components/newtab/locales/es-AR/strings.properties => browser/components/newtab/locales-src/es-AR/strings.properties rename : browser/components/newtab/locales/es-CL/strings.properties => browser/components/newtab/locales-src/es-CL/strings.properties rename : browser/components/newtab/locales/es-ES/strings.properties => browser/components/newtab/locales-src/es-ES/strings.properties rename : browser/components/newtab/locales/es-MX/strings.properties => browser/components/newtab/locales-src/es-MX/strings.properties rename : browser/components/newtab/locales/et/strings.properties => browser/components/newtab/locales-src/et/strings.properties rename : browser/components/newtab/locales/eu/strings.properties => browser/components/newtab/locales-src/eu/strings.properties rename : browser/components/newtab/locales/fa/strings.properties => browser/components/newtab/locales-src/fa/strings.properties rename : browser/components/newtab/locales/ff/strings.properties => browser/components/newtab/locales-src/ff/strings.properties rename : browser/components/newtab/locales/fi/strings.properties => browser/components/newtab/locales-src/fi/strings.properties rename : browser/components/newtab/locales/fr/strings.properties => browser/components/newtab/locales-src/fr/strings.properties rename : browser/components/newtab/locales/fy-NL/strings.properties => browser/components/newtab/locales-src/fy-NL/strings.properties rename : browser/components/newtab/locales/ga-IE/strings.properties => browser/components/newtab/locales-src/ga-IE/strings.properties rename : browser/components/newtab/locales/gd/strings.properties => browser/components/newtab/locales-src/gd/strings.properties rename : browser/components/newtab/locales/gl/strings.properties => browser/components/newtab/locales-src/gl/strings.properties rename : browser/components/newtab/locales/gn/strings.properties => browser/components/newtab/locales-src/gn/strings.properties rename : browser/components/newtab/locales/gu-IN/strings.properties => browser/components/newtab/locales-src/gu-IN/strings.properties rename : browser/components/newtab/locales/he/strings.properties => browser/components/newtab/locales-src/he/strings.properties rename : browser/components/newtab/locales/hi-IN/strings.properties => browser/components/newtab/locales-src/hi-IN/strings.properties rename : browser/components/newtab/locales/hr/strings.properties => browser/components/newtab/locales-src/hr/strings.properties rename : browser/components/newtab/locales/hsb/strings.properties => browser/components/newtab/locales-src/hsb/strings.properties rename : browser/components/newtab/locales/hu/strings.properties => browser/components/newtab/locales-src/hu/strings.properties rename : browser/components/newtab/locales/hy-AM/strings.properties => browser/components/newtab/locales-src/hy-AM/strings.properties rename : browser/components/newtab/locales/ia/strings.properties => browser/components/newtab/locales-src/ia/strings.properties rename : browser/components/newtab/locales/id/strings.properties => browser/components/newtab/locales-src/id/strings.properties rename : browser/components/newtab/locales/is/strings.properties => browser/components/newtab/locales-src/is/strings.properties rename : browser/components/newtab/locales/it/strings.properties => browser/components/newtab/locales-src/it/strings.properties rename : browser/components/newtab/locales/ja-JP-mac/strings.properties => browser/components/newtab/locales-src/ja-JP-mac/strings.properties rename : browser/components/newtab/locales/ja/strings.properties => browser/components/newtab/locales-src/ja/strings.properties rename : browser/components/newtab/locales/ka/strings.properties => browser/components/newtab/locales-src/ka/strings.properties rename : browser/components/newtab/locales/kab/strings.properties => browser/components/newtab/locales-src/kab/strings.properties rename : browser/components/newtab/locales/kk/strings.properties => browser/components/newtab/locales-src/kk/strings.properties rename : browser/components/newtab/locales/km/strings.properties => browser/components/newtab/locales-src/km/strings.properties rename : browser/components/newtab/locales/kn/strings.properties => browser/components/newtab/locales-src/kn/strings.properties rename : browser/components/newtab/locales/ko/strings.properties => browser/components/newtab/locales-src/ko/strings.properties rename : browser/components/newtab/locales/lij/strings.properties => browser/components/newtab/locales-src/lij/strings.properties rename : browser/components/newtab/locales/lo/strings.properties => browser/components/newtab/locales-src/lo/strings.properties rename : browser/components/newtab/locales/lt/strings.properties => browser/components/newtab/locales-src/lt/strings.properties rename : browser/components/newtab/locales/ltg/strings.properties => browser/components/newtab/locales-src/ltg/strings.properties rename : browser/components/newtab/locales/lv/strings.properties => browser/components/newtab/locales-src/lv/strings.properties rename : browser/components/newtab/locales/mai/strings.properties => browser/components/newtab/locales-src/mai/strings.properties rename : browser/components/newtab/locales/mk/strings.properties => browser/components/newtab/locales-src/mk/strings.properties rename : browser/components/newtab/locales/ml/strings.properties => browser/components/newtab/locales-src/ml/strings.properties rename : browser/components/newtab/locales/mr/strings.properties => browser/components/newtab/locales-src/mr/strings.properties rename : browser/components/newtab/locales/ms/strings.properties => browser/components/newtab/locales-src/ms/strings.properties rename : browser/components/newtab/locales/my/strings.properties => browser/components/newtab/locales-src/my/strings.properties rename : browser/components/newtab/locales/nb-NO/strings.properties => browser/components/newtab/locales-src/nb-NO/strings.properties rename : browser/components/newtab/locales/ne-NP/strings.properties => browser/components/newtab/locales-src/ne-NP/strings.properties rename : browser/components/newtab/locales/nl/strings.properties => browser/components/newtab/locales-src/nl/strings.properties rename : browser/components/newtab/locales/nn-NO/strings.properties => browser/components/newtab/locales-src/nn-NO/strings.properties rename : browser/components/newtab/locales/oc/strings.properties => browser/components/newtab/locales-src/oc/strings.properties rename : browser/components/newtab/locales/pa-IN/strings.properties => browser/components/newtab/locales-src/pa-IN/strings.properties rename : browser/components/newtab/locales/pl/strings.properties => browser/components/newtab/locales-src/pl/strings.properties rename : browser/components/newtab/locales/pt-BR/strings.properties => browser/components/newtab/locales-src/pt-BR/strings.properties rename : browser/components/newtab/locales/pt-PT/strings.properties => browser/components/newtab/locales-src/pt-PT/strings.properties rename : browser/components/newtab/locales/rm/strings.properties => browser/components/newtab/locales-src/rm/strings.properties rename : browser/components/newtab/locales/ro/strings.properties => browser/components/newtab/locales-src/ro/strings.properties rename : browser/components/newtab/locales/ru/strings.properties => browser/components/newtab/locales-src/ru/strings.properties rename : browser/components/newtab/locales/si/strings.properties => browser/components/newtab/locales-src/si/strings.properties rename : browser/components/newtab/locales/sk/strings.properties => browser/components/newtab/locales-src/sk/strings.properties rename : browser/components/newtab/locales/sl/strings.properties => browser/components/newtab/locales-src/sl/strings.properties rename : browser/components/newtab/locales/sq/strings.properties => browser/components/newtab/locales-src/sq/strings.properties rename : browser/components/newtab/locales/sr/strings.properties => browser/components/newtab/locales-src/sr/strings.properties rename : browser/components/newtab/locales/sv-SE/strings.properties => browser/components/newtab/locales-src/sv-SE/strings.properties rename : browser/components/newtab/locales/ta/strings.properties => browser/components/newtab/locales-src/ta/strings.properties rename : browser/components/newtab/locales/te/strings.properties => browser/components/newtab/locales-src/te/strings.properties rename : browser/components/newtab/locales/th/strings.properties => browser/components/newtab/locales-src/th/strings.properties rename : browser/components/newtab/locales/tl/strings.properties => browser/components/newtab/locales-src/tl/strings.properties rename : browser/components/newtab/locales/tr/strings.properties => browser/components/newtab/locales-src/tr/strings.properties rename : browser/components/newtab/locales/uk/strings.properties => browser/components/newtab/locales-src/uk/strings.properties rename : browser/components/newtab/locales/ur/strings.properties => browser/components/newtab/locales-src/ur/strings.properties rename : browser/components/newtab/locales/uz/strings.properties => browser/components/newtab/locales-src/uz/strings.properties rename : browser/components/newtab/locales/vi/strings.properties => browser/components/newtab/locales-src/vi/strings.properties rename : browser/components/newtab/locales/zh-CN/strings.properties => browser/components/newtab/locales-src/zh-CN/strings.properties rename : browser/components/newtab/locales/zh-TW/strings.properties => browser/components/newtab/locales-src/zh-TW/strings.properties extra : moz-landing-system : lando
This commit is contained in:
Родитель
055117366d
Коммит
a8fe89d2f5
|
@ -189,7 +189,7 @@ module.exports = {
|
|||
"no-void": 2,
|
||||
"no-warning-comments": 0, // TODO: Change to `1`?
|
||||
"nonblock-statement-body-position": 2,
|
||||
"object-curly-newline": [2, {"multiline": true}],
|
||||
"object-curly-newline": [2, {"multiline": true, "consistent": true}],
|
||||
"object-curly-spacing": [2, "never"],
|
||||
"object-property-newline": [2, {"allowMultiplePropertiesPerLine": true}],
|
||||
"one-var": [2, "never"],
|
||||
|
|
|
@ -17,7 +17,7 @@ rules:
|
|||
mixins-before-declarations: [2, {exclude: [breakpoint, mq]}]
|
||||
nesting-depth: [2, {max-depth: 4}]
|
||||
no-debug: 1
|
||||
no-disallowed-properties: [1, {properties: [text-transform]}]
|
||||
no-disallowed-properties: [1, {properties: [margin-left, margin-right, text-transform]}]
|
||||
no-duplicate-properties: 2
|
||||
no-misspelled-properties: [2, {extra-properties: [-moz-context-properties]}]
|
||||
no-url-domains: 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# flod as main contact for string changes
|
||||
locales/en-US/strings.properties @flodolo
|
||||
locales-src/en-US/strings.properties @flodolo
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
exports.DEFAULT_LOCALE = "en-US";
|
||||
if (!process.env.npm_lifecycle_event) {
|
||||
throw Error("You should only run this from npm script contexts");
|
||||
}
|
||||
|
||||
exports.DEFAULT_LOCALE = process.env.npm_package_config_default_locale;
|
||||
|
||||
exports.LOCALES_SOURCE_DIRECTORY = process.env.npm_package_config_locales_dir;
|
||||
|
||||
// This locales list is to find any similar locales that we can reuse strings
|
||||
// instead of falling back to the default, e.g., use bn-BD strings for bn-IN.
|
||||
|
|
|
@ -7,7 +7,7 @@ const fetch = require("node-fetch");
|
|||
/* globals cd, ls, mkdir, rm, ShellString */
|
||||
require("shelljs/global");
|
||||
|
||||
const {CENTRAL_LOCALES, DEFAULT_LOCALE} = require("./locales");
|
||||
const {CENTRAL_LOCALES, DEFAULT_LOCALE, LOCALES_SOURCE_DIRECTORY} = require("./locales");
|
||||
const L10N_CENTRAL = "https://hg.mozilla.org/l10n-central";
|
||||
const PROPERTIES_PATH = "raw-file/default/browser/chrome/browser/activity-stream/newtab.properties";
|
||||
const STRINGS_FILE = "strings.properties";
|
||||
|
@ -74,9 +74,9 @@ async function saveProperties(locale) {
|
|||
|
||||
// Replace and update each locale's strings
|
||||
async function updateLocales() {
|
||||
console.log("Switching to and deleting existing l10n tree under: locales");
|
||||
console.log(`Switching to and deleting existing l10n tree under: ${LOCALES_SOURCE_DIRECTORY}`);
|
||||
|
||||
cd("locales");
|
||||
cd(LOCALES_SOURCE_DIRECTORY);
|
||||
ls().forEach(dir => {
|
||||
// Keep the default/source locale as it might have newer strings
|
||||
if (dir !== DEFAULT_LOCALE) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import {LocalizationProvider} from "fluent-react";
|
|||
import {OnboardingMessage} from "./templates/OnboardingMessage/OnboardingMessage";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import {SendToDeviceSnippet} from "./templates/SendToDeviceSnippet/SendToDeviceSnippet";
|
||||
import {SimpleSnippet} from "./templates/SimpleSnippet/SimpleSnippet";
|
||||
import {SubmitFormSnippet} from "./templates/SubmitFormSnippet/SubmitFormSnippet";
|
||||
|
||||
|
@ -14,6 +15,7 @@ const SnippetComponents = {
|
|||
simple_snippet: SimpleSnippet,
|
||||
newsletter_snippet: props => <SubmitFormSnippet {...props} form_method="POST" />,
|
||||
fxa_signup_snippet: props => <SubmitFormSnippet {...props} form_method="GET" />,
|
||||
send_to_device_snippet: SendToDeviceSnippet,
|
||||
};
|
||||
|
||||
const INCOMING_MESSAGE_NAME = "ASRouter:parent-to-child";
|
||||
|
@ -129,7 +131,7 @@ export class ASRouterUISurface extends React.PureComponent {
|
|||
if (action.type) {
|
||||
ASRouterUtils.executeAction(action);
|
||||
}
|
||||
if (!this.state.message.content.do_not_autoblock) {
|
||||
if (!this.state.message.content.do_not_autoblock && !event.target.dataset.do_not_autoblock) {
|
||||
ASRouterUtils.blockById(this.state.message.id);
|
||||
}
|
||||
if (this.state.message.provider !== "preview") {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
.ASRouterButton {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--newtab-border-secondary-color);
|
||||
|
@ -14,7 +15,7 @@
|
|||
}
|
||||
|
||||
&.primary {
|
||||
border: 1px solid var(--newtab-border-primary-color);
|
||||
border: 1px solid var(--newtab-button-primary-color);
|
||||
background-color: var(--newtab-button-primary-color);
|
||||
color: $grey-10;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
.modalOverlayInner {
|
||||
width: 960px;
|
||||
height: 510px;
|
||||
height: 570px;
|
||||
position: fixed;
|
||||
top: calc(50% - 255px); // halfway down minus half the height of the modal
|
||||
top: calc(50% - 285px); // halfway down minus half the height of the modal
|
||||
left: calc(50% - 480px); // halfway across minus half the width of the modal
|
||||
background: $white;
|
||||
box-shadow: 0 1px 15px 0 $black-30;
|
||||
|
@ -95,9 +95,9 @@
|
|||
|
||||
.modalButton {
|
||||
margin-top: 20px;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
height: 30px;
|
||||
padding: 4px 0 6px;
|
||||
padding: 4px 30px 6px;
|
||||
font-size: 15px;
|
||||
|
||||
&:focus,
|
||||
|
|
|
@ -17,7 +17,7 @@ const ALLOWED_TAGS = {
|
|||
* Transform an object (tag name: {url}) into (tag name: anchor) where the url
|
||||
* is used as href, in order to render links inside a Fluent.Localized component.
|
||||
*/
|
||||
export function convertLinks(links, sendClick) {
|
||||
export function convertLinks(links, sendClick, autoBlock) {
|
||||
if (links) {
|
||||
return Object.keys(links).reduce((acc, linkTag) => {
|
||||
const {action} = links[linkTag];
|
||||
|
@ -25,9 +25,11 @@ export function convertLinks(links, sendClick) {
|
|||
const url = action ? false : safeURI(links[linkTag].url);
|
||||
|
||||
acc[linkTag] = (<a href={url}
|
||||
target={autoBlock === false ? "_blank" : ""}
|
||||
data-metric={links[linkTag].metric}
|
||||
data-action={action}
|
||||
data-args={links[linkTag].args}
|
||||
data-do_not_autoblock={autoBlock === false}
|
||||
onClick={sendClick} />);
|
||||
return acc;
|
||||
}, {});
|
||||
|
@ -44,7 +46,7 @@ export function RichText(props) {
|
|||
throw new Error(`ASRouter: ${props.localization_id} is not a valid rich text property. If you want it to be processed, you need to add it to asrouter/rich-text-strings.js`);
|
||||
}
|
||||
return (
|
||||
<Localized id={props.localization_id} {...ALLOWED_TAGS} {...convertLinks(props.links, props.sendClick)}>
|
||||
<Localized id={props.localization_id} {...ALLOWED_TAGS} {...convertLinks(props.links, props.sendClick, props.autoBlock)}>
|
||||
<span>{props.text}</span>
|
||||
</Localized>
|
||||
);
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
a {
|
||||
cursor: pointer;
|
||||
color: var(--newtab-link-primary-color);
|
||||
|
||||
[lwt-newtab-brighttext] & {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.innerWrapper {
|
||||
|
|
|
@ -27,6 +27,7 @@ Please note that some targeting attributes require stricter controls on the tele
|
|||
* [topFrecentSites](#topfrecentsites)
|
||||
* [totalBookmarksCount](#totalbookmarkscount)
|
||||
* [xpinstallEnabled](#xpinstallEnabled)
|
||||
* [needsUpdate](#needsupdate)
|
||||
|
||||
## Detailed usage
|
||||
|
||||
|
@ -384,3 +385,11 @@ Pref used by system administrators to disallow add-ons from installed altogether
|
|||
```ts
|
||||
declare const xpinstallEnabled: boolean;
|
||||
```
|
||||
|
||||
### `needsUpdate`
|
||||
|
||||
Does the client have the latest available version installed
|
||||
|
||||
```ts
|
||||
declare const needsUpdate: boolean;
|
||||
```
|
||||
|
|
|
@ -8,6 +8,7 @@ import {MessageContext} from "fluent";
|
|||
const RICH_TEXT_CONFIG = {
|
||||
"text": ["text", "scene1_text"],
|
||||
"privacy_html": "scene2_privacy_html",
|
||||
"disclaimer_html": "scene2_disclaimer_html",
|
||||
};
|
||||
|
||||
export const RICH_TEXT_KEYS = Object.keys(RICH_TEXT_CONFIG);
|
||||
|
|
|
@ -100,13 +100,14 @@
|
|||
> span > p {
|
||||
color: $grey-60;
|
||||
margin-top: 0;
|
||||
height: 130px;
|
||||
height: 180px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
|
||||
@media(max-width: 650px) {
|
||||
margin-bottom: 0;
|
||||
height: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,13 +124,12 @@
|
|||
// at 850px, the button shimmies down and to the right
|
||||
@media(max-width: 850px) {
|
||||
float: right;
|
||||
margin-top: -60px;
|
||||
margin-right: -10px;
|
||||
margin-top: -105px;
|
||||
margin-inline-end: -10px;
|
||||
}
|
||||
|
||||
@media(max-width: 650px) {
|
||||
float: none;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
|
@ -143,12 +143,12 @@
|
|||
|
||||
&::before {
|
||||
content: '';
|
||||
height: 220px;
|
||||
height: 230px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
background-color: $grey-30;
|
||||
margin-top: 40px;
|
||||
margin-left: 215px;
|
||||
margin-inline-start: 215px;
|
||||
|
||||
// at 850px, the line goes from vertical to horizontal
|
||||
@media(max-width: 850px) {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import {isEmailOrPhoneNumber} from "./isEmailOrPhoneNumber";
|
||||
import React from "react";
|
||||
import {SubmitFormSnippet} from "../SubmitFormSnippet/SubmitFormSnippet.jsx";
|
||||
|
||||
function validateInput(value, content) {
|
||||
const type = isEmailOrPhoneNumber(value, content);
|
||||
return type ? "" : "Must be an email or a phone number.";
|
||||
}
|
||||
|
||||
function processFormData(input, message) {
|
||||
const {content} = message;
|
||||
const type = content.include_sms ? isEmailOrPhoneNumber(input.value, content) : "email";
|
||||
const formData = new FormData();
|
||||
let url;
|
||||
if (type === "phone") {
|
||||
url = "https://basket.mozilla.org/news/subscribe_sms/";
|
||||
formData.append("mobile_number", input.value);
|
||||
formData.append("msg_name", content.message_id_sms);
|
||||
formData.append("country", content.country);
|
||||
} else if (type === "email") {
|
||||
url = "https://basket.mozilla.org/news/subscribe/";
|
||||
formData.append("email", input.value);
|
||||
formData.append("newsletters", content.message_id_email);
|
||||
formData.append("source_url", encodeURIComponent(`https://snippets.mozilla.com/show/${message.id}`));
|
||||
}
|
||||
formData.append("lang", content.locale);
|
||||
return {formData, url};
|
||||
}
|
||||
|
||||
export const SendToDeviceSnippet = props => (
|
||||
<SubmitFormSnippet {...props}
|
||||
form_method="POST"
|
||||
className="send_to_device_snippet"
|
||||
inputType={props.content.include_sms ? "text" : "email"}
|
||||
validateInput={props.content.include_sms ? validateInput : null}
|
||||
processFormData={processFormData} />
|
||||
);
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Checks if a given string is an email or phone number or neither
|
||||
* @param {string} val The user input
|
||||
* @param {ASRMessageContent} content .content property on ASR message
|
||||
* @returns {"email"|"phone"|""} The type of the input
|
||||
*/
|
||||
export function isEmailOrPhoneNumber(val, content) {
|
||||
const {locale} = content;
|
||||
// http://emailregex.com/
|
||||
const email_re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
const check_email = email_re.test(val);
|
||||
let check_phone; // depends on locale
|
||||
switch (locale) {
|
||||
case "en-US":
|
||||
case "en-CA":
|
||||
// allow 10-11 digits in case user wants to enter country code
|
||||
check_phone = val.length >= 10 && val.length <= 11 && !isNaN(val);
|
||||
break;
|
||||
case "de":
|
||||
// allow between 2 and 12 digits for german phone numbers
|
||||
check_phone = val.length >= 2 && val.length <= 12 && !isNaN(val);
|
||||
break;
|
||||
// this case should never be hit, but good to have a fallback just in case
|
||||
default:
|
||||
check_phone = !isNaN(val);
|
||||
break;
|
||||
}
|
||||
if (check_email) {
|
||||
return "email";
|
||||
} else if (check_phone) {
|
||||
return "phone";
|
||||
}
|
||||
return "";
|
||||
}
|
|
@ -16,9 +16,12 @@ export class SimpleSnippet extends React.PureComponent {
|
|||
if (this.props.provider !== "preview") {
|
||||
this.props.sendUserActionTelemetry({event: "CLICK_BUTTON", id: this.props.UISurface});
|
||||
}
|
||||
const {button_url} = this.props.content;
|
||||
// If button_url is defined handle it as OPEN_URL action
|
||||
const type = this.props.content.button_action || (button_url && "OPEN_URL");
|
||||
this.props.onAction({
|
||||
type: this.props.content.button_action,
|
||||
data: {args: this.props.content.button_action_args},
|
||||
type,
|
||||
data: {args: this.props.content.button_action_args || button_url},
|
||||
});
|
||||
if (!this.props.content.do_not_autoblock) {
|
||||
this.props.onBlock();
|
||||
|
@ -37,7 +40,7 @@ export class SimpleSnippet extends React.PureComponent {
|
|||
|
||||
renderButton() {
|
||||
const {props} = this;
|
||||
if (!props.content.button_action && !props.onButtonClick) {
|
||||
if (!props.content.button_action && !props.onButtonClick && !props.content.button_url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,12 @@
|
|||
"type": "string",
|
||||
"description": "The type of action the button should trigger."
|
||||
},
|
||||
"button_url": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/link_url"},
|
||||
{"description": "A url, button_label links to this"}
|
||||
]
|
||||
},
|
||||
"button_action_args": {
|
||||
"type": "string",
|
||||
"description": "Additional parameters for button action, example which specific menu the button should open"
|
||||
|
@ -95,7 +101,8 @@
|
|||
"additionalProperties": false,
|
||||
"required": ["text"],
|
||||
"dependencies": {
|
||||
"button_label": ["button_action"],
|
||||
"button_action": ["button_label"],
|
||||
"button_url": ["button_label"],
|
||||
"button_color": ["button_label"],
|
||||
"button_background_color": ["button_label"]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {Button} from "../../components/Button/Button";
|
||||
import React from "react";
|
||||
import {RichText} from "../../components/RichText/RichText";
|
||||
import {SimpleSnippet} from "../SimpleSnippet/SimpleSnippet";
|
||||
|
@ -8,6 +9,7 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
super(props);
|
||||
this.expandSnippet = this.expandSnippet.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.onInputChange = this.onInputChange.bind(this);
|
||||
this.state = {
|
||||
expanded: false,
|
||||
signupSubmitted: false,
|
||||
|
@ -32,23 +34,24 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
|
||||
const fetchConfig = {
|
||||
body: new FormData(this.refs.form),
|
||||
method: "POST",
|
||||
};
|
||||
const {url, formData} = this.props.processFormData ?
|
||||
this.props.processFormData(this.refs.mainInput, this.props) :
|
||||
{url: this.refs.form.action, formData: new FormData(this.refs.form)};
|
||||
|
||||
try {
|
||||
const fetchRequest = new Request(this.refs.form.action, fetchConfig);
|
||||
const fetchRequest = new Request(url, {body: formData, method: "POST"});
|
||||
const response = await fetch(fetchRequest);
|
||||
json = await response.json();
|
||||
} catch (err) {
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
if (json && json.status === "ok") {
|
||||
this.setState({signupSuccess: true, signupSubmitted: true});
|
||||
this.props.onBlock({preventDismiss: true});
|
||||
this.props.sendUserActionTelemetry({event: "CLICK_BUTTON", value: "subscribe-success", id: "NEWTAB_FOOTER_BAR_CONTENT"});
|
||||
} else {
|
||||
console.error("There was a problem submitting the form", json || "[No JSON response]"); // eslint-disable-line no-console
|
||||
this.setState({signupSuccess: false, signupSubmitted: true});
|
||||
this.props.sendUserActionTelemetry({event: "CLICK_BUTTON", value: "subscribe-error", id: "NEWTAB_FOOTER_BAR_CONTENT"});
|
||||
}
|
||||
|
@ -74,17 +77,32 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
return Object.keys(hidden_inputs).map((key, idx) => <input key={idx} type="hidden" name={key} value={hidden_inputs[key]} />);
|
||||
}
|
||||
|
||||
renderDisclaimer() {
|
||||
const {content} = this.props;
|
||||
if (!content.scene2_disclaimer_html) {
|
||||
return null;
|
||||
}
|
||||
return (<p className="disclaimerText">
|
||||
<RichText text={content.scene2_disclaimer_html}
|
||||
localization_id="disclaimer_html"
|
||||
links={content.links}
|
||||
autoBlock={false}
|
||||
sendClick={this.props.sendClick} />
|
||||
</p>);
|
||||
}
|
||||
|
||||
renderFormPrivacyNotice() {
|
||||
const {content} = this.props;
|
||||
if (!content.scene2_privacy_html) {
|
||||
return null;
|
||||
}
|
||||
return (<label className="privacy-notice" htmlFor="id_privacy">
|
||||
return (<label className="privacyNotice" htmlFor="id_privacy">
|
||||
<p>
|
||||
<input type="checkbox" id="id_privacy" name="privacy" required="required" />
|
||||
<span><RichText text={content.scene2_privacy_html}
|
||||
localization_id="privacy_html"
|
||||
links={content.links}
|
||||
autoBlock={false}
|
||||
sendClick={this.props.sendClick} />
|
||||
</span>
|
||||
</p>
|
||||
|
@ -92,29 +110,53 @@ export class SubmitFormSnippet extends React.PureComponent {
|
|||
}
|
||||
|
||||
renderSignupSubmitted() {
|
||||
const message = this.state.signupSuccess ? this.props.content.success_text : this.props.content.error_text;
|
||||
const onButtonClick = !this.state.signupSuccess ? this.expandSnippet : null;
|
||||
const {content} = this.props;
|
||||
const isSuccess = this.state.signupSuccess;
|
||||
const successTitle = isSuccess && content.success_title;
|
||||
const bodyText = isSuccess ? content.success_text : content.error_text;
|
||||
const retryButtonText = content.scene1_button_label;
|
||||
return (<SnippetBase {...this.props}><div className="submissionStatus">
|
||||
{successTitle ? <h2 className="submitStatusTitle">{successTitle}</h2> : null}
|
||||
<p>{bodyText}{isSuccess ? null : <Button onClick={this.expandSnippet}>{retryButtonText}</Button>}</p>
|
||||
</div></SnippetBase>);
|
||||
}
|
||||
|
||||
return (<SimpleSnippet className={this.props.className}
|
||||
onButtonClick={onButtonClick}
|
||||
provider={this.props.provider}
|
||||
content={{button_label: this.props.content.scene1_button_label, text: message}} />);
|
||||
onInputChange(event) {
|
||||
if (!this.props.validateInput) {
|
||||
return;
|
||||
}
|
||||
const hasError = this.props.validateInput(event.target.value, this.props.content);
|
||||
event.target.setCustomValidity(hasError);
|
||||
}
|
||||
|
||||
renderInput() {
|
||||
const placholder = this.props.content.scene2_email_placeholder_text || this.props.content.scene2_input_placeholder;
|
||||
return (<input
|
||||
ref="mainInput"
|
||||
type={this.props.inputType || "email"}
|
||||
className="mainInput"
|
||||
name="email"
|
||||
required={true}
|
||||
placeholder={placholder}
|
||||
onChange={this.props.validateInput ? this.onInputChange : null}
|
||||
autoFocus={true} />);
|
||||
}
|
||||
|
||||
renderSignupView() {
|
||||
const {content} = this.props;
|
||||
|
||||
return (<SnippetBase {...this.props} className="SubmitFormSnippet" footerDismiss={true}>
|
||||
const containerClass = `SubmitFormSnippet ${this.props.className}`;
|
||||
return (<SnippetBase {...this.props} className={containerClass} footerDismiss={true}>
|
||||
{content.scene2_icon ? <div className="scene2Icon"><img src={content.scene2_icon} /></div> : null}
|
||||
<div className="message">
|
||||
<p>{content.scene2_text}</p>
|
||||
</div>
|
||||
<form action={content.form_action} method={this.props.form_method} onSubmit={this.handleSubmit} ref="form">
|
||||
{this.renderHiddenFormInputs()}
|
||||
<div>
|
||||
<input type="email" name="email" required="required" placeholder={content.scene2_email_placeholder_text} autoFocus={true} />
|
||||
{this.renderInput()}
|
||||
<button type="submit" className="ASRouterButton primary" ref="formSubmitBtn">{content.scene2_button_label}</button>
|
||||
</div>
|
||||
{this.renderFormPrivacyNotice()}
|
||||
{this.renderFormPrivacyNotice() || this.renderDisclaimer()}
|
||||
</form>
|
||||
</SnippetBase>);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,17 @@
|
|||
}
|
||||
},
|
||||
"properties": {
|
||||
"locale": {
|
||||
"type": "string",
|
||||
"description": "Two to five character string for the locale code"
|
||||
},
|
||||
"country": {
|
||||
"type": "string",
|
||||
"description": "Two character string for the country code (used for SMS)"
|
||||
},
|
||||
"scene1_title": {
|
||||
"allof": [
|
||||
{"$ref": "#/definitions/plaintext"},
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
{"description": "snippet title displayed before snippet text"}
|
||||
]
|
||||
},
|
||||
|
@ -31,6 +39,12 @@
|
|||
{"description": "Main body text of snippet. HTML subset allowed: i, b, u, strong, em, br"}
|
||||
]
|
||||
},
|
||||
"scene2_title": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/plainText"},
|
||||
{"description": "Title displayed before text in scene 2. Should be plain text."}
|
||||
]
|
||||
},
|
||||
"scene2_text": {
|
||||
"allOf": [
|
||||
{"$ref": "#/definitions/richText"},
|
||||
|
@ -49,6 +63,10 @@
|
|||
"type": "string",
|
||||
"description": "Endpoint to submit form data."
|
||||
},
|
||||
"success_title": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Title shown before text on successful registration."
|
||||
},
|
||||
"success_text": {
|
||||
"type": "string",
|
||||
"description": "Message shown on successful registration."
|
||||
|
@ -61,6 +79,10 @@
|
|||
"type": "string",
|
||||
"description": "Value to show while input is empty."
|
||||
},
|
||||
"scene2_input_placeholder": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Value to show while input is empty."
|
||||
},
|
||||
"scene2_button_label": {
|
||||
"type": "string",
|
||||
"description": "Label for form submit button"
|
||||
|
@ -69,10 +91,18 @@
|
|||
"type": "string",
|
||||
"description": "Information about how the form data is used."
|
||||
},
|
||||
"scene2_disclaimer_html": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Html for disclaimer and link underneath input box."
|
||||
},
|
||||
"scene2_dismiss_button_text": {
|
||||
"type": "string",
|
||||
"description": "Label for the dismiss button when the sign-up form is expanded."
|
||||
},
|
||||
"scene2_icon": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Image to display above the form. 98x98px. SVG or PNG preferred."
|
||||
},
|
||||
"hidden_inputs": {
|
||||
"type": "object",
|
||||
"description": "Each entry represents a hidden input, key is used as value for the name property."
|
||||
|
@ -83,11 +113,11 @@
|
|||
{"description": "Text for a button next to main snippet text that links to button_url. Requires button_url."}
|
||||
]
|
||||
},
|
||||
"button_color": {
|
||||
"scene1_button_color": {
|
||||
"type": "string",
|
||||
"description": "The text color of the button. Valid CSS color."
|
||||
},
|
||||
"button_background_color": {
|
||||
"scene1_button_background_color": {
|
||||
"type": "string",
|
||||
"description": "The background color of the button. Valid CSS color."
|
||||
},
|
||||
|
@ -95,6 +125,18 @@
|
|||
"type": "boolean",
|
||||
"description": "Used to prevent blocking the snippet after the CTA (link or button) has been clicked"
|
||||
},
|
||||
"include_sms": {
|
||||
"type": "boolean",
|
||||
"description": "(send to device) Allow users to send an SMS message with the form?"
|
||||
},
|
||||
"message_id_sms": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Newsletter/basket id representing the SMS message to be sent."
|
||||
},
|
||||
"message_id_email": {
|
||||
"type": "string",
|
||||
"description": "(send to device) Newsletter/basket id representing the email message to be sent. Must be a value from the 'Slug' column here: https://basket.mozilla.org/news/."
|
||||
},
|
||||
"links": {
|
||||
"additionalProperties": {
|
||||
"url": {
|
||||
|
|
|
@ -3,13 +3,29 @@
|
|||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
|
||||
&.send_to_device_snippet {
|
||||
text-align: center;
|
||||
|
||||
.message {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.ASRouterButton {
|
||||
&.primary {
|
||||
font-size: 15px;
|
||||
flex: 1 1 0;
|
||||
}
|
||||
}
|
||||
|
||||
.scene2Icon {
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 98px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -20,24 +36,34 @@
|
|||
font-size: 14px;
|
||||
align-self: stretch;
|
||||
flex: 0 0 100%;
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.privacy-notice {
|
||||
.privacyNotice {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
flex: 0 0 100%;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.innerWrapper {
|
||||
max-width: 670px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
background: $grey-20;
|
||||
background-color: var(--newtab-background-color);
|
||||
padding: 10px 0;
|
||||
|
||||
.footer-content {
|
||||
|
@ -49,11 +75,12 @@
|
|||
}
|
||||
|
||||
input {
|
||||
&[type='email'] {
|
||||
&.mainInput {
|
||||
border-radius: 3px;
|
||||
background-color: var(--newtab-textbox-background-color);
|
||||
border: $input-border;
|
||||
padding: 0 8px;
|
||||
height: 32px;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
width: 50%;
|
||||
|
||||
|
@ -64,3 +91,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: 20px 0;
|
||||
|
||||
.submitStatusTitle {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {actionCreators as ac, actionTypes as at} from "common/Actions.jsm";
|
||||
import {FormattedMessage, injectIntl} from "react-intl";
|
||||
import {cardContextTypes} from "./types";
|
||||
import {connect} from "react-redux";
|
||||
import {FormattedMessage} from "react-intl";
|
||||
import {GetPlatformString} from "content-src/lib/link-menu-options";
|
||||
import {LinkMenu} from "content-src/components/LinkMenu/LinkMenu";
|
||||
import React from "react";
|
||||
|
@ -245,7 +245,7 @@ export class _Card extends React.PureComponent {
|
|||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{!props.placeholder && <button className="context-menu-button icon"
|
||||
{!props.placeholder && <button className="context-menu-button icon" title={this.props.intl.formatMessage({id: "context_menu_title"})}
|
||||
onClick={this.onMenuButtonClick}>
|
||||
<span className="sr-only">{`Open context menu for ${link.title}`}</span>
|
||||
</button>}
|
||||
|
@ -264,5 +264,5 @@ export class _Card extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
_Card.defaultProps = {link: {}};
|
||||
export const Card = connect(state => ({platform: state.Prefs.values.platform}))(_Card);
|
||||
export const Card = connect(state => ({platform: state.Prefs.values.platform}))(injectIntl(_Card));
|
||||
export const PlaceholderCard = props => <Card placeholder={true} className={props.className} />;
|
||||
|
|
|
@ -162,6 +162,7 @@ export class _CollapsibleSection extends React.PureComponent {
|
|||
<div>
|
||||
<button
|
||||
className="context-menu-button icon"
|
||||
title={this.props.intl.formatMessage({id: "context_menu_title"})}
|
||||
onClick={this.onMenuButtonClick}
|
||||
onMouseEnter={this.onMenuButtonMouseEnter}
|
||||
onMouseLeave={this.onMenuButtonMouseLeave}>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
.confirmation-dialog {
|
||||
.modal {
|
||||
box-shadow: 0 2px 2px 0 $black-10;
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 20%;
|
||||
width: 400px;
|
||||
}
|
||||
|
|
|
@ -279,7 +279,7 @@ export class TopSite extends React.PureComponent {
|
|||
const title = link.label || link.hostname;
|
||||
return (<TopSiteLink {...props} onClick={this.onLinkClick} onDragEvent={this.props.onDragEvent} className={`${props.className || ""}${isContextMenuOpen ? " active" : ""}`} title={title}>
|
||||
<div>
|
||||
<button className="context-menu-button icon" onClick={this.onMenuButtonClick}>
|
||||
<button className="context-menu-button icon" title={this.props.intl.formatMessage({id: "context_menu_title"})} onClick={this.onMenuButtonClick}>
|
||||
<span className="sr-only">
|
||||
<FormattedMessage id="context_menu_button_sr" values={{title}} />
|
||||
</span>
|
||||
|
|
|
@ -1405,9 +1405,10 @@ a.firstrun-link {
|
|||
|
||||
.confirmation-dialog .modal {
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 20%;
|
||||
width: 400px; }
|
||||
|
||||
|
@ -1893,6 +1894,7 @@ a.firstrun-link {
|
|||
transform: scaleX(-1); }
|
||||
|
||||
.ASRouterButton {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--newtab-border-secondary-color);
|
||||
|
@ -1905,7 +1907,7 @@ a.firstrun-link {
|
|||
.tall .ASRouterButton {
|
||||
margin-inline-start: 20px; }
|
||||
.ASRouterButton.primary {
|
||||
border: 1px solid var(--newtab-border-primary-color);
|
||||
border: 1px solid var(--newtab-button-primary-color);
|
||||
background-color: var(--newtab-button-primary-color);
|
||||
color: #F9F9FA; }
|
||||
.ASRouterButton.secondary {
|
||||
|
@ -1930,6 +1932,8 @@ a.firstrun-link {
|
|||
.SnippetBaseContainer a {
|
||||
cursor: pointer;
|
||||
color: var(--newtab-link-primary-color); }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer .innerWrapper {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
|
@ -1999,9 +2003,9 @@ a.firstrun-link {
|
|||
|
||||
.modalOverlayInner {
|
||||
width: 960px;
|
||||
height: 510px;
|
||||
height: 570px;
|
||||
position: fixed;
|
||||
top: calc(50% - 255px);
|
||||
top: calc(50% - 285px);
|
||||
left: calc(50% - 480px);
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
|
@ -2054,9 +2058,9 @@ a.firstrun-link {
|
|||
position: sticky; } }
|
||||
.modalOverlayInner .footer .modalButton {
|
||||
margin-top: 20px;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
height: 30px;
|
||||
padding: 4px 0 6px;
|
||||
padding: 4px 30px 6px;
|
||||
font-size: 15px; }
|
||||
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active, .modalOverlayInner .footer .modalButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
|
@ -2094,9 +2098,17 @@ a.firstrun-link {
|
|||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.send_to_device_snippet {
|
||||
text-align: center; }
|
||||
.SubmitFormSnippet.send_to_device_snippet .message {
|
||||
font-size: 16px; }
|
||||
.SubmitFormSnippet .ASRouterButton.primary {
|
||||
font-size: 15px;
|
||||
flex: 1 1 0; }
|
||||
.SubmitFormSnippet .scene2Icon {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .scene2Icon img {
|
||||
width: 98px;
|
||||
display: inline-block; }
|
||||
.SubmitFormSnippet form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -2105,35 +2117,49 @@ a.firstrun-link {
|
|||
font-size: 14px;
|
||||
align-self: stretch;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacy-notice {
|
||||
.SubmitFormSnippet .message p {
|
||||
margin-top: 0; }
|
||||
.SubmitFormSnippet .privacyNotice {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacyNotice p {
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center; }
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px; }
|
||||
.SubmitFormSnippet .footer {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
background: #EDEDF0;
|
||||
background-color: var(--newtab-background-color);
|
||||
padding: 10px 0; }
|
||||
.SubmitFormSnippet .footer .footer-content {
|
||||
margin: 0 auto;
|
||||
max-width: 768px;
|
||||
width: 100%;
|
||||
text-align: right; }
|
||||
.SubmitFormSnippet input[type='email'] {
|
||||
.SubmitFormSnippet input.mainInput {
|
||||
border-radius: 3px;
|
||||
background-color: var(--newtab-textbox-background-color);
|
||||
border: 1px solid var(--newtab-textbox-border);
|
||||
padding: 0 8px;
|
||||
height: 32px;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
width: 50%; }
|
||||
.SubmitFormSnippet input[type='email']:focus {
|
||||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: 20px 0; }
|
||||
.submissionStatus .submitStatusTitle {
|
||||
font-size: 20px; }
|
||||
|
||||
.onboardingMessageContainer {
|
||||
display: grid;
|
||||
grid-column-gap: 21px;
|
||||
|
@ -2206,13 +2232,14 @@ a.firstrun-link {
|
|||
.onboardingMessage .onboardingContent > span > p {
|
||||
color: #4A4A4F;
|
||||
margin-top: 0;
|
||||
height: 130px;
|
||||
height: 180px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 15px;
|
||||
line-height: 22px; }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingContent > span > p {
|
||||
margin-bottom: 0; } }
|
||||
margin-bottom: 0;
|
||||
height: 160px; } }
|
||||
.onboardingMessage .onboardingButton {
|
||||
background-color: rgba(12, 12, 13, 0.1);
|
||||
border: 0;
|
||||
|
@ -2224,23 +2251,22 @@ a.firstrun-link {
|
|||
@media (max-width: 850px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: right;
|
||||
margin-top: -60px;
|
||||
margin-right: -10px; } }
|
||||
margin-top: -105px;
|
||||
margin-inline-end: -10px; } }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: none;
|
||||
margin-top: 30px; } }
|
||||
float: none; } }
|
||||
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active, .onboardingMessage .onboardingButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
transition: box-shadow 150ms; }
|
||||
.onboardingMessage::before {
|
||||
content: '';
|
||||
height: 220px;
|
||||
height: 230px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
background-color: #D7D7DB;
|
||||
margin-top: 40px;
|
||||
margin-left: 215px; }
|
||||
margin-inline-start: 215px; }
|
||||
@media (max-width: 850px) {
|
||||
.onboardingMessage::before {
|
||||
content: none; } }
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1408,9 +1408,10 @@ a.firstrun-link {
|
|||
|
||||
.confirmation-dialog .modal {
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 20%;
|
||||
width: 400px; }
|
||||
|
||||
|
@ -1896,6 +1897,7 @@ a.firstrun-link {
|
|||
transform: scaleX(-1); }
|
||||
|
||||
.ASRouterButton {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--newtab-border-secondary-color);
|
||||
|
@ -1908,7 +1910,7 @@ a.firstrun-link {
|
|||
.tall .ASRouterButton {
|
||||
margin-inline-start: 20px; }
|
||||
.ASRouterButton.primary {
|
||||
border: 1px solid var(--newtab-border-primary-color);
|
||||
border: 1px solid var(--newtab-button-primary-color);
|
||||
background-color: var(--newtab-button-primary-color);
|
||||
color: #F9F9FA; }
|
||||
.ASRouterButton.secondary {
|
||||
|
@ -1933,6 +1935,8 @@ a.firstrun-link {
|
|||
.SnippetBaseContainer a {
|
||||
cursor: pointer;
|
||||
color: var(--newtab-link-primary-color); }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer .innerWrapper {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
|
@ -2002,9 +2006,9 @@ a.firstrun-link {
|
|||
|
||||
.modalOverlayInner {
|
||||
width: 960px;
|
||||
height: 510px;
|
||||
height: 570px;
|
||||
position: fixed;
|
||||
top: calc(50% - 255px);
|
||||
top: calc(50% - 285px);
|
||||
left: calc(50% - 480px);
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
|
@ -2057,9 +2061,9 @@ a.firstrun-link {
|
|||
position: sticky; } }
|
||||
.modalOverlayInner .footer .modalButton {
|
||||
margin-top: 20px;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
height: 30px;
|
||||
padding: 4px 0 6px;
|
||||
padding: 4px 30px 6px;
|
||||
font-size: 15px; }
|
||||
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active, .modalOverlayInner .footer .modalButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
|
@ -2097,9 +2101,17 @@ a.firstrun-link {
|
|||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.send_to_device_snippet {
|
||||
text-align: center; }
|
||||
.SubmitFormSnippet.send_to_device_snippet .message {
|
||||
font-size: 16px; }
|
||||
.SubmitFormSnippet .ASRouterButton.primary {
|
||||
font-size: 15px;
|
||||
flex: 1 1 0; }
|
||||
.SubmitFormSnippet .scene2Icon {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .scene2Icon img {
|
||||
width: 98px;
|
||||
display: inline-block; }
|
||||
.SubmitFormSnippet form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -2108,35 +2120,49 @@ a.firstrun-link {
|
|||
font-size: 14px;
|
||||
align-self: stretch;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacy-notice {
|
||||
.SubmitFormSnippet .message p {
|
||||
margin-top: 0; }
|
||||
.SubmitFormSnippet .privacyNotice {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacyNotice p {
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center; }
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px; }
|
||||
.SubmitFormSnippet .footer {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
background: #EDEDF0;
|
||||
background-color: var(--newtab-background-color);
|
||||
padding: 10px 0; }
|
||||
.SubmitFormSnippet .footer .footer-content {
|
||||
margin: 0 auto;
|
||||
max-width: 768px;
|
||||
width: 100%;
|
||||
text-align: right; }
|
||||
.SubmitFormSnippet input[type='email'] {
|
||||
.SubmitFormSnippet input.mainInput {
|
||||
border-radius: 3px;
|
||||
background-color: var(--newtab-textbox-background-color);
|
||||
border: 1px solid var(--newtab-textbox-border);
|
||||
padding: 0 8px;
|
||||
height: 32px;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
width: 50%; }
|
||||
.SubmitFormSnippet input[type='email']:focus {
|
||||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: 20px 0; }
|
||||
.submissionStatus .submitStatusTitle {
|
||||
font-size: 20px; }
|
||||
|
||||
.onboardingMessageContainer {
|
||||
display: grid;
|
||||
grid-column-gap: 21px;
|
||||
|
@ -2209,13 +2235,14 @@ a.firstrun-link {
|
|||
.onboardingMessage .onboardingContent > span > p {
|
||||
color: #4A4A4F;
|
||||
margin-top: 0;
|
||||
height: 130px;
|
||||
height: 180px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 15px;
|
||||
line-height: 22px; }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingContent > span > p {
|
||||
margin-bottom: 0; } }
|
||||
margin-bottom: 0;
|
||||
height: 160px; } }
|
||||
.onboardingMessage .onboardingButton {
|
||||
background-color: rgba(12, 12, 13, 0.1);
|
||||
border: 0;
|
||||
|
@ -2227,23 +2254,22 @@ a.firstrun-link {
|
|||
@media (max-width: 850px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: right;
|
||||
margin-top: -60px;
|
||||
margin-right: -10px; } }
|
||||
margin-top: -105px;
|
||||
margin-inline-end: -10px; } }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: none;
|
||||
margin-top: 30px; } }
|
||||
float: none; } }
|
||||
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active, .onboardingMessage .onboardingButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
transition: box-shadow 150ms; }
|
||||
.onboardingMessage::before {
|
||||
content: '';
|
||||
height: 220px;
|
||||
height: 230px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
background-color: #D7D7DB;
|
||||
margin-top: 40px;
|
||||
margin-left: 215px; }
|
||||
margin-inline-start: 215px; }
|
||||
@media (max-width: 850px) {
|
||||
.onboardingMessage::before {
|
||||
content: none; } }
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1405,9 +1405,10 @@ a.firstrun-link {
|
|||
|
||||
.confirmation-dialog .modal {
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);
|
||||
left: 50%;
|
||||
margin-left: -200px;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
top: 20%;
|
||||
width: 400px; }
|
||||
|
||||
|
@ -1893,6 +1894,7 @@ a.firstrun-link {
|
|||
transform: scaleX(-1); }
|
||||
|
||||
.ASRouterButton {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--newtab-border-secondary-color);
|
||||
|
@ -1905,7 +1907,7 @@ a.firstrun-link {
|
|||
.tall .ASRouterButton {
|
||||
margin-inline-start: 20px; }
|
||||
.ASRouterButton.primary {
|
||||
border: 1px solid var(--newtab-border-primary-color);
|
||||
border: 1px solid var(--newtab-button-primary-color);
|
||||
background-color: var(--newtab-button-primary-color);
|
||||
color: #F9F9FA; }
|
||||
.ASRouterButton.secondary {
|
||||
|
@ -1930,6 +1932,8 @@ a.firstrun-link {
|
|||
.SnippetBaseContainer a {
|
||||
cursor: pointer;
|
||||
color: var(--newtab-link-primary-color); }
|
||||
[lwt-newtab-brighttext] .SnippetBaseContainer a {
|
||||
font-weight: bold; }
|
||||
.SnippetBaseContainer .innerWrapper {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
|
@ -1999,9 +2003,9 @@ a.firstrun-link {
|
|||
|
||||
.modalOverlayInner {
|
||||
width: 960px;
|
||||
height: 510px;
|
||||
height: 570px;
|
||||
position: fixed;
|
||||
top: calc(50% - 255px);
|
||||
top: calc(50% - 285px);
|
||||
left: calc(50% - 480px);
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
|
@ -2054,9 +2058,9 @@ a.firstrun-link {
|
|||
position: sticky; } }
|
||||
.modalOverlayInner .footer .modalButton {
|
||||
margin-top: 20px;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
height: 30px;
|
||||
padding: 4px 0 6px;
|
||||
padding: 4px 30px 6px;
|
||||
font-size: 15px; }
|
||||
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active, .modalOverlayInner .footer .modalButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
|
@ -2094,9 +2098,17 @@ a.firstrun-link {
|
|||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet.send_to_device_snippet {
|
||||
text-align: center; }
|
||||
.SubmitFormSnippet.send_to_device_snippet .message {
|
||||
font-size: 16px; }
|
||||
.SubmitFormSnippet .ASRouterButton.primary {
|
||||
font-size: 15px;
|
||||
flex: 1 1 0; }
|
||||
.SubmitFormSnippet .scene2Icon {
|
||||
width: 100%; }
|
||||
.SubmitFormSnippet .scene2Icon img {
|
||||
width: 98px;
|
||||
display: inline-block; }
|
||||
.SubmitFormSnippet form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -2105,35 +2117,49 @@ a.firstrun-link {
|
|||
font-size: 14px;
|
||||
align-self: stretch;
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacy-notice {
|
||||
.SubmitFormSnippet .message p {
|
||||
margin-top: 0; }
|
||||
.SubmitFormSnippet .privacyNotice {
|
||||
color: var(--newtab-text-secondary-color);
|
||||
flex: 0 0 100%; }
|
||||
.SubmitFormSnippet .privacyNotice p {
|
||||
margin-bottom: 0; }
|
||||
.SubmitFormSnippet .innerWrapper {
|
||||
max-width: 670px;
|
||||
flex-wrap: wrap;
|
||||
justify-items: center; }
|
||||
justify-items: center;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px; }
|
||||
.SubmitFormSnippet .footer {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
background: #EDEDF0;
|
||||
background-color: var(--newtab-background-color);
|
||||
padding: 10px 0; }
|
||||
.SubmitFormSnippet .footer .footer-content {
|
||||
margin: 0 auto;
|
||||
max-width: 768px;
|
||||
width: 100%;
|
||||
text-align: right; }
|
||||
.SubmitFormSnippet input[type='email'] {
|
||||
.SubmitFormSnippet input.mainInput {
|
||||
border-radius: 3px;
|
||||
background-color: var(--newtab-textbox-background-color);
|
||||
border: 1px solid var(--newtab-textbox-border);
|
||||
padding: 0 8px;
|
||||
height: 32px;
|
||||
height: 100%;
|
||||
font-size: 15px;
|
||||
width: 50%; }
|
||||
.SubmitFormSnippet input[type='email']:focus {
|
||||
.SubmitFormSnippet input.mainInput:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
|
||||
.submissionStatus {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
padding: 20px 0; }
|
||||
.submissionStatus .submitStatusTitle {
|
||||
font-size: 20px; }
|
||||
|
||||
.onboardingMessageContainer {
|
||||
display: grid;
|
||||
grid-column-gap: 21px;
|
||||
|
@ -2206,13 +2232,14 @@ a.firstrun-link {
|
|||
.onboardingMessage .onboardingContent > span > p {
|
||||
color: #4A4A4F;
|
||||
margin-top: 0;
|
||||
height: 130px;
|
||||
height: 180px;
|
||||
margin-bottom: 12px;
|
||||
font-size: 15px;
|
||||
line-height: 22px; }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingContent > span > p {
|
||||
margin-bottom: 0; } }
|
||||
margin-bottom: 0;
|
||||
height: 160px; } }
|
||||
.onboardingMessage .onboardingButton {
|
||||
background-color: rgba(12, 12, 13, 0.1);
|
||||
border: 0;
|
||||
|
@ -2224,23 +2251,22 @@ a.firstrun-link {
|
|||
@media (max-width: 850px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: right;
|
||||
margin-top: -60px;
|
||||
margin-right: -10px; } }
|
||||
margin-top: -105px;
|
||||
margin-inline-end: -10px; } }
|
||||
@media (max-width: 650px) {
|
||||
.onboardingMessage .onboardingButton {
|
||||
float: none;
|
||||
margin-top: 30px; } }
|
||||
float: none; } }
|
||||
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active, .onboardingMessage .onboardingButton:hover {
|
||||
box-shadow: 0 0 0 5px #D7D7DB;
|
||||
transition: box-shadow 150ms; }
|
||||
.onboardingMessage::before {
|
||||
content: '';
|
||||
height: 220px;
|
||||
height: 230px;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
background-color: #D7D7DB;
|
||||
margin-top: 40px;
|
||||
margin-left: 215px; }
|
||||
margin-inline-start: 215px; }
|
||||
@media (max-width: 850px) {
|
||||
.onboardingMessage::before {
|
||||
content: none; } }
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -16,7 +16,9 @@ const DEFAULT_STATE = {
|
|||
_devtoolsPref: DEVTOOLS_PREF,
|
||||
};
|
||||
|
||||
const USER_PREFERENCES = {snippets: "browser.newtabpage.activity-stream.feeds.snippets"};
|
||||
const USER_PREFERENCES = {
|
||||
snippets: "browser.newtabpage.activity-stream.feeds.snippets",
|
||||
};
|
||||
|
||||
const TEST_PROVIDER = {
|
||||
id: "snippets_local_testing",
|
||||
|
|
|
@ -60,6 +60,48 @@ function CachedTargetingGetter(property, options = null, updateInterval = FRECEN
|
|||
};
|
||||
}
|
||||
|
||||
function CheckBrowserNeedsUpdate(updateInterval = FRECENT_SITES_UPDATE_INTERVAL) {
|
||||
const UpdateChecker = Cc["@mozilla.org/updates/update-checker;1"].createInstance(Ci.nsIUpdateChecker);
|
||||
const checker = {
|
||||
_lastUpdated: 0,
|
||||
_value: null,
|
||||
// For testing. Avoid update check network call.
|
||||
setUp(value) {
|
||||
this._lastUpdated = Date.now();
|
||||
this._value = value;
|
||||
},
|
||||
expire() {
|
||||
this._lastUpdated = 0;
|
||||
this._value = null;
|
||||
},
|
||||
get() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const now = Date.now();
|
||||
const updateServiceListener = {
|
||||
onCheckComplete(request, updates, updateCount) {
|
||||
checker._value = updateCount > 0;
|
||||
resolve(checker._value);
|
||||
},
|
||||
onError(request, update) {
|
||||
reject(request);
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckListener"]),
|
||||
};
|
||||
|
||||
if (now - this._lastUpdated >= updateInterval) {
|
||||
UpdateChecker.checkForUpdates(updateServiceListener, true);
|
||||
this._lastUpdated = now;
|
||||
} else {
|
||||
resolve(this._value);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return checker;
|
||||
}
|
||||
|
||||
const QueryCache = {
|
||||
expireAll() {
|
||||
Object.keys(this.queries).forEach(query => {
|
||||
|
@ -78,6 +120,7 @@ const QueryCache = {
|
|||
}
|
||||
),
|
||||
TotalBookmarksCount: new CachedTargetingGetter("getTotalBookmarksCount"),
|
||||
CheckBrowserNeedsUpdate: new CheckBrowserNeedsUpdate(),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -218,6 +261,9 @@ const TargetingGetters = {
|
|||
get region() {
|
||||
return Services.prefs.getStringPref(SEARCH_REGION_PREF, "");
|
||||
},
|
||||
get needsUpdate() {
|
||||
return QueryCache.queries.CheckBrowserNeedsUpdate.get();
|
||||
},
|
||||
};
|
||||
|
||||
this.ASRouterTargeting = {
|
||||
|
|
|
@ -93,10 +93,10 @@ this.ManualMigration = class ManualMigration {
|
|||
this.store.dispatch({type: at.MIGRATION_COMPLETED});
|
||||
}
|
||||
|
||||
onAction(action) {
|
||||
async onAction(action) {
|
||||
switch (action.type) {
|
||||
case at.PREFS_INITIAL_VALUES:
|
||||
this.expireIfNecessary(action.data.migrationExpired);
|
||||
await this.expireIfNecessary(action.data.migrationExpired);
|
||||
break;
|
||||
case at.MIGRATION_START:
|
||||
MigrationUtils.showMigrationWizard(action._target.browser.ownerGlobal, [MigrationUtils.MIGRATION_ENTRYPOINT_NEWTAB]);
|
||||
|
|
|
@ -16,6 +16,17 @@ const MESSAGES = () => ([
|
|||
"block_button_text": "Block",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "SIMPLE_TEST_BUTTON_URL_1",
|
||||
"template": "simple_snippet",
|
||||
"content": {
|
||||
"icon": TEST_ICON,
|
||||
"button_label": "Get one now!",
|
||||
"button_url": "https://www.mozilla.org/en-US/firefox/accounts",
|
||||
"text": "Sync it, link it, take it with you. All this and more with a Firefox Account.",
|
||||
"block_button_text": "Block",
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": "SIMPLE_WITH_TITLE_TEST_1",
|
||||
"template": "simple_snippet",
|
||||
|
@ -36,9 +47,8 @@ const MESSAGES = () => ([
|
|||
"scene1_title_icon": "",
|
||||
"scene1_text": "Internet shutdowns, hackers, harassment – the health of the internet is on the line. Sign up and Mozilla will keep you updated on how you can help.",
|
||||
"scene1_button_label": "Continue",
|
||||
// TODO: Need to update schema
|
||||
// "scene1_button_color": "#712b00",
|
||||
// "scene1_button_background_color": "#ff9400",
|
||||
"scene1_button_color": "#712b00",
|
||||
"scene1_button_background_color": "#ff9400",
|
||||
"scene2_dismiss_button_text": "Dismiss",
|
||||
"scene2_text": "Sign up for the Mozilla newsletter and we will keep you updated on how you can help.",
|
||||
"scene2_privacy_html": "I'm okay with Mozilla handling my info as explained in this <privacyLink>Privacy Notice</privacyLink>.",
|
||||
|
@ -61,17 +71,15 @@ const MESSAGES = () => ([
|
|||
"content": {
|
||||
"scene1_icon": TEST_ICON,
|
||||
"scene1_button_label": "Get connected with sync!",
|
||||
// TODO: Need to update schema
|
||||
// "scene1_button_color": "#712b00",
|
||||
// "scene1_button_background_color": "#ff9400",
|
||||
"scene1_button_color": "#712b00",
|
||||
"scene1_button_background_color": "#ff9400",
|
||||
|
||||
"scene1_text": "Connect to Firefox by securely syncing passwords, bookmarks, and open tabs.",
|
||||
"scene1_title": "Browser better.",
|
||||
"scene1_title_icon": "",
|
||||
|
||||
"scene2_text": "Connect to your Firefox account to securely sync passwords, bookmarks, and open tabs.",
|
||||
// TODO: needs to be added
|
||||
// "scene2_title": "Title 123",
|
||||
"scene2_title": "Title 123",
|
||||
"scene2_email_placeholder_text": "Your email",
|
||||
"scene2_button_label": "Continue",
|
||||
"scene2_dismiss_button_text": "Dismiss",
|
||||
|
@ -83,6 +91,42 @@ const MESSAGES = () => ([
|
|||
"hidden_inputs": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "SNIPPETS_SEND_TO_DEVICE_TEST",
|
||||
template: "send_to_device_snippet",
|
||||
content: {
|
||||
include_sms: true,
|
||||
locale: "en-CA",
|
||||
country: "us",
|
||||
message_id_sms: "ff-mobilesn-download",
|
||||
message_id_email: "download-firefox-mobile",
|
||||
|
||||
scene1_button_background_color: "#6200a4",
|
||||
scene1_button_color: "#FFFFFF",
|
||||
scene1_button_label: "Install now",
|
||||
scene1_icon: TEST_ICON,
|
||||
scene1_text: "Browse without compromise with Firefox Mobile.",
|
||||
scene1_title: "Full-featured. Customizable. Lightning fast",
|
||||
scene1_title_icon: "",
|
||||
|
||||
scene2_button_label: "Send",
|
||||
scene2_disclaimer_html: "The intended recipient of the email must have consented. <privacyLink>Learn more.</privacyLink>",
|
||||
scene2_dismiss_button_text: "Dismiss",
|
||||
scene2_icon: TEST_ICON,
|
||||
scene2_input_placeholder: "Your email address or phone number",
|
||||
scene2_text: "Send Firefox to your phone and take a powerful independent browser with you.",
|
||||
scene2_title: "",
|
||||
|
||||
error_text: "Oops, there was a problem.",
|
||||
success_title: "Your download link was sent.",
|
||||
success_text: "Check your device for the email message!",
|
||||
links: {"privacyLink": {"url": "https://www.mozilla.org/privacy/websites/?sample_rate=0.001&snippet_name=7894"}},
|
||||
|
||||
// TODO: Not actually defined in the send to device schema
|
||||
form_action: "https://basket.mozilla.org/subscribe.json",
|
||||
hidden_inputs: {},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const SnippetsTestMessageProvider = {
|
||||
|
|
|
@ -143,9 +143,9 @@ pocket_read_more=Папулярныя тэмы:
|
|||
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
|
||||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Іншыя навіны
|
||||
|
||||
pocket_more_reccommendations=Больш рэкамендацый
|
||||
pocket_learn_more=Падрабязней
|
||||
pocket_how_it_works=Як гэта працуе
|
||||
pocket_cta_button=Атрымаць Pocket
|
||||
pocket_cta_text=Захоўвайце ўлюбёныя гісторыі ў Pocket, і сілкуйце свой розум добрай чытанкай.
|
||||
|
||||
|
@ -196,7 +196,6 @@ firstrun_form_header=Увядзіце сваю электронную пошту
|
|||
firstrun_form_sub_header=каб прадоўжыць з Firefox Sync.
|
||||
|
||||
firstrun_email_input_placeholder=Эл.пошта
|
||||
|
||||
firstrun_invalid_input=Патрабуецца сапраўдны адрас эл.пошты
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
|
@ -143,6 +143,8 @@ pocket_read_more=জনপ্রিয় বিষয়:
|
|||
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
|
||||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=আরও গল্প দেখুন
|
||||
pocket_learn_more=আরও জানুন
|
||||
pocket_how_it_works=কিভাবে এটা কাজ করে
|
||||
|
||||
highlights_empty_state=ব্রাউজি করা শুরু করুন, এবং কিছু গুরুত্বপূর্ণ নিবন্ধ, ভিডিও, এবং আপনি সম্প্রতি পরিদর্শন বা বুকমার্ক করেছেন এমন কিছু পৃষ্ঠা আমরা এখানে প্রদর্শন করব।
|
||||
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
|
||||
|
@ -191,7 +193,6 @@ firstrun_form_header=আপনার ই-মেইল লিখুন
|
|||
firstrun_form_sub_header=Firefox সিঙ্ক চালিয়ে যেতে
|
||||
|
||||
firstrun_email_input_placeholder=ইমেইল
|
||||
|
||||
firstrun_invalid_input=কার্যকর ইমেইল আবশ্যক
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
|
@ -144,6 +144,12 @@ pocket_read_more=Danvezioù brudet:
|
|||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Gwelet muioc'h a istorioù
|
||||
|
||||
pocket_more_reccommendations=Erbedadennoù ouzhpenn
|
||||
pocket_learn_more=Gouzout hiroc'h
|
||||
pocket_how_it_works=Penaos ez a en-dro
|
||||
pocket_cta_button=Staliañ Pocket
|
||||
pocket_cta_text=Enrollit pennadoù a-zoare e Pocket ha magit ho spered gant lennadennoù boemus.
|
||||
|
||||
highlights_empty_state=Krogit da verdeiñ hag e tiskouezimp deoc’h pennadoù, videoioù ha pajennoù all gweladennet pe lakaet er sinedoù nevez ’zo.
|
||||
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
|
||||
# in the space that would have shown a few stories, this is shown instead.
|
||||
|
@ -173,6 +179,7 @@ section_menu_action_expand_section=Astenn ar gevrenn
|
|||
section_menu_action_manage_section=Merañ ar gevrenn
|
||||
section_menu_action_manage_webext=Merañ an askouezh
|
||||
section_menu_action_add_topsite=Ouzhpennañ ul lec'hienn gwellañ din
|
||||
section_menu_action_add_search_engine=Ouzhpennañ ul lusker klask
|
||||
section_menu_action_move_up=Dilec'hiañ etrezek ar c'hrec'h
|
||||
section_menu_action_move_down=Dilec'hiañ etrezek an traoñ
|
||||
section_menu_action_privacy_notice=Evezhiadennoù a-fet buhez prevez
|
||||
|
@ -201,4 +208,3 @@ firstrun_privacy_notice=evezhiadennoù a-fet buhez prevez
|
|||
|
||||
firstrun_continue_to_login=Kenderc'hel
|
||||
firstrun_skip_login=Tremen ar bazenn-mañ
|
||||
section_menu_action_add_search_engine=Ouzhpennañ ul lusker enklask
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Mostra més articles
|
|||
|
||||
pocket_more_reccommendations=Més recomanacions
|
||||
pocket_learn_more=Més informació
|
||||
pocket_how_it_works=Com funciona
|
||||
pocket_cta_button=Obtén el Pocket
|
||||
pocket_cta_text=Deseu els vostres articles preferits al Pocket i gaudiu d'altres recomanacions fascinants.
|
||||
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Gweld Rhagor o Straeon
|
|||
|
||||
pocket_more_reccommendations=Rhagor o Argymhellion
|
||||
pocket_learn_more=Dysgu Rhagor
|
||||
pocket_how_it_works=Sut mae'n gweithio
|
||||
pocket_cta_button=Defnyddio Pocket
|
||||
pocket_cta_text=Cadw'r straeon rydych yn eu hoffi i Pocket a bwydo'ch meddwl á deunydd diddorol.
|
||||
|
|
@ -205,3 +205,6 @@ firstrun_privacy_notice=Privacy Notice
|
|||
|
||||
firstrun_continue_to_login=Continue
|
||||
firstrun_skip_login=Skip this step
|
||||
|
||||
# LOCALIZATION NOTE (context_menu_title): Action tooltip to open a context menu
|
||||
context_menu_title=Open menu
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Ver más historias
|
|||
|
||||
pocket_more_reccommendations=Más recomendaciones
|
||||
pocket_learn_more=Conocer más
|
||||
pocket_how_it_works=Cómo funciona
|
||||
pocket_cta_button=Obtener Pocket
|
||||
pocket_cta_text=Guarde las historias que quiera en Pocket y potencie su mente con lecturas fascinantes.
|
||||
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Ver más historias
|
|||
|
||||
pocket_more_reccommendations=Más recomendaciones
|
||||
pocket_learn_more=Aprender más
|
||||
pocket_how_it_works=Cómo funciona
|
||||
pocket_cta_button=Obtener Pocket
|
||||
pocket_cta_text=Guarda las historias que amas en Pocket, y potencia tu mente con fascinantes lecturas.
|
||||
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Ikusi istorio gehiago
|
|||
|
||||
pocket_more_reccommendations=Gomendio gehiago
|
||||
pocket_learn_more=Argibide gehiago
|
||||
pocket_how_it_works=Nola dabilen
|
||||
pocket_cta_button=Eskuratu Pocket
|
||||
pocket_cta_text=Gorde gogoko dituzun istorioak Pocket-en eta piztu zure gogoa irakurgai erakargarriekin.
|
||||
|
|
@ -143,9 +143,9 @@ pocket_read_more=موضوعهای محبوب:
|
|||
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
|
||||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=مشاهده داستانهای بیشتر
|
||||
|
||||
pocket_more_reccommendations=توصیههای بیشتر
|
||||
pocket_learn_more=بیشتر بدانید
|
||||
pocket_how_it_works=این چجوری کار میکنه
|
||||
pocket_cta_button=دریافت پاکت
|
||||
pocket_cta_text=داستانهایی را که دوست دارید در پاکت خود ذخیره کنید و ذهن خود را با خواندنیهای جذاب پرورش دهید.
|
||||
|
||||
|
@ -196,7 +196,6 @@ firstrun_form_header=پستالکترونیکی خود را وارد کنید
|
|||
firstrun_form_sub_header=برای فعال کردن همگامسازی فایرفاکس.
|
||||
|
||||
firstrun_email_input_placeholder=پستالکترونیکی
|
||||
|
||||
firstrun_invalid_input=رایانامهٔ معتبر لازم است
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
|
@ -143,9 +143,9 @@ pocket_read_more=Suositut aiheet:
|
|||
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
|
||||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Katso lisää juttuja
|
||||
|
||||
pocket_more_reccommendations=Lisää suosituksia
|
||||
pocket_learn_more=Lue lisää
|
||||
pocket_how_it_works=Kuinka se toimii
|
||||
pocket_cta_button=Hanki Pocket
|
||||
pocket_cta_text=Tallenna tykkäämäsi tekstit Pocketiin ja ravitse mieltäsi kiinnostavilla teksteillä.
|
||||
|
||||
|
@ -196,7 +196,6 @@ firstrun_form_header=Kirjoita sähköpostisi
|
|||
firstrun_form_sub_header=jatkaaksesi Firefox Sync -palveluun.
|
||||
|
||||
firstrun_email_input_placeholder=Sähköposti
|
||||
|
||||
firstrun_invalid_input=Sähköpostiosoitteen täytyy olla kelvollinen
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Afficher plus d’articles
|
|||
|
||||
pocket_more_reccommendations=Plus de recommandations
|
||||
pocket_learn_more=En savoir plus
|
||||
pocket_how_it_works=Mode d'emploi
|
||||
pocket_cta_button=Installer Pocket
|
||||
pocket_cta_text=Enregistrez les articles que vous aimez dans Pocket, et stimulez votre imagination avec des lectures fascinantes.
|
||||
|
|
@ -177,7 +177,7 @@ section_menu_action_remove_section=Szakasz eltávolítása
|
|||
section_menu_action_collapse_section=Szakasz összecsukása
|
||||
section_menu_action_expand_section=Szakasz lenyitása
|
||||
section_menu_action_manage_section=Szakasz kezelése
|
||||
section_menu_action_manage_webext=Kiterjesztés kezelése
|
||||
section_menu_action_manage_webext=Kiegészítő kezelése
|
||||
section_menu_action_add_topsite=Hozzáadás a népszerű oldalakhoz
|
||||
section_menu_action_add_search_engine=Keresőszolgáltatás hozzáadása
|
||||
section_menu_action_move_up=Mozgatás felfelé
|
|
@ -143,10 +143,11 @@ pocket_read_more=Topik Populer:
|
|||
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
|
||||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Lihat Cerita Lainnya
|
||||
|
||||
pocket_more_reccommendations=Rekomendasi Lainnya
|
||||
pocket_learn_more=Pelajari Lebih Lanjut
|
||||
pocket_how_it_works=Panduan
|
||||
pocket_cta_button=Dapatkan Pocket
|
||||
pocket_cta_text=Simpan cerita yang anda sukai di Pocket, dan dapatkan bacaan menarik untuk Anda.
|
||||
|
||||
highlights_empty_state=Mulai menjelajah, dan kami akan menampilkan beberapa artikel bagus, video, dan halaman lain yang baru saja Anda kunjungi atau termarkah di sini.
|
||||
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
|
||||
|
@ -195,7 +196,6 @@ firstrun_form_header=Masukkan surel Anda
|
|||
firstrun_form_sub_header=Lanjutkan ke Firefox Sync.
|
||||
|
||||
firstrun_email_input_placeholder=Surel
|
||||
|
||||
firstrun_invalid_input=Surel harus valid
|
||||
|
||||
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Көбірек хикаяларды қарау
|
|||
|
||||
pocket_more_reccommendations=Көбірек ұсыныстар
|
||||
pocket_learn_more=Көбірек білу
|
||||
pocket_how_it_works=Ол қалай жұмыс істейді
|
||||
pocket_cta_button=Pocket-ті алу
|
||||
pocket_cta_text=Өзіңіз ұнатқан хикаяларды Pocket ішіне сақтап, миіңізді тамаша оқумен толықтырыңыз.
|
||||
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=더 많은 이야기 보기
|
|||
|
||||
pocket_more_reccommendations=더 많은 추천
|
||||
pocket_learn_more=자세히 보기
|
||||
pocket_how_it_works=사용 방법
|
||||
pocket_cta_button=Pocket 받기
|
||||
pocket_cta_text=좋아하는 이야기를 Pocket에 저장하고 재미있게 읽어 보세요.
|
||||
|
|
@ -30,8 +30,8 @@ type_label_downloaded=ດາວໂຫຼດແລ້ວ
|
|||
# bookmarks"
|
||||
menu_action_bookmark=ບຸກມາກ
|
||||
menu_action_remove_bookmark=ລຶບບຸກມາກອອກ
|
||||
menu_action_open_new_window=ເປີດລີ້ງໃນຫນ້າຕ່າງໃຫມ່
|
||||
menu_action_open_private_window=ເປີດໃນຫນ້າຕ່າງສ່ວນຕົວໃຫມ່
|
||||
menu_action_open_new_window=ເປີດລີ້ງໃນວິນໂດໃຫມ່
|
||||
menu_action_open_private_window=ເປີດໃນວິນໂດສ່ວນຕົວໃຫມ່
|
||||
menu_action_dismiss=ຍົກເລີກ
|
||||
menu_action_delete=ລຶບອອກຈາກປະຫວັດການນຳໃຊ້
|
||||
menu_action_pin=ປັກໝຸດ
|
||||
|
@ -168,7 +168,7 @@ manual_migration_import_button=ນຳເຂົ້າຕອນນີ້
|
|||
# LOCALIZATION NOTE (error_fallback_default_*): This message and suggested
|
||||
# action link are shown in each section of UI that fails to render
|
||||
error_fallback_default_info=ໂອ້ຍ, ມີບາງສິ່ງບາງຢ່າງຜິດພາດໃນການໂຫລດເນື້ອຫານີ້.
|
||||
error_fallback_default_refresh_suggestion=ຣີເຟຣຊຫນ້າເພື່ອລອງອີກຄັ້ງ.
|
||||
error_fallback_default_refresh_suggestion=ຟື້ນຟູໜ້າເພື່ອລອງອີກຄັ້ງ.
|
||||
|
||||
# LOCALIZATION NOTE (section_menu_action_*). These strings are displayed in the section
|
||||
# context menu and are meant as a call to action for the given section.
|
|
@ -146,6 +146,7 @@ pocket_read_even_more=Rodyti daugiau straipsnių
|
|||
|
||||
pocket_more_reccommendations=Daugiau rekomendacijų
|
||||
pocket_learn_more=Sužinoti daugiau
|
||||
pocket_how_it_works=Kaip tai veikia
|
||||
pocket_cta_button=Gauti „Pocket“
|
||||
pocket_cta_text=Išsaugokite patinkančius straipsnius į „Pocket“, bei sužadinkite savo mintis stulbinančiomis istorijomis.
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче