Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Bogdan Tara 2018-02-10 12:02:18 +02:00
Родитель 7fa839175a 5bbbbe17bc
Коммит f55c490734
334 изменённых файлов: 20423 добавлений и 23610 удалений

Просмотреть файл

@ -345,7 +345,7 @@ enum Role {
/**
* Represents a spin box, which is a control that allows the user to increment
* or decrement the value displayed in a separate "buddy" control associated
* with the spin box. It is used for xul:spinbuttons.
* with the spin box. It is used for input[type=number] spin buttons.
*/
SPINBUTTON = 52,

Просмотреть файл

@ -338,7 +338,7 @@ interface nsIAccessibleRole : nsISupports
/**
* Represents a spin box, which is a control that allows the user to increment
* or decrement the value displayed in a separate "buddy" control associated
* with the spin box. It is used for xul:spinbuttons.
* with the spin box. It is used for input[type=number] spin buttons.
*/
const unsigned long ROLE_SPINBUTTON = 52;

Просмотреть файл

@ -75,10 +75,12 @@
accTree =
{ SECTION: [
{ ENTRY: [ { TEXT_LEAF: [] } ] },
{ SPINBUTTON: [
{ ENTRY: [ { TEXT_LEAF: [] } ] },
{ PUSHBUTTON: [ ] },
{ PUSHBUTTON: [ ] }
] },
{ MENUPOPUP: [] },
{ PUSHBUTTON: [] },
{ PUSHBUTTON: [] }
] };
testAccessibleTree("txc_number", accTree);

Просмотреть файл

@ -119,6 +119,25 @@ var SidebarUI = {
this._switcherTarget.classList.add("active");
},
updateShortcut({button, key}) {
// If the shortcuts haven't been rendered yet then it will be set correctly
// on the first render so there's nothing to do now.
if (!this._addedShortcuts) {
return;
}
if (key) {
let keyId = key.getAttribute("id");
button = this._switcherPanel.querySelector(`[key="${keyId}"]`);
} else if (button) {
let keyId = button.getAttribute("key");
key = document.getElementById(keyId);
}
if (!button || !key) {
return;
}
button.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(key));
},
_addedShortcuts: false,
_ensureShortcutsShown() {
if (this._addedShortcuts) {
@ -126,12 +145,7 @@ var SidebarUI = {
}
this._addedShortcuts = true;
for (let button of this._switcherPanel.querySelectorAll("toolbarbutton[key]")) {
let keyId = button.getAttribute("key");
let key = document.getElementById(keyId);
if (!key) {
continue;
}
button.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(key));
this.updateShortcut({button});
}
},

Просмотреть файл

@ -35,6 +35,7 @@
"url": "chrome://browser/content/ext-commands.js",
"schema": "chrome://browser/content/schemas/commands.json",
"scopes": ["addon_parent"],
"events": ["uninstall"],
"manifest": ["commands"],
"paths": [
["commands"]

Просмотреть файл

@ -8,41 +8,91 @@
ChromeUtils.defineModuleGetter(this, "ExtensionParent",
"resource://gre/modules/ExtensionParent.jsm");
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
var XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const EXECUTE_PAGE_ACTION = "_execute_page_action";
const EXECUTE_BROWSER_ACTION = "_execute_browser_action";
const EXECUTE_SIDEBAR_ACTION = "_execute_sidebar_action";
function normalizeShortcut(shortcut) {
return shortcut ? shortcut.replace(/\s+/g, "") : null;
}
this.commands = class extends ExtensionAPI {
onManifestEntry(entryName) {
static async onUninstall(extensionId) {
// Cleanup the updated commands. In some cases the extension is installed
// and uninstalled so quickly that `this.commands` hasn't loaded yet. To
// handle that we need to make sure ExtensionSettingsStore is initialized
// before we clean it up.
await ExtensionSettingsStore.initialize();
ExtensionSettingsStore
.getAllForExtension(extensionId, "commands")
.forEach(key => {
ExtensionSettingsStore.removeSetting(extensionId, "commands", key);
});
}
async onManifestEntry(entryName) {
let {extension} = this;
this.id = makeWidgetId(extension.id);
this.windowOpenListener = null;
// Map[{String} commandName -> {Object} commandProperties]
this.commands = this.loadCommandsFromManifest(this.extension.manifest);
this.manifestCommands = this.loadCommandsFromManifest(extension.manifest);
this.commands = new Promise(async (resolve) => {
// Deep copy the manifest commands to commands so we can keep the original
// manifest commands and update commands as needed.
let commands = new Map();
this.manifestCommands.forEach((command, name) => {
commands.set(name, {...command});
});
// Update the manifest commands with the persisted updates from
// browser.commands.update().
let savedCommands = await this.loadCommandsFromStorage(extension.id);
savedCommands.forEach((update, name) => {
let command = commands.get(name);
if (command) {
// We will only update commands, not add them.
Object.assign(command, update);
}
});
resolve(commands);
});
// WeakMap[Window -> <xul:keyset>]
this.keysetsMap = new WeakMap();
this.register();
await this.register();
}
onShutdown(reason) {
this.unregister();
}
registerKeys(commands) {
for (let window of windowTracker.browserWindows()) {
this.registerKeysToDocument(window, commands);
}
}
/**
* Registers the commands to all open windows and to any which
* are later created.
*/
register() {
for (let window of windowTracker.browserWindows()) {
this.registerKeysToDocument(window);
}
async register() {
let commands = await this.commands;
this.registerKeys(commands);
this.windowOpenListener = (window) => {
if (!this.keysetsMap.has(window)) {
this.registerKeysToDocument(window);
this.registerKeysToDocument(window, commands);
}
};
@ -77,8 +127,7 @@ this.commands = class extends ExtensionAPI {
let os = PlatformInfo.os == "win" ? "windows" : PlatformInfo.os;
for (let [name, command] of Object.entries(manifest.commands)) {
let suggested_key = command.suggested_key || {};
let shortcut = suggested_key[os] || suggested_key.default;
shortcut = shortcut ? shortcut.replace(/\s+/g, "") : null;
let shortcut = normalizeShortcut(suggested_key[os] || suggested_key.default);
commands.set(name, {
description: command.description,
shortcut,
@ -87,21 +136,42 @@ this.commands = class extends ExtensionAPI {
return commands;
}
async loadCommandsFromStorage(extensionId) {
await ExtensionSettingsStore.initialize();
let names = ExtensionSettingsStore.getAllForExtension(extensionId, "commands");
return names.reduce((map, name) => {
let command = ExtensionSettingsStore.getSetting(
"commands", name, extensionId).value;
return map.set(name, command);
}, new Map());
}
/**
* Registers the commands to a document.
* @param {ChromeWindow} window The XUL window to insert the Keyset.
* @param {Map} commands The commands to be set.
*/
registerKeysToDocument(window) {
registerKeysToDocument(window, commands) {
let doc = window.document;
let keyset = doc.createElementNS(XUL_NS, "keyset");
keyset.id = `ext-keyset-id-${this.id}`;
this.commands.forEach((command, name) => {
if (this.keysetsMap.has(window)) {
this.keysetsMap.get(window).remove();
}
let sidebarKey;
commands.forEach((command, name) => {
if (command.shortcut) {
let keyElement = this.buildKey(doc, name, command.shortcut);
keyset.appendChild(keyElement);
if (name == EXECUTE_SIDEBAR_ACTION) {
sidebarKey = keyElement;
}
}
});
doc.documentElement.appendChild(keyset);
if (sidebarKey) {
window.SidebarUI.updateShortcut({key: sidebarKey});
}
this.keysetsMap.set(window, keyset);
}
@ -128,11 +198,11 @@ this.commands = class extends ExtensionAPI {
// therefore the listeners for these elements will be garbage collected.
keyElement.addEventListener("command", (event) => {
let action;
if (name == "_execute_page_action") {
if (name == EXECUTE_PAGE_ACTION) {
action = pageActionFor(this.extension);
} else if (name == "_execute_browser_action") {
} else if (name == EXECUTE_BROWSER_ACTION) {
action = browserActionFor(this.extension);
} else if (name == "_execute_sidebar_action") {
} else if (name == EXECUTE_SIDEBAR_ACTION) {
action = sidebarActionFor(this.extension);
} else {
this.extension.tabManager
@ -170,7 +240,7 @@ this.commands = class extends ExtensionAPI {
// The modifiers are the remaining elements.
keyElement.setAttribute("modifiers", this.getModifiersAttribute(parts));
if (name == "_execute_sidebar_action") {
if (name == EXECUTE_SIDEBAR_ACTION) {
let id = `ext-key-id-${this.id}-sidebar-action`;
keyElement.setAttribute("id", id);
}
@ -235,15 +305,64 @@ this.commands = class extends ExtensionAPI {
getAPI(context) {
return {
commands: {
getAll: () => {
let commands = this.commands;
return Promise.resolve(Array.from(commands, ([name, command]) => {
getAll: async () => {
let commands = await this.commands;
return Array.from(commands, ([name, command]) => {
return ({
name,
description: command.description,
shortcut: command.shortcut,
});
}));
});
},
update: async ({name, description, shortcut}) => {
let {extension} = this;
let commands = await this.commands;
let command = commands.get(name);
if (!command) {
throw new ExtensionError(`Unknown command "${name}"`);
}
// Only store the updates so manifest changes can take precedence
// later.
let previousUpdates = await ExtensionSettingsStore.getSetting(
"commands", name, extension.id);
let commandUpdates = (previousUpdates && previousUpdates.value) || {};
if (description && description != command.description) {
commandUpdates.description = description;
command.description = description;
}
if (shortcut && shortcut != command.shortcut) {
shortcut = normalizeShortcut(shortcut);
commandUpdates.shortcut = shortcut;
command.shortcut = shortcut;
}
await ExtensionSettingsStore.addSetting(
extension.id, "commands", name, commandUpdates);
this.registerKeys(commands);
},
reset: async (name) => {
let {extension, manifestCommands} = this;
let commands = await this.commands;
let command = commands.get(name);
if (!command) {
throw new ExtensionError(`Unknown command "${name}"`);
}
let storedCommand = ExtensionSettingsStore.getSetting(
"commands", name, extension.id);
if (storedCommand && storedCommand.value) {
commands.set(name, {...manifestCommands.get(name)});
ExtensionSettingsStore.removeSetting(extension.id, "commands", name);
this.registerKeys(commands);
}
},
onCommand: new EventManager(context, "commands.onCommand", fire => {
let listener = (eventName, commandName) => {

Просмотреть файл

@ -151,7 +151,7 @@ this.sidebarAction = class extends ExtensionAPI {
}
createMenuItem(window, details) {
let {document} = window;
let {document, SidebarUI} = window;
// Use of the broadcaster allows browser-sidebar.js to properly manage the
// checkmarks in the menus.
@ -190,6 +190,7 @@ this.sidebarAction = class extends ExtensionAPI {
document.getElementById("viewSidebarMenu").appendChild(menuitem);
let separator = document.getElementById("sidebar-extensions-separator");
separator.parentNode.insertBefore(toolbarbutton, separator);
SidebarUI.updateShortcut({button: toolbarbutton});
return menuitem;
}

Просмотреть файл

@ -124,6 +124,47 @@
}
],
"functions": [
{
"name": "update",
"type": "function",
"async": true,
"description": "Update the details of an already defined command.",
"parameters": [
{
"type": "object",
"name": "detail",
"description": "The new description for the command.",
"properties": {
"name": {
"type": "string",
"description": "The name of the command."
},
"description": {
"type": "string",
"optional": true,
"description": "The new description for the command."
},
"shortcut": {
"$ref": "manifest.KeyName",
"optional": true
}
}
}
]
},
{
"name": "reset",
"type": "function",
"async": true,
"description": "Reset a command's details to what is specified in the manifest.",
"parameters": [
{
"type": "string",
"name": "name",
"description": "The name of the command."
}
]
},
{
"name": "getAll",
"type": "function",

Просмотреть файл

@ -66,6 +66,7 @@ skip-if = (os == 'win' && !debug) # bug 1352668
[browser_ext_commands_execute_sidebar_action.js]
[browser_ext_commands_getAll.js]
[browser_ext_commands_onCommand.js]
[browser_ext_commands_update.js]
[browser_ext_contentscript_connect.js]
[browser_ext_contextMenus.js]
[browser_ext_contextMenus_checkboxes.js]

Просмотреть файл

@ -0,0 +1,307 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
"resource://gre/modules/ExtensionSettingsStore.jsm");
ChromeUtils.defineModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
function enableAddon(addon) {
return new Promise(resolve => {
AddonManager.addAddonListener({
onEnabled(enabledAddon) {
if (enabledAddon.id == addon.id) {
resolve();
AddonManager.removeAddonListener(this);
}
},
});
addon.userDisabled = false;
});
}
function disableAddon(addon) {
return new Promise(resolve => {
AddonManager.addAddonListener({
onDisabled(disabledAddon) {
if (disabledAddon.id == addon.id) {
resolve();
AddonManager.removeAddonListener(this);
}
},
});
addon.userDisabled = true;
});
}
add_task(async function test_update_defined_command() {
let extension;
let updatedExtension;
registerCleanupFunction(async () => {
await extension.unload();
// updatedExtension might not have started up if we didn't make it that far.
if (updatedExtension) {
await updatedExtension.unload();
}
// Check that ESS is cleaned up on uninstall.
let storedCommands = ExtensionSettingsStore.getAllForExtension(
extension.id, "commands");
is(storedCommands.length, 0, "There are no stored commands after unload");
});
extension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
manifest: {
version: "1.0",
applications: {gecko: {id: "commands@mochi.test"}},
commands: {
foo: {
suggested_key: {
default: "Ctrl+Shift+I",
},
description: "The foo command",
},
},
},
background() {
browser.test.onMessage.addListener(async (msg, data) => {
if (msg == "update") {
await browser.commands.update(data);
return browser.test.sendMessage("updateDone");
} else if (msg == "reset") {
await browser.commands.reset(data);
return browser.test.sendMessage("resetDone");
} else if (msg != "run") {
return;
}
// Test initial manifest command.
let commands = await browser.commands.getAll();
browser.test.assertEq(1, commands.length, "There is 1 command");
let command = commands[0];
browser.test.assertEq("foo", command.name, "The name is right");
browser.test.assertEq("The foo command", command.description, "The description is right");
browser.test.assertEq("Ctrl+Shift+I", command.shortcut, "The shortcut is right");
// Update the shortcut.
await browser.commands.update({name: "foo", shortcut: "Ctrl+Shift+L"});
// Test the updated shortcut.
commands = await browser.commands.getAll();
browser.test.assertEq(1, commands.length, "There is still 1 command");
command = commands[0];
browser.test.assertEq("foo", command.name, "The name is unchanged");
browser.test.assertEq("The foo command", command.description, "The description is unchanged");
browser.test.assertEq("Ctrl+Shift+L", command.shortcut, "The shortcut is updated");
// Update the description.
await browser.commands.update({name: "foo", description: "The only command"});
// Test the updated shortcut.
commands = await browser.commands.getAll();
browser.test.assertEq(1, commands.length, "There is still 1 command");
command = commands[0];
browser.test.assertEq("foo", command.name, "The name is unchanged");
browser.test.assertEq("The only command", command.description, "The description is updated");
browser.test.assertEq("Ctrl+Shift+L", command.shortcut, "The shortcut is unchanged");
// Update the description and shortcut.
await browser.commands.update({
name: "foo",
description: "The new command",
shortcut: " Alt+ Shift +P",
});
// Test the updated shortcut.
commands = await browser.commands.getAll();
browser.test.assertEq(1, commands.length, "There is still 1 command");
command = commands[0];
browser.test.assertEq("foo", command.name, "The name is unchanged");
browser.test.assertEq("The new command", command.description, "The description is updated");
browser.test.assertEq("Alt+Shift+P", command.shortcut, "The shortcut is updated");
// Test a bad shortcut update.
browser.test.assertThrows(
() => browser.commands.update({name: "foo", shortcut: "Ctl+Shift+L"}),
/Type error for parameter detail/,
"It rejects for a bad shortcut");
// Try to update a command that doesn't exist.
await browser.test.assertRejects(
browser.commands.update({name: "bar", shortcut: "Ctrl+Shift+L"}),
'Unknown command "bar"',
"It rejects for an unknown command");
browser.test.notifyPass("commands");
});
browser.test.sendMessage("ready");
},
});
await extension.startup();
function extensionKeyset(extensionId) {
return document.getElementById(makeWidgetId(`ext-keyset-id-${extensionId}`));
}
function checkKey(extensionId, shortcutKey, modifiers) {
let keyset = extensionKeyset(extensionId);
is(keyset.children.length, 1, "There is 1 key in the keyset");
let key = keyset.children[0];
is(key.getAttribute("key"), shortcutKey, "The key is correct");
is(key.getAttribute("modifiers"), modifiers, "The modifiers are correct");
}
// Check that the <key> is set for the original shortcut.
checkKey(extension.id, "I", "accel shift");
await extension.awaitMessage("ready");
extension.sendMessage("run");
await extension.awaitFinish("commands");
// Check that the <key> has been updated.
checkKey(extension.id, "P", "alt shift");
// Check that the updated command is stored in ExtensionSettingsStore.
let storedCommands = ExtensionSettingsStore.getAllForExtension(
extension.id, "commands");
is(storedCommands.length, 1, "There is only one stored command");
let command = ExtensionSettingsStore.getSetting("commands", "foo", extension.id).value;
is(command.description, "The new command", "The description is stored");
is(command.shortcut, "Alt+Shift+P", "The shortcut is stored");
// Check that the key is updated immediately.
extension.sendMessage("update", {name: "foo", shortcut: "Ctrl+Shift+M"});
await extension.awaitMessage("updateDone");
checkKey(extension.id, "M", "accel shift");
// Ensure all successive updates are stored.
// Force the command to only have a description saved.
await ExtensionSettingsStore.addSetting(
extension.id, "commands", "foo", {description: "description only"});
// This command now only has a description set in storage, also update the shortcut.
extension.sendMessage("update", {name: "foo", shortcut: "Alt+Shift+P"});
await extension.awaitMessage("updateDone");
let storedCommand = await ExtensionSettingsStore.getSetting(
"commands", "foo", extension.id);
is(storedCommand.value.shortcut, "Alt+Shift+P", "The shortcut is saved correctly");
is(storedCommand.value.description, "description only", "The description is saved correctly");
// Calling browser.commands.reset("foo") should reset to manifest version.
extension.sendMessage("reset", "foo");
await extension.awaitMessage("resetDone");
checkKey(extension.id, "I", "accel shift");
// Check that enable/disable removes the keyset and reloads the saved command.
let addon = await AddonManager.getAddonByID(extension.id);
await disableAddon(addon);
let keyset = extensionKeyset(extension.id);
is(keyset, null, "The extension keyset is removed when disabled");
// Add some commands to storage, only "foo" should get loaded.
await ExtensionSettingsStore.addSetting(
extension.id, "commands", "foo", {shortcut: "Alt+Shift+P"});
await ExtensionSettingsStore.addSetting(
extension.id, "commands", "unknown", {shortcut: "Ctrl+Shift+P"});
storedCommands = ExtensionSettingsStore.getAllForExtension(extension.id, "commands");
is(storedCommands.length, 2, "There are now 2 commands stored");
await enableAddon(addon);
// Wait for the keyset to appear (it's async on enable).
await TestUtils.waitForCondition(() => extensionKeyset(extension.id));
// The keyset is back with the value from ExtensionSettingsStore.
checkKey(extension.id, "P", "alt shift");
// Check that an update to a shortcut in the manifest is mapped correctly.
updatedExtension = ExtensionTestUtils.loadExtension({
useAddonManager: "permanent",
manifest: {
version: "1.0",
applications: {gecko: {id: "commands@mochi.test"}},
commands: {
foo: {
suggested_key: {
default: "Ctrl+Shift+L",
},
description: "The foo command",
},
},
},
});
await updatedExtension.startup();
await TestUtils.waitForCondition(() => extensionKeyset(extension.id));
// Shortcut is unchanged since it was previously updated.
checkKey(extension.id, "P", "alt shift");
});
add_task(async function updateSidebarCommand() {
let extension = ExtensionTestUtils.loadExtension({
useAddonManager: "temporary",
manifest: {
commands: {
_execute_sidebar_action: {
suggested_key: {
default: "Ctrl+Shift+E",
},
},
},
sidebar_action: {
default_panel: "sidebar.html",
},
},
background() {
browser.test.onMessage.addListener(async (msg, data) => {
if (msg == "updateShortcut") {
await browser.commands.update(data);
return browser.test.sendMessage("done");
}
throw new Error("Unknown message");
});
},
files: {
"sidebar.html": `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"/>
<script src="sidebar.js"></script>
</head>
<body>
A Test Sidebar
</body></html>
`,
"sidebar.js": function() {
window.onload = () => {
browser.test.sendMessage("sidebar");
};
},
},
});
await extension.startup();
await extension.awaitMessage("sidebar");
// Show and hide the switcher panel to generate the initial shortcuts.
let switcherShown = promisePopupShown(SidebarUI._switcherPanel);
SidebarUI.showSwitcherPanel();
await switcherShown;
let switcherHidden = promisePopupHidden(SidebarUI._switcherPanel);
SidebarUI.hideSwitcherPanel();
await switcherHidden;
let buttonId = `button_${makeWidgetId(extension.id)}-sidebar-action`;
let button = document.getElementById(buttonId);
let shortcut = button.getAttribute("shortcut");
ok(shortcut.endsWith("E"), "The button has the shortcut set");
extension.sendMessage(
"updateShortcut", {name: "_execute_sidebar_action", shortcut: "Ctrl+Shift+M"});
await extension.awaitMessage("done");
shortcut = button.getAttribute("shortcut");
ok(shortcut.endsWith("M"), "The button shortcut has been updated");
await extension.unload();
});

Просмотреть файл

@ -6,13 +6,6 @@ requestLongerTimeout(2);
let extData = {
manifest: {
commands: {
_execute_sidebar_action: {
suggested_key: {
default: "Ctrl+Shift+I",
},
},
},
sidebar_action: {
default_panel: "sidebar.html",
},
@ -57,6 +50,17 @@ let extData = {
},
};
function getExtData(manifestUpdates = {}) {
return {
...extData,
manifest: {
...extData.manifest,
...manifestUpdates,
},
};
}
async function sendMessage(ext, msg, data = undefined) {
ext.sendMessage({msg, data});
await ext.awaitMessage("done");
@ -64,7 +68,7 @@ async function sendMessage(ext, msg, data = undefined) {
add_task(async function sidebar_initial_install() {
ok(document.getElementById("sidebar-box").hidden, "sidebar box is not visible");
let extension = ExtensionTestUtils.loadExtension(extData);
let extension = ExtensionTestUtils.loadExtension(getExtData());
await extension.startup();
// Test sidebar is opened on install
await extension.awaitMessage("sidebar");
@ -77,14 +81,14 @@ add_task(async function sidebar_initial_install() {
add_task(async function sidebar_two_sidebar_addons() {
let extension2 = ExtensionTestUtils.loadExtension(extData);
let extension2 = ExtensionTestUtils.loadExtension(getExtData());
await extension2.startup();
// Test sidebar is opened on install
await extension2.awaitMessage("sidebar");
ok(!document.getElementById("sidebar-box").hidden, "sidebar box is visible");
// Test second sidebar install opens new sidebar
let extension3 = ExtensionTestUtils.loadExtension(extData);
let extension3 = ExtensionTestUtils.loadExtension(getExtData());
await extension3.startup();
// Test sidebar is opened on install
await extension3.awaitMessage("sidebar");
@ -98,7 +102,7 @@ add_task(async function sidebar_two_sidebar_addons() {
});
add_task(async function sidebar_empty_panel() {
let extension = ExtensionTestUtils.loadExtension(extData);
let extension = ExtensionTestUtils.loadExtension(getExtData());
await extension.startup();
// Test sidebar is opened on install
await extension.awaitMessage("sidebar");
@ -109,7 +113,7 @@ add_task(async function sidebar_empty_panel() {
add_task(async function sidebar_isOpen() {
info("Load extension1");
let extension1 = ExtensionTestUtils.loadExtension(extData);
let extension1 = ExtensionTestUtils.loadExtension(getExtData());
await extension1.startup();
info("Test extension1's sidebar is opened on install");
@ -117,14 +121,8 @@ add_task(async function sidebar_isOpen() {
await sendMessage(extension1, "isOpen", {result: true});
let sidebar1ID = SidebarUI.currentID;
// Test that the key is set for the extension.
let button = document.getElementById(`button_${makeWidgetId(extension1.id)}-sidebar-action`);
ok(button.hasAttribute("key"), "The menu item has a key specified");
let key = document.getElementById(button.getAttribute("key"));
ok(key, "The key attribute finds the related key element");
info("Load extension2");
let extension2 = ExtensionTestUtils.loadExtension(extData);
let extension2 = ExtensionTestUtils.loadExtension(getExtData());
await extension2.startup();
info("Test extension2's sidebar is opened on install");
@ -168,3 +166,61 @@ add_task(async function sidebar_isOpen() {
await extension1.unload();
await extension2.unload();
});
add_task(async function testShortcuts() {
function verifyShortcut(id, commandKey) {
// We're just testing the command key since the modifiers have different
// icons on different platforms.
let button = document.getElementById(`button_${makeWidgetId(id)}-sidebar-action`);
ok(button.hasAttribute("key"), "The menu item has a key specified");
let key = document.getElementById(button.getAttribute("key"));
ok(key, "The key attribute finds the related key element");
ok(button.getAttribute("shortcut").endsWith(commandKey),
"The shortcut has the right key");
}
let extension1 = ExtensionTestUtils.loadExtension(
getExtData({
commands: {
_execute_sidebar_action: {
suggested_key: {
default: "Ctrl+Shift+I",
},
},
},
}));
let extension2 = ExtensionTestUtils.loadExtension(
getExtData({
commands: {
_execute_sidebar_action: {
suggested_key: {
default: "Ctrl+Shift+E",
},
},
},
}));
await extension1.startup();
await extension1.awaitMessage("sidebar");
// Open and close the switcher panel to trigger shortcut content rendering.
let switcherPanelShown = promisePopupShown(SidebarUI._switcherPanel);
SidebarUI.showSwitcherPanel();
await switcherPanelShown;
let switcherPanelHidden = promisePopupHidden(SidebarUI._switcherPanel);
SidebarUI.hideSwitcherPanel();
await switcherPanelHidden;
// Test that the key is set for the extension after the shortcuts are rendered.
verifyShortcut(extension1.id, "I");
await extension2.startup();
await extension2.awaitMessage("sidebar");
// Once the switcher panel has been opened new shortcuts should be added
// automatically.
verifyShortcut(extension2.id, "E");
await extension1.unload();
await extension2.unload();
});

Просмотреть файл

@ -6,8 +6,8 @@
const {actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});
const {Dedupe} = ChromeUtils.import("resource://activity-stream/common/Dedupe.jsm", {});
const TOP_SITES_DEFAULT_ROWS = 2;
const TOP_SITES_MAX_SITES_PER_ROW = 6;
const TOP_SITES_DEFAULT_ROWS = 1;
const TOP_SITES_MAX_SITES_PER_ROW = 8;
const dedupe = new Dedupe(site => site && site.url);

Просмотреть файл

@ -210,19 +210,23 @@ main {
margin: auto;
padding-bottom: 48px;
width: 224px; }
@media (min-width: 416px) {
@media (min-width: 432px) {
main {
width: 352px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
main {
width: 480px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
main {
width: 736px; } }
main section {
margin-bottom: 40px;
position: relative; }
@media (min-width: 1072px) {
.wide-layout-enabled main {
width: 992px; } }
.section-top-bar {
height: 16px;
margin-bottom: 16px; }
@ -236,6 +240,9 @@ main {
fill: #737373;
vertical-align: middle; }
.base-content-fallback {
height: 100vh; }
.body-wrapper .section-title,
.body-wrapper .sections-list .section:last-of-type,
@ -248,12 +255,27 @@ main {
.body-wrapper.on .topic {
opacity: 1; }
.as-error-fallback {
align-items: center;
border-radius: 3px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
color: #4A4A4F;
display: flex;
flex-direction: column;
font-size: 12px;
justify-content: center;
justify-items: center;
line-height: 1.5; }
.as-error-fallback a {
color: #4A4A4F;
text-decoration: underline; }
.top-sites-list {
list-style: none;
margin: 0 -16px;
margin-bottom: -18px;
padding: 0; }
@media (max-width: 416px) {
@media (max-width: 432px) {
.top-sites-list :nth-child(2n+1) .context-menu {
margin-inline-end: auto;
margin-inline-start: auto;
@ -264,32 +286,32 @@ main {
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 416px) and (max-width: 544px) {
@media (min-width: 432px) and (max-width: 560px) {
.top-sites-list :nth-child(3n+2) .context-menu,
.top-sites-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.top-sites-list :nth-child(4n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 768px) {
@media (min-width: 560px) and (max-width: 784px) {
.top-sites-list :nth-child(4n+3) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.top-sites-list :nth-child(6n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1024px) {
@media (min-width: 816px) and (max-width: 1040px) {
.top-sites-list :nth-child(6n+5) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -412,6 +434,13 @@ main {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); }
.top-sites-list .top-site-outer.placeholder .screenshot {
display: none; }
.top-sites-list .top-site-outer.dragged .tile {
background: #EDEDF0;
box-shadow: none; }
.top-sites-list .top-site-outer.dragged .tile * {
display: none; }
.top-sites-list .top-site-outer.dragged .title {
visibility: hidden; }
.top-sites-list:not(.dnd-active) .top-site-outer:-moz-any(.active, :focus, :hover) .tile {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -419,6 +448,27 @@ main {
opacity: 1;
transform: scale(1); }
.wide-layout-disabled .top-sites-list .hide-for-narrow {
display: none; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .top-sites-list :nth-child(8n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) and (max-width: 1296px) {
.wide-layout-enabled .top-sites-list :nth-child(8n+7) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media not all and (min-width: 1072px) {
.wide-layout-enabled .top-sites-list .hide-for-narrow {
display: none; } }
.edit-topsites-wrapper .add-topsites-button {
border-right: 1px solid #D7D7DB;
line-height: 13px;
@ -525,19 +575,19 @@ main {
grid-gap: 32px;
grid-template-columns: repeat(auto-fit, 224px);
margin: 0; }
@media (max-width: 544px) {
@media (max-width: 560px) {
.sections-list .section-list .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.sections-list .section-list :nth-child(2n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -569,18 +619,29 @@ main {
margin-bottom: 0;
text-align: center; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) {
.wide-layout-enabled .sections-list .section-list {
grid-template-columns: repeat(auto-fit, 309px); } }
.topic {
color: #737373;
font-size: 12px;
line-height: 1.6;
margin-top: 12px; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic {
line-height: 16px; } }
.topic ul {
margin: 0;
padding: 0; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic ul {
display: inline;
padding-inline-start: 12px; } }
@ -595,7 +656,7 @@ main {
color: #008EA4; }
.topic .topic-read-more {
color: #008EA4; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic .topic-read-more {
float: right; }
.topic .topic-read-more:dir(rtl) {
@ -910,7 +971,7 @@ main {
height: 266px;
margin-inline-end: 32px;
position: relative;
width: 224px; }
width: 100%; }
.card-outer .context-menu-button {
background-clip: padding-box;
background-color: #FFF;
@ -947,7 +1008,7 @@ main {
height: 100%;
outline: none;
position: absolute;
width: 224px; }
width: 100%; }
.card-outer > a:-moz-any(.active, :focus) .card {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -1041,27 +1102,35 @@ main {
text-overflow: ellipsis;
white-space: nowrap; }
@media (min-width: 1072px) {
.wide-layout-enabled .card-outer {
height: 370px; }
.wide-layout-enabled .card-outer .card-preview-image-outer {
height: 155px; }
.wide-layout-enabled .card-outer .card-text {
max-height: 135px; } }
.manual-migration-container {
color: #4A4A4F;
font-size: 13px;
line-height: 15px;
margin-bottom: 40px;
text-align: center; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container {
display: flex;
justify-content: space-between;
text-align: left; } }
.manual-migration-container p {
margin: 0; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container p {
align-self: center;
display: flex;
justify-content: space-between; } }
.manual-migration-container .icon {
display: none; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container .icon {
align-self: center;
display: block;
@ -1072,7 +1141,7 @@ main {
border: 0;
display: block;
flex-wrap: nowrap; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-actions {
display: flex;
justify-content: space-between;
@ -1206,13 +1275,13 @@ main {
position: relative; }
.collapsible-section .section-disclaimer .section-disclaimer-text {
display: inline-block; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 224px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 340px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 610px; } }
.collapsible-section .section-disclaimer a {
@ -1230,10 +1299,13 @@ main {
.collapsible-section .section-disclaimer button:hover:not(.dismiss) {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer button {
position: absolute; } }
.collapsible-section .section-body-fallback {
height: 266px; }
.collapsible-section .section-body {
margin: 0 -7px;
padding: 0 7px; }
@ -1257,3 +1329,5 @@ main {
.collapsible-section:not(.collapsed):hover .info-option-icon {
opacity: 1; }
/*# sourceMappingURL=activity-stream-linux.css.map */

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -210,19 +210,23 @@ main {
margin: auto;
padding-bottom: 48px;
width: 224px; }
@media (min-width: 416px) {
@media (min-width: 432px) {
main {
width: 352px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
main {
width: 480px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
main {
width: 736px; } }
main section {
margin-bottom: 40px;
position: relative; }
@media (min-width: 1072px) {
.wide-layout-enabled main {
width: 992px; } }
.section-top-bar {
height: 16px;
margin-bottom: 16px; }
@ -236,6 +240,9 @@ main {
fill: #737373;
vertical-align: middle; }
.base-content-fallback {
height: 100vh; }
.body-wrapper .section-title,
.body-wrapper .sections-list .section:last-of-type,
@ -248,12 +255,27 @@ main {
.body-wrapper.on .topic {
opacity: 1; }
.as-error-fallback {
align-items: center;
border-radius: 3px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
color: #4A4A4F;
display: flex;
flex-direction: column;
font-size: 12px;
justify-content: center;
justify-items: center;
line-height: 1.5; }
.as-error-fallback a {
color: #4A4A4F;
text-decoration: underline; }
.top-sites-list {
list-style: none;
margin: 0 -16px;
margin-bottom: -18px;
padding: 0; }
@media (max-width: 416px) {
@media (max-width: 432px) {
.top-sites-list :nth-child(2n+1) .context-menu {
margin-inline-end: auto;
margin-inline-start: auto;
@ -264,32 +286,32 @@ main {
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 416px) and (max-width: 544px) {
@media (min-width: 432px) and (max-width: 560px) {
.top-sites-list :nth-child(3n+2) .context-menu,
.top-sites-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.top-sites-list :nth-child(4n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 768px) {
@media (min-width: 560px) and (max-width: 784px) {
.top-sites-list :nth-child(4n+3) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.top-sites-list :nth-child(6n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1024px) {
@media (min-width: 816px) and (max-width: 1040px) {
.top-sites-list :nth-child(6n+5) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -412,6 +434,13 @@ main {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); }
.top-sites-list .top-site-outer.placeholder .screenshot {
display: none; }
.top-sites-list .top-site-outer.dragged .tile {
background: #EDEDF0;
box-shadow: none; }
.top-sites-list .top-site-outer.dragged .tile * {
display: none; }
.top-sites-list .top-site-outer.dragged .title {
visibility: hidden; }
.top-sites-list:not(.dnd-active) .top-site-outer:-moz-any(.active, :focus, :hover) .tile {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -419,6 +448,27 @@ main {
opacity: 1;
transform: scale(1); }
.wide-layout-disabled .top-sites-list .hide-for-narrow {
display: none; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .top-sites-list :nth-child(8n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) and (max-width: 1296px) {
.wide-layout-enabled .top-sites-list :nth-child(8n+7) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media not all and (min-width: 1072px) {
.wide-layout-enabled .top-sites-list .hide-for-narrow {
display: none; } }
.edit-topsites-wrapper .add-topsites-button {
border-right: 1px solid #D7D7DB;
line-height: 13px;
@ -525,19 +575,19 @@ main {
grid-gap: 32px;
grid-template-columns: repeat(auto-fit, 224px);
margin: 0; }
@media (max-width: 544px) {
@media (max-width: 560px) {
.sections-list .section-list .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.sections-list .section-list :nth-child(2n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -569,18 +619,29 @@ main {
margin-bottom: 0;
text-align: center; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) {
.wide-layout-enabled .sections-list .section-list {
grid-template-columns: repeat(auto-fit, 309px); } }
.topic {
color: #737373;
font-size: 12px;
line-height: 1.6;
margin-top: 12px; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic {
line-height: 16px; } }
.topic ul {
margin: 0;
padding: 0; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic ul {
display: inline;
padding-inline-start: 12px; } }
@ -595,7 +656,7 @@ main {
color: #008EA4; }
.topic .topic-read-more {
color: #008EA4; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic .topic-read-more {
float: right; }
.topic .topic-read-more:dir(rtl) {
@ -910,7 +971,7 @@ main {
height: 266px;
margin-inline-end: 32px;
position: relative;
width: 224px; }
width: 100%; }
.card-outer .context-menu-button {
background-clip: padding-box;
background-color: #FFF;
@ -947,7 +1008,7 @@ main {
height: 100%;
outline: none;
position: absolute;
width: 224px; }
width: 100%; }
.card-outer > a:-moz-any(.active, :focus) .card {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -1041,27 +1102,35 @@ main {
text-overflow: ellipsis;
white-space: nowrap; }
@media (min-width: 1072px) {
.wide-layout-enabled .card-outer {
height: 370px; }
.wide-layout-enabled .card-outer .card-preview-image-outer {
height: 155px; }
.wide-layout-enabled .card-outer .card-text {
max-height: 135px; } }
.manual-migration-container {
color: #4A4A4F;
font-size: 13px;
line-height: 15px;
margin-bottom: 40px;
text-align: center; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container {
display: flex;
justify-content: space-between;
text-align: left; } }
.manual-migration-container p {
margin: 0; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container p {
align-self: center;
display: flex;
justify-content: space-between; } }
.manual-migration-container .icon {
display: none; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container .icon {
align-self: center;
display: block;
@ -1072,7 +1141,7 @@ main {
border: 0;
display: block;
flex-wrap: nowrap; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-actions {
display: flex;
justify-content: space-between;
@ -1206,13 +1275,13 @@ main {
position: relative; }
.collapsible-section .section-disclaimer .section-disclaimer-text {
display: inline-block; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 224px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 340px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 610px; } }
.collapsible-section .section-disclaimer a {
@ -1230,10 +1299,13 @@ main {
.collapsible-section .section-disclaimer button:hover:not(.dismiss) {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer button {
position: absolute; } }
.collapsible-section .section-body-fallback {
height: 266px; }
.collapsible-section .section-body {
margin: 0 -7px;
padding: 0 7px; }
@ -1257,3 +1329,5 @@ main {
.collapsible-section:not(.collapsed):hover .info-option-icon {
opacity: 1; }
/*# sourceMappingURL=activity-stream-mac.css.map */

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -210,19 +210,23 @@ main {
margin: auto;
padding-bottom: 48px;
width: 224px; }
@media (min-width: 416px) {
@media (min-width: 432px) {
main {
width: 352px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
main {
width: 480px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
main {
width: 736px; } }
main section {
margin-bottom: 40px;
position: relative; }
@media (min-width: 1072px) {
.wide-layout-enabled main {
width: 992px; } }
.section-top-bar {
height: 16px;
margin-bottom: 16px; }
@ -236,6 +240,9 @@ main {
fill: #737373;
vertical-align: middle; }
.base-content-fallback {
height: 100vh; }
.body-wrapper .section-title,
.body-wrapper .sections-list .section:last-of-type,
@ -248,12 +255,27 @@ main {
.body-wrapper.on .topic {
opacity: 1; }
.as-error-fallback {
align-items: center;
border-radius: 3px;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
color: #4A4A4F;
display: flex;
flex-direction: column;
font-size: 12px;
justify-content: center;
justify-items: center;
line-height: 1.5; }
.as-error-fallback a {
color: #4A4A4F;
text-decoration: underline; }
.top-sites-list {
list-style: none;
margin: 0 -16px;
margin-bottom: -18px;
padding: 0; }
@media (max-width: 416px) {
@media (max-width: 432px) {
.top-sites-list :nth-child(2n+1) .context-menu {
margin-inline-end: auto;
margin-inline-start: auto;
@ -264,32 +286,32 @@ main {
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 416px) and (max-width: 544px) {
@media (min-width: 432px) and (max-width: 560px) {
.top-sites-list :nth-child(3n+2) .context-menu,
.top-sites-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.top-sites-list :nth-child(4n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 768px) {
@media (min-width: 560px) and (max-width: 784px) {
.top-sites-list :nth-child(4n+3) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.top-sites-list :nth-child(6n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1024px) {
@media (min-width: 816px) and (max-width: 1040px) {
.top-sites-list :nth-child(6n+5) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -412,6 +434,13 @@ main {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); }
.top-sites-list .top-site-outer.placeholder .screenshot {
display: none; }
.top-sites-list .top-site-outer.dragged .tile {
background: #EDEDF0;
box-shadow: none; }
.top-sites-list .top-site-outer.dragged .tile * {
display: none; }
.top-sites-list .top-site-outer.dragged .title {
visibility: hidden; }
.top-sites-list:not(.dnd-active) .top-site-outer:-moz-any(.active, :focus, :hover) .tile {
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -419,6 +448,27 @@ main {
opacity: 1;
transform: scale(1); }
.wide-layout-disabled .top-sites-list .hide-for-narrow {
display: none; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .top-sites-list :nth-child(8n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) and (max-width: 1296px) {
.wide-layout-enabled .top-sites-list :nth-child(8n+7) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media not all and (min-width: 1072px) {
.wide-layout-enabled .top-sites-list .hide-for-narrow {
display: none; } }
.edit-topsites-wrapper .add-topsites-button {
border-right: 1px solid #D7D7DB;
line-height: 13px;
@ -525,19 +575,19 @@ main {
grid-gap: 32px;
grid-template-columns: repeat(auto-fit, 224px);
margin: 0; }
@media (max-width: 544px) {
@media (max-width: 560px) {
.sections-list .section-list .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 544px) and (max-width: 800px) {
@media (min-width: 560px) and (max-width: 816px) {
.sections-list .section-list :nth-child(2n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 800px) and (max-width: 1248px) {
@media (min-width: 816px) and (max-width: 1264px) {
.sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
@ -569,18 +619,29 @@ main {
margin-bottom: 0;
text-align: center; }
@media (min-width: 1072px) and (max-width: 1520px) {
.wide-layout-enabled .sections-list .section-list :nth-child(3n) .context-menu {
margin-inline-end: 5px;
margin-inline-start: auto;
offset-inline-end: 0;
offset-inline-start: auto; } }
@media (min-width: 1072px) {
.wide-layout-enabled .sections-list .section-list {
grid-template-columns: repeat(auto-fit, 309px); } }
.topic {
color: #737373;
font-size: 12px;
line-height: 1.6;
margin-top: 12px; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic {
line-height: 16px; } }
.topic ul {
margin: 0;
padding: 0; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic ul {
display: inline;
padding-inline-start: 12px; } }
@ -595,7 +656,7 @@ main {
color: #008EA4; }
.topic .topic-read-more {
color: #008EA4; }
@media (min-width: 800px) {
@media (min-width: 816px) {
.topic .topic-read-more {
float: right; }
.topic .topic-read-more:dir(rtl) {
@ -910,7 +971,7 @@ main {
height: 266px;
margin-inline-end: 32px;
position: relative;
width: 224px; }
width: 100%; }
.card-outer .context-menu-button {
background-clip: padding-box;
background-color: #FFF;
@ -947,7 +1008,7 @@ main {
height: 100%;
outline: none;
position: absolute;
width: 224px; }
width: 100%; }
.card-outer > a:-moz-any(.active, :focus) .card {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@ -1041,27 +1102,35 @@ main {
text-overflow: ellipsis;
white-space: nowrap; }
@media (min-width: 1072px) {
.wide-layout-enabled .card-outer {
height: 370px; }
.wide-layout-enabled .card-outer .card-preview-image-outer {
height: 155px; }
.wide-layout-enabled .card-outer .card-text {
max-height: 135px; } }
.manual-migration-container {
color: #4A4A4F;
font-size: 13px;
line-height: 15px;
margin-bottom: 40px;
text-align: center; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container {
display: flex;
justify-content: space-between;
text-align: left; } }
.manual-migration-container p {
margin: 0; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container p {
align-self: center;
display: flex;
justify-content: space-between; } }
.manual-migration-container .icon {
display: none; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-container .icon {
align-self: center;
display: block;
@ -1072,7 +1141,7 @@ main {
border: 0;
display: block;
flex-wrap: nowrap; }
@media (min-width: 544px) {
@media (min-width: 560px) {
.manual-migration-actions {
display: flex;
justify-content: space-between;
@ -1206,13 +1275,13 @@ main {
position: relative; }
.collapsible-section .section-disclaimer .section-disclaimer-text {
display: inline-block; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 224px; } }
@media (min-width: 544px) {
@media (min-width: 560px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 340px; } }
@media (min-width: 800px) {
@media (min-width: 816px) {
.collapsible-section .section-disclaimer .section-disclaimer-text {
width: 610px; } }
.collapsible-section .section-disclaimer a {
@ -1230,10 +1299,13 @@ main {
.collapsible-section .section-disclaimer button:hover:not(.dismiss) {
box-shadow: 0 0 0 5px #D7D7DB;
transition: box-shadow 150ms; }
@media (min-width: 416px) {
@media (min-width: 432px) {
.collapsible-section .section-disclaimer button {
position: absolute; } }
.collapsible-section .section-body-fallback {
height: 266px; }
.collapsible-section .section-body {
margin: 0 -7px;
padding: 0 7px; }
@ -1257,3 +1329,5 @@ main {
.collapsible-section:not(.collapsed):hover .info-option-icon {
opacity: 1; }
/*# sourceMappingURL=activity-stream-windows.css.map */

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -8,7 +8,7 @@
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<em:version>2018.02.05.1095-9be4c3c6</em:version>
<em:version>2018.02.09.1159-a77359dc</em:version>
<em:name>Activity Stream</em:name>
<em:description>A rich visual history feed and a reimagined home page make it easier than ever to find exactly what you're looking for in Firefox.</em:description>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

Просмотреть файл

@ -17,13 +17,27 @@
content/vendor/react-intl.js (./vendor/react-intl.js)
content/vendor/redux.js (./vendor/redux.js)
content/vendor/react-redux.js (./vendor/react-redux.js)
content/data/ (./data/*)
content/data/content/assets/ (./data/content/assets/*)
content/data/content/tippytop/ (./data/content/tippytop/*)
content/data/content/activity-stream.bundle.js (./data/content/activity-stream.bundle.js)
#ifndef RELEASE_OR_BETA
content/data/content/activity-stream.bundle.js.map (./data/content/activity-stream.bundle.js.map)
#endif
#ifdef XP_MACOSX
content/css/activity-stream.css (./css/activity-stream-mac.css)
#ifndef RELEASE_OR_BETA
content/css/activity-stream-mac.css.map (./css/activity-stream-mac.css.map)
#endif
#elifdef XP_WIN
content/css/activity-stream.css (./css/activity-stream-windows.css)
#ifndef RELEASE_OR_BETA
content/css/activity-stream-windows.css.map (./css/activity-stream-windows.css.map)
#endif
#else
content/css/activity-stream.css (./css/activity-stream-linux.css)
#ifndef RELEASE_OR_BETA
content/css/activity-stream-linux.css.map (./css/activity-stream-linux.css.map)
#endif
#endif
content/prerendered/static/activity-stream-initial-state.js (./prerendered/static/activity-stream-initial-state.js)
#ifndef RELEASE_OR_BETA

Просмотреть файл

@ -107,7 +107,7 @@ const PREFS_CONFIG = new Map([
}],
["topSitesRows", {
title: "Number of rows of Top Sites to display",
value: 2
value: 1
}],
["telemetry", {
title: "Enable system error and usage data collection",
@ -133,6 +133,10 @@ const PREFS_CONFIG = new Map([
["tippyTop.service.endpoint", {
title: "Tippy Top service manifest url",
value: "https://activity-stream-icons.services.mozilla.com/v1/icons.json.br"
}],
["enableWideLayout", {
title: "Enable the wider layout (8 topsites per row and larger pocket+highlight cards)",
value: true
}]
]);

Просмотреть файл

@ -15,6 +15,8 @@ ChromeUtils.defineModuleGetter(this, "perfService",
"resource://activity-stream/common/PerfService.jsm");
ChromeUtils.defineModuleGetter(this, "PingCentre",
"resource:///modules/PingCentre.jsm");
ChromeUtils.defineModuleGetter(this, "UTEventReporting",
"resource://activity-stream/lib/UTEventReporting.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
"@mozilla.org/uuid-generator;1",
@ -117,6 +119,14 @@ this.TelemetryFeed = class TelemetryFeed {
return this.pingCentre;
}
/**
* Lazily initialize UTEventReporting to send pings
*/
get utEvents() {
Object.defineProperty(this, "utEvents", {value: new UTEventReporting()});
return this.utEvents;
}
/**
* Get encoded user preferences, multiple prefs will be combined via bitwise OR operator
*/
@ -217,7 +227,9 @@ this.TelemetryFeed = class TelemetryFeed {
session.session_duration = Math.round(perfService.absNow() - session.perf.visibility_event_rcvd_ts);
}
this.sendEvent(this.createSessionEndEvent(session));
let sessionEndEvent = this.createSessionEndEvent(session);
this.sendEvent(sessionEndEvent);
this.utEvents.sendSessionEndEvent(sessionEndEvent);
this.sessions.delete(portID);
}
@ -344,7 +356,9 @@ this.TelemetryFeed = class TelemetryFeed {
}
handleUserEvent(action) {
this.sendEvent(this.createUserEvent(action));
let userEvent = this.createUserEvent(action);
this.sendEvent(userEvent);
this.utEvents.sendUserEvent(userEvent);
}
handleUndesiredEvent(action) {
@ -430,6 +444,9 @@ this.TelemetryFeed = class TelemetryFeed {
if (Object.prototype.hasOwnProperty.call(this, "pingCentre")) {
this.pingCentre.uninit();
}
if (Object.prototype.hasOwnProperty.call(this, "utEvents")) {
this.utEvents.uninit();
}
try {
this._prefs.ignore(TELEMETRY_PREF, this._onTelemetryPrefChange);

Просмотреть файл

@ -7,7 +7,7 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {actionCreators: ac, actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});
const {TippyTopProvider} = ChromeUtils.import("resource://activity-stream/lib/TippyTopProvider.jsm", {});
const {insertPinned, TOP_SITES_DEFAULT_ROWS, TOP_SITES_MAX_SITES_PER_ROW} = ChromeUtils.import("resource://activity-stream/common/Reducers.jsm", {});
const {insertPinned, TOP_SITES_MAX_SITES_PER_ROW} = ChromeUtils.import("resource://activity-stream/common/Reducers.jsm", {});
const {Dedupe} = ChromeUtils.import("resource://activity-stream/common/Dedupe.jsm", {});
const {shortURL} = ChromeUtils.import("resource://activity-stream/lib/ShortURL.jsm", {});
@ -73,8 +73,8 @@ this.TopSitesFeed = class TopSitesFeed {
}
async getLinksWithDefaults(action) {
// Get at least TOP_SITES_DEFAULT_ROWS (2) amount so toggling between 1 and 2 rows has sites
const numItems = Math.max(this.store.getState().Prefs.values.topSitesRows, TOP_SITES_DEFAULT_ROWS) * TOP_SITES_MAX_SITES_PER_ROW;
// Get at least 2 rows so toggling between 1 and 2 rows has sites
const numItems = Math.max(this.store.getState().Prefs.values.topSitesRows, 2) * TOP_SITES_MAX_SITES_PER_ROW;
const frecent = (await this.frecentCache.request({
numItems,
topsiteFrecency: FRECENCY_THRESHOLD

Просмотреть файл

@ -0,0 +1,59 @@
/* 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/. */
/* globals Services */
"use strict";
ChromeUtils.import("resource://gre/modules/Services.jsm");
/**
* Note: the schema can be found in
* https://searchfox.org/mozilla-central/source/toolkit/components/telemetry/Events.yaml
*/
const EXTRAS_FIELD_NAMES = ["addon_version", "session_id", "page", "user_prefs", "action_position"];
this.UTEventReporting = class UTEventReporting {
constructor() {
Services.telemetry.setEventRecordingEnabled("activity_stream", true);
}
_createExtras(data) {
// Make a copy of the given data and delete/modify it as needed.
let utExtras = Object.assign({}, data);
for (let field of Object.keys(utExtras)) {
if (EXTRAS_FIELD_NAMES.includes(field)) {
utExtras[field] = String(utExtras[field]);
continue;
}
delete utExtras[field];
}
return utExtras;
}
sendUserEvent(data) {
let mainFields = ["event", "source"];
let eventFields = mainFields.map(field => String(data[field]) || null);
Services.telemetry.recordEvent(
"activity_stream",
"event",
...eventFields,
this._createExtras(data));
}
sendSessionEndEvent(data) {
Services.telemetry.recordEvent(
"activity_stream",
"end",
"session",
String(data.session_duration),
this._createExtras(data));
}
uninit() {
Services.telemetry.setEventRecordingEnabled("activity_stream", false);
}
};
this.EXPORTED_SYMBOLS = ["UTEventReporting"];

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ityeko weng. Rot doki lacen pi lok madito mapol ki bot {provider}. Pe itwero kuro? Yer lok macuke lamal me nongo lok mabeco mapol ki i but kakube.",
"manual_migration_explanation2": "Tem Firefox ki alamabuk, gin mukato ki mung me donyo ki ii layeny mukene.",
"manual_migration_cancel_button": "Pe Apwoyo",
"manual_migration_import_button": "Kel kombedi"
"manual_migration_import_button": "Kel kombedi",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -10,7 +10,7 @@ window.gActivityStreamStrings = {
"header_recommended_by": "ينصح به {provider}",
"header_bookmarks_placeholder": "لا علامات لديك بعد.",
"header_stories_from": "من",
"context_menu_button_sr": "Open context menu for {title}",
"context_menu_button_sr": "افتح قائمة {title} السياقية",
"type_label_visited": "مُزارة",
"type_label_bookmarked": "معلّمة",
"type_label_synced": "مُزامنة من جهاز آخر",
@ -79,7 +79,7 @@ window.gActivityStreamStrings = {
"edit_topsites_edit_button": "حرّر هذا الموقع",
"edit_topsites_dismiss_button": "احذف هذا الموقع",
"edit_topsites_add_button": "أضِفْ",
"edit_topsites_add_button_tooltip": "Add Top Site",
"edit_topsites_add_button_tooltip": "أضف موقعًا شائعًا",
"topsites_form_add_header": "موقع شائع جديد",
"topsites_form_edit_header": "حرّر الموقع الشائع",
"topsites_form_title_placeholder": "أدخل عنوانًا",
@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "لا جديد. تحقق لاحقًا للحصول على مزيد من أهم الأخبار من {provider}. لا يمكنك الانتظار؟ اختر موضوعًا شائعًا للعثور على المزيد من القصص الرائعة من جميع أنحاء الوِب.",
"manual_migration_explanation2": "جرب فَيَرفُكس مع العلامات، و التأريخ، و كلمات السر من متصفح آخر.",
"manual_migration_cancel_button": "لا شكرًا",
"manual_migration_import_button": "استورد الآن"
"manual_migration_import_button": "استورد الآن",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Youve caught up. Check back later for more top stories from {provider}. Cant wait? Select a popular topic to find more great stories from around the web.",
"manual_migration_explanation2": "Prueba Firefox colos marcadores, hestorial y contraseñes d'otru restolador.",
"manual_migration_cancel_button": "Non, gracies",
"manual_migration_import_button": "Importar agora"
"manual_migration_import_button": "Importar agora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Hamısını oxudunuz. Yeni {provider} məqalələri üçün daha sonra təkrar yoxlayın. Gözləyə bilmirsiz? Məşhur mövzu seçərək internetdən daha çox gözəl məqalələr tapın.",
"manual_migration_explanation2": "Firefox səyyahını digər səyyahlardan olan əlfəcin, tarixçə və parollar ilə yoxlayın.",
"manual_migration_cancel_button": "Xeyr, Təşəkkürlər",
"manual_migration_import_button": "İndi idxal et"
"manual_migration_import_button": "İndi idxal et",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Гатова. Праверце пазней, каб убачыць больш матэрыялаў ад {provider}. Не жадаеце чакаць? Выберыце папулярную тэму, каб знайсці больш цікавых матэрыялаў з усяго Інтэрнэту.",
"manual_migration_explanation2": "Паспрабуйце Firefox з закладкамі, гісторыяй і паролямі з іншага браўзера.",
"manual_migration_cancel_button": "Не, дзякуй",
"manual_migration_import_button": "Імпартаваць зараз"
"manual_migration_import_button": "Імпартаваць зараз",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Разгледахте всичко. Проверете по-късно за повече истории от {provider}. Нямате търпение? Изберете популярна тема, за да откриете повече истории из цялата Мрежа.",
"manual_migration_explanation2": "Опитайте Firefox с отметките, историята и паролите от друг четец.",
"manual_migration_cancel_button": "Не, благодаря",
"manual_migration_import_button": "Внасяне"
"manual_migration_import_button": "Внасяне",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "কিছু একটা ঠিক নেই। {provider} এর শীর্ষ গল্পগুলো পেতে কিছুক্ষণ পর আবার দেখুন। অপেক্ষা করতে চান না? বিশ্বের সেরা গল্পগুলো পেতে কোন জনপ্রিয় বিষয় নির্বাচন করুন।",
"manual_migration_explanation2": "অন্য ব্রাউজার থেকে আনা বুকমার্ক, ইতিহাস এবং পাসওয়ার্ডগুলির সাথে ফায়ারফক্স ব্যবহার করে দেখুন।",
"manual_migration_cancel_button": "প্রয়োজন নেই",
"manual_migration_import_button": "এখনই ইম্পোর্ট করুন"
"manual_migration_import_button": "এখনই ইম্পোর্ট করুন",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "কিছু একটা ঠিক নেই। {provider} এর শীর্ষ গল্পগুলো পেতে কিছুক্ষণ পর আবার দেখুন। অপেক্ষা করতে চান না? বিশ্বের সেরা গল্পগুলো পেতে কোন জনপ্রিয় বিষয় নির্বাচন করুন।",
"manual_migration_explanation2": "অন্য ব্রাউজার থেকে আনা বুকমার্ক, ইতিহাস এবং পাসওয়ার্ডগুলির সাথে ফায়ারফক্স ব্যবহার করে দেখুন।",
"manual_migration_cancel_button": "প্রয়োজন নেই",
"manual_migration_import_button": "এখনই ইম্পোর্ট করুন"
"manual_migration_import_button": "এখনই ইম্পোর্ট করুন",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Aet oc'h betek penn. Distroit diwezhatoc'h evit muioch a istorioù digant {provider}. Noc'h ket evit gortoz? Dibabit un danvez brudet evit klask muioch a bennadoù dedennus eus pep lech er web.",
"manual_migration_explanation2": "Amprouit Firefox gant sinedoù, roll istor ha gerioù-tremen ur merdeer all.",
"manual_migration_cancel_button": "N'am bo ket",
"manual_migration_import_button": "Emporzhiañ bremañ"
"manual_migration_import_button": "Emporzhiañ bremañ",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Provjerite kasnije za više najpopularnijih priča od {provider}. Ne možete čekati? Odaberite popularne teme kako biste pronašli više kvalitetnih priča s cijelog weba.",
"manual_migration_explanation2": "Probajte Firefox s zabilješkama, historijom i lozinkama iz drugog pretraživača.",
"manual_migration_cancel_button": "Ne, hvala",
"manual_migration_import_button": "Uvezi sada"
"manual_migration_import_button": "Uvezi sada",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ja esteu al dia. Torneu més tard per veure més articles populars de {provider}. No podeu esperar? Trieu un tema popular per descobrir els articles més interessants de tot el web.",
"manual_migration_explanation2": "Proveu el Firefox amb les adreces d'interès, l'historial i les contrasenyes d'un altre navegador.",
"manual_migration_cancel_button": "No, gràcies",
"manual_migration_import_button": "Importa-ho ara"
"manual_migration_import_button": "Importa-ho ara",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Xaq'i'. Katzolin chik pe richin ye'ak'ül ri utziläj taq rub'anob'al {provider}. ¿La man noyob'en ta? Tacha' jun ütz na'oj richin nawïl ch'aqa' chik taq b'anob'äl e k'o chi rij ri ajk'amaya'l.",
"manual_migration_explanation2": "Tatojtob'ej Firefox kik'in ri taq ruyaketal, runatab'äl chuqa' taq ewan rutzij jun chik okik'amaya'l.",
"manual_migration_cancel_button": "Mani matyox",
"manual_migration_import_button": "Tijik' pe"
"manual_migration_import_button": "Tijik' pe",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -32,9 +32,9 @@ window.gActivityStreamStrings = {
"confirm_history_delete_notice_p2": "Tuto akci nelze vzít zpět.",
"menu_action_save_to_pocket": "Uložit do služby Pocket",
"search_for_something_with": "Vyhledat {search_term} s:",
"search_button": "Hledat",
"search_button": "Vyhledat",
"search_header": "Vyhledat pomocí {search_engine_name}",
"search_web_placeholder": "Hledat na webu",
"search_web_placeholder": "Vyhledat na webu",
"search_settings": "Změnit nastavení vyhledávání",
"section_info_option": "Informace",
"section_info_send_feedback": "Zpětná vazba",
@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Už jste všechno přečetli. Další příběhy ze služby {provider} tu najdete zase později. Ale pokud se nemůžete dočkat, vyberte své oblíbené téma a podívejte se na další velké příběhy z celého webu.",
"manual_migration_explanation2": "Vyzkoušejte Firefox se záložkami, historií a hesly z jiného vašeho prohlížeče.",
"manual_migration_cancel_button": "Ne, děkuji",
"manual_migration_import_button": "Importovat nyní"
"manual_migration_import_button": "Importovat nyní",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Rydych wedi dal i fynDewch nôl rhywbryd eto am fwy o'r straeon pwysicaf gan {provider}. Methu aros? Dewiswch bwnc poblogaidd i ganfod straeon da o ar draws y we. ",
"manual_migration_explanation2": "Profwch Firefox gyda nodau tudalen, hanes a chyfrineiriau o borwr arall.",
"manual_migration_cancel_button": "Dim Diolch",
"manual_migration_import_button": "Mewnforio Nawr"
"manual_migration_import_button": "Mewnforio Nawr",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Der er ikke flere nye historier. Kom tilbage senere for at se flere tophistorier fra {provider}. Kan du ikke vente? Vælg et populært emne og find flere spændende historier fra hele verden.",
"manual_migration_explanation2": "Prøv Firefox med bogmærkerne, historikken og adgangskoderne fra en anden browser.",
"manual_migration_cancel_button": "Nej tak",
"manual_migration_import_button": "Importer nu"
"manual_migration_import_button": "Importer nu",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Jetzt kennen Sie die Neuigkeiten. Schauen Sie später wieder vorbei, um neue Informationen von {provider} zu erhalten. Können Sie nicht warten? Wählen Sie ein beliebtes Thema und lesen Sie weitere interessante Geschichten aus dem Internet.",
"manual_migration_explanation2": "Probieren Sie Firefox aus und importieren Sie die Lesezeichen, Chronik und Passwörter eines anderen Browsers.",
"manual_migration_cancel_button": "Nein, danke",
"manual_migration_import_button": "Jetzt importieren"
"manual_migration_import_button": "Jetzt importieren",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "To jo nachylu wšykno. Wrośćo se pózdźej wjelicnych tšojeńkow dla wót {provider}. Njamóžośo cakaś? Wubjeŕśo woblubowanu temu, aby dalšne wjelicne tšojeńka we webje namakał.",
"manual_migration_explanation2": "Wopytajśo Firefox z cytanskimi znamjenjami, historiju a gronidłami z drugego wobglědowaka.",
"manual_migration_cancel_button": "Ně, źěkujom se",
"manual_migration_import_button": "Něnto importěrowaś"
"manual_migration_import_button": "Něnto importěrowaś",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Δεν υπάρχει κάτι νεότερο. Ελέγξτε αργότερα για περισσότερες ιστορίες από τον πάροχο {provider}. Δεν μπορείτε να περιμένετε; Διαλέξτε κάποιο από τα δημοφιλή θέματα και ανακαλύψτε ενδιαφέρουσες ιστορίες από όλο τον Ιστό.",
"manual_migration_explanation2": "Δοκιμάστε το Firefox με τους σελιδοδείκτες, το ιστορικό και τους κωδικούς πρόσβασης από ένα άλλο πρόγραμμα περιήγησης.",
"manual_migration_cancel_button": "Όχι ευχαριστώ",
"manual_migration_import_button": "Εισαγωγή τώρα"
"manual_migration_import_button": "Εισαγωγή τώρα",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Youve caught up. Check back later for more top stories from {provider}. Cant wait? Select a popular topic to find more great stories from around the web.",
"manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.",
"manual_migration_cancel_button": "No Thanks",
"manual_migration_import_button": "Import Now"
"manual_migration_import_button": "Import Now",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Youve caught up. Check back later for more top stories from {provider}. Cant wait? Select a popular topic to find more great stories from around the web.",
"manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.",
"manual_migration_cancel_button": "No Thanks",
"manual_migration_import_button": "Import Now"
"manual_migration_import_button": "Import Now",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Vi legis ĉion. Kontrolu denove poste ĉu estas pli da novaĵon de {provider}. Ĉu vi ne povas atendi? Elektu popularan temon por trovi pli da interesaj artikoloj en la tuta teksaĵo.",
"manual_migration_explanation2": "Provu Firefox kun la legosignoj, historio kaj pasvortoj de alia retumilo.",
"manual_migration_cancel_button": "Ne, dankon",
"manual_migration_import_button": "Importi nun"
"manual_migration_import_button": "Importi nun",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ya te pusiste al día. Volvé más tarde para más historias de {provider}. ¿No podés esperar? Seleccioná un tema popular para encontrar más historias de todo el mundo.",
"manual_migration_explanation2": "Probá Firefox con los marcadores, historial y contraseñas de otro navegador.",
"manual_migration_cancel_button": "No gracias",
"manual_migration_import_button": "Importar ahora"
"manual_migration_import_button": "Importar ahora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Te has puesto al día. Revisa más tarde para ver más historias de {provider}. ¿No puedes esperar? Selecciona un tema popular para encontrar más historias de todo el mundo.",
"manual_migration_explanation2": "Prueba Firefox con los marcadores, historial y contraseñas de otro navegador.",
"manual_migration_cancel_button": "No, gracias",
"manual_migration_import_button": "Importar ahora"
"manual_migration_import_button": "Importar ahora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ya estás al día. Vuelve luego y busca más historias de {provider}. ¿No puedes esperar? Selecciona un tema popular y encontrás más historias alucinantes por toda la web.",
"manual_migration_explanation2": "Prueba Firefox con los marcadores, historial y contraseñas de otro navegador.",
"manual_migration_cancel_button": "No, gracias",
"manual_migration_import_button": "Importar ahora"
"manual_migration_import_button": "Importar ahora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ya estás al día. Vuelve luego y busca más historias de {provider}. ¿No puedes esperar? Selecciona un tema popular y encontrarás más historias interesantes por toda la web.",
"manual_migration_explanation2": "Prueba Firefox con los marcadores, historial y contraseñas de otro navegador.",
"manual_migration_cancel_button": "No, gracias",
"manual_migration_import_button": "Importar ahora"
"manual_migration_import_button": "Importar ahora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Vaata hiljem uuesti, et näha parimaid postitusi teenusepakkujalt {provider}. Ei suuda oodata? Vali populaarne teema, et leida veel suurepärast sisu internetist.",
"manual_migration_explanation2": "Proovi Firefoxi teisest brauserist pärinevate järjehoidjate, ajaloo ja paroolidega.",
"manual_migration_cancel_button": "Ei soovi",
"manual_migration_import_button": "Impordi kohe"
"manual_migration_import_button": "Impordi kohe",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Egunean zaude jada. Etorri berriro geroago {provider} hornitzailearen istorio ezagun gehiagorako. Ezin duzu itxaron? Hautatu gai ezagun bat webeko istorio gehiago aurkitzeko.",
"manual_migration_explanation2": "Probatu Firefox beste nabigatzaile batetik ekarritako laster-marka, historia eta pasahitzekin.",
"manual_migration_cancel_button": "Ez, eskerrik asko",
"manual_migration_import_button": "Inportatu orain"
"manual_migration_import_button": "Inportatu orain",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "فعلا تموم شد. بعدا دوباره سر بزن تا مطالب جدید از {provider} ببینی. نمی‌تونی صبر کنی؟ یک موضوع محبوب رو انتخاب کن تا مطالب جالب مرتبط از سراسر دنیا رو پیدا کنی.",
"manual_migration_explanation2": "فایرفاکس را با نشانک‌ها،‌ تاریخچه‌ها و کلمات عبور از سایر مرورگر ها تجربه کنید.",
"manual_migration_cancel_button": "نه ممنون",
"manual_migration_import_button": "هم‌اکنون وارد شوند"
"manual_migration_import_button": "هم‌اکنون وارد شوند",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Youve caught up. Check back later for more top stories from {provider}. Cant wait? Select a popular topic to find more great stories from around the web.",
"manual_migration_explanation2": "Ƴeewndo Firefox wonndude e maantore ɗee, aslol kam e finndeeji iwde e wanngorde woɗnde.",
"manual_migration_cancel_button": "Alaa, moƴƴii",
"manual_migration_import_button": "Jiggo Jooni"
"manual_migration_import_button": "Jiggo Jooni",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ei enempää suosituksia juuri nyt. Katso myöhemmin uudestaan lisää ykkösjuttuja lähteestä {provider}. Etkö malta odottaa? Valitse suosittu aihe ja löydä lisää hyviä juttuja ympäri verkkoa.",
"manual_migration_explanation2": "Kokeile Firefoxia toisesta selaimesta tuotujen kirjanmerkkien, historian ja salasanojen kanssa.",
"manual_migration_cancel_button": "Ei kiitos",
"manual_migration_import_button": "Tuo nyt"
"manual_migration_import_button": "Tuo nyt",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Il ny en a pas dautres. Revenez plus tard pour plus darticles de {provider}. Vous ne voulez pas attendre ? Choisissez un sujet parmi les plus populaires pour découvrir dautres articles intéressants sur le Web.",
"manual_migration_explanation2": "Essayez Firefox en important les marque-pages, lhistorique et les mots de passe depuis un autre navigateur.",
"manual_migration_cancel_button": "Non merci",
"manual_migration_import_button": "Importer"
"manual_migration_import_button": "Importer",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Jo binne by. Kom letter werom foar mear ferhalen fan {provider}. Kin jo net wachtsje? Selektearje in populêr ûnderwerp om mear ferhalen fan it ynternet te finen.",
"manual_migration_explanation2": "Probearje Firefox en ymportearje de blêdwizers, skiednis en wachtwurden fan oare browsers.",
"manual_migration_cancel_button": "Nee tankewol",
"manual_migration_import_button": "No ymportearje"
"manual_migration_import_button": "No ymportearje",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -97,6 +97,8 @@ window.gActivityStreamStrings = {
"manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.",
"manual_migration_cancel_button": "No Thanks",
"manual_migration_import_button": "Import Now",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again.",
"settings_pane_body": "Roghnaigh na rudaí a fheicfidh tú nuair a osclóidh tú cluaisín nua.",
"settings_pane_pocketstories_header": "Barrscéalta",
"settings_pane_pocketstories_body": "Le Pocket, ball de theaghlach Mozilla, beidh tú ábalta teacht ar ábhar den chéad scoth go héasca.",

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Sin na naidheachdan uile o {provider} an-dràsta ach bidh barrachd ann a dhaithghearr. No thoir sùil air cuspair air a bheil fèill mhòr is leugh na tha a dol mun cuairt air an lìon an-dràsta.",
"manual_migration_explanation2": "Feuch Firefox leis na comharran-lìn, an eachdraidh s na faclan-faire o bhrabhsair eile.",
"manual_migration_cancel_button": "Chan eil, tapadh leibh",
"manual_migration_import_button": "Ion-phortaich an-dràsta"
"manual_migration_import_button": "Ion-phortaich an-dràsta",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Youve caught up. Check back later for more top stories from {provider}. Cant wait? Select a popular topic to find more great stories from around the web.",
"manual_migration_explanation2": "Try Firefox with the bookmarks, history and passwords from another browser.",
"manual_migration_cancel_button": "Non, grazas",
"manual_migration_import_button": "Importar agora"
"manual_migration_import_button": "Importar agora",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "Ko'ág̃a reikuaapáma ipyahúva. Eikejey ag̃ave ápe eikuaávo mombe'upy pyahu {provider} oikuave'ẽva ndéve. Ndaikatuvéima reha'ãrõ? Eiporavo peteĩ ñe'ẽmbyrã ha emoñe'ẽve oĩvéva ñande yvy ape ári.",
"manual_migration_explanation2": "Eipuru Firefox reheve techaukaha, tembiasakue ha ñe'ẽñemi ambue kundaharapegua.",
"manual_migration_cancel_button": "Ag̃amiénte",
"manual_migration_import_button": "Egueroike Ko'ág̃a"
"manual_migration_import_button": "Egueroike Ko'ág̃a",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -96,5 +96,7 @@ window.gActivityStreamStrings = {
"topstories_empty_state": "તમે પકડાઈ ગયા છો. {પ્રદાતા} તરફથી વધુ ટોચની વાતો માટે પછીથી પાછા તપાસો. રાહ નથી જોઈ શકતા? સમગ્ર વેબ પરથી વધુ સુંદર વાર્તાઓ શોધવા માટે એક લોકપ્રિય વિષય પસંદ કરો.",
"manual_migration_explanation2": "અન્ય બ્રાઉઝરથી બુકમાર્ક્સ, ઇતિહાસ અને પાસવર્ડ્સ સાથે ફાયરફોક્સ અજમાવો.",
"manual_migration_cancel_button": "ના અભાર",
"manual_migration_import_button": "હવે આયાત કરો"
"manual_migration_import_button": "હવે આયાત કરો",
"error_fallback_default_info": "Oops, something went wrong loading this content.",
"error_fallback_default_refresh_suggestion": "Refresh page to try again."
};

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше