Bug 1521168 - Export Screenshots 37.1.0 to Firefox (code excluding translations); r=_6a68

MozReview-Commit-ID: 3lIF2XGAwlj

Depends on D18102

Differential Revision: https://phabricator.services.mozilla.com/D18103

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ian Bicking 2019-02-05 20:33:45 +00:00
Родитель a00d402d69
Коммит 8812511647
19 изменённых файлов: 396 добавлений и 468 удалений

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

@ -5,8 +5,17 @@
this.analytics = (function() {
const exports = {};
const GA_PORTION = 0.1; // 10% of users will send to the server/GA
// This is set from storage, or randomly; if it is less that GA_PORTION then we send analytics:
let myGaSegment = 1;
let telemetryPrefKnown = false;
let telemetryEnabled;
// If we ever get a 410 Gone response (or 404) from the server, we'll stop trying to send events for the rest
// of the session
let hasReturnedGone = false;
// If there's this many entirely failed responses (e.g., server can't be contacted), then stop sending events
// for the rest of the session:
let serverFailedResponses = 3;
const EVENT_BATCH_DURATION = 1000; // ms for setTimeout
let pendingEvents = [];
@ -19,6 +28,10 @@ this.analytics = (function() {
credentials: "include",
};
function shouldSendEvents() {
return !hasReturnedGone && serverFailedResponses > 0 && myGaSegment < GA_PORTION;
}
function flushEvents() {
if (pendingEvents.length === 0) {
return;
@ -58,6 +71,9 @@ this.analytics = (function() {
function sendTiming(timingLabel, timingVar, timingValue) {
// sendTiming is only called in response to sendEvent, so no need to check
// the telemetry pref again here.
if (!shouldSendEvents()) {
return;
}
const timingCategory = "addon";
pendingTimings.push({
timingCategory,
@ -110,6 +126,10 @@ this.analytics = (function() {
for (const [gaField, value] of Object.entries(abTests)) {
options[gaField] = value;
}
if (!shouldSendEvents()) {
// We don't want to save or send the events anymore
return Promise.resolve();
}
pendingEvents.push({
eventTime: Date.now(),
event: eventCategory,
@ -307,16 +327,37 @@ this.analytics = (function() {
}
function fetchWatcher(request) {
catcher.watchPromise(
request.then(response => {
if (!response.ok) {
throw new Error(`Bad response from ${request.url}: ${response.status} ${response.statusText}`);
}
return response;
}),
true
);
request.then(response => {
if (response.status === 410 || response.status === 404) { // Gone
hasReturnedGone = true;
pendingEvents = [];
pendingTimings = [];
}
if (!response.ok) {
log.debug(`Error code in event response: ${response.status} ${response.statusText}`);
}
}).catch(error => {
serverFailedResponses--;
if (serverFailedResponses <= 0) {
log.info(`Server is not responding, no more events will be sent`);
pendingEvents = [];
pendingTimings = [];
}
log.debug(`Error event in response: ${error}`);
});
}
async function init() {
const result = await browser.storage.local.get(["myGaSegment"]);
if (!result.myGaSegment) {
myGaSegment = Math.random();
await browser.storage.local.set({myGaSegment});
} else {
myGaSegment = result.myGaSegment;
}
}
init();
return exports;
})();

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

@ -10,6 +10,17 @@ this.main = (function() {
const manifest = browser.runtime.getManifest();
let backend;
let _hasAnyShots = false;
startBackground.serverStatus.then((status) => {
_hasAnyShots = status.hasAny;
}).catch((e) => {
log.warn("Cannot see server status", e);
});
exports.hasAnyShots = function() {
return _hasAnyShots;
};
let hasSeenOnboarding = browser.storage.local.get(["hasSeenOnboarding"]).then((result) => {
const onboarded = !!result.hasSeenOnboarding;
@ -83,36 +94,7 @@ this.main = (function() {
// This is called by startBackground.js, where is registered as a click
// handler for the webextension page action.
exports.onClicked = catcher.watchFunction((tab) => {
catcher.watchPromise(hasSeenOnboarding.then(onboarded => {
if (shouldOpenMyShots(tab.url)) {
if (!onboarded) {
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
return forceOnboarding();
}));
return;
}
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
sendEvent("goto-myshots", "about-newtab", {incognito: tab.incognito});
}));
catcher.watchPromise(
auth.maybeLogin()
.then(() => browser.tabs.update({url: backend + "/shots"})));
} else {
catcher.watchPromise(
toggleSelector(tab)
.then(active => {
const event = active ? "start-shot" : "cancel-shot";
sendEvent(event, "toolbar-button", {incognito: tab.incognito});
}, (error) => {
if ((!onboarded) && error.popupMessage === "UNSHOOTABLE_PAGE") {
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
return forceOnboarding();
}
throw error;
}));
}
}));
_startShotFlow(tab, "toolbar-button");
});
function forceOnboarding() {
@ -120,6 +102,23 @@ this.main = (function() {
}
exports.onClickedContextMenu = catcher.watchFunction((info, tab) => {
_startShotFlow(tab, "context-menu");
});
exports.onCommand = catcher.watchFunction((tab) => {
_startShotFlow(tab, "keyboard-shortcut");
});
const _openMyShots = (tab, inputType) => {
catcher.watchPromise(analytics.refreshTelemetryPref().then(() => {
sendEvent("goto-myshots", inputType, {incognito: tab.incognito});
}));
catcher.watchPromise(
auth.maybeLogin()
.then(() => browser.tabs.update({url: backend + "/shots"})));
};
const _startShotFlow = (tab, inputType) => {
catcher.watchPromise(hasSeenOnboarding.then(onboarded => {
if (!tab) {
// Not in a page/tab context, ignore
@ -127,7 +126,8 @@ this.main = (function() {
}
if (!urlEnabled(tab.url)) {
if (!onboarded) {
sendEvent("goto-onboarding", "selection-button", {incognito: tab.incognito});
// Updated generic "selection-button" event data to inputType
sendEvent("goto-onboarding", inputType, {incognito: tab.incognito});
forceOnboarding();
return;
}
@ -135,13 +135,24 @@ this.main = (function() {
popupMessage: "UNSHOOTABLE_PAGE",
});
return;
} else if (shouldOpenMyShots(tab.url)) {
_openMyShots(tab, inputType);
return;
}
// No need to catch() here because of watchPromise().
// eslint-disable-next-line promise/catch-or-return
toggleSelector(tab)
.then(() => sendEvent("start-shot", "context-menu", {incognito: tab.incognito}));
.then(active => {
let event = "start-shot";
if (inputType !== "context-menu") {
event = active ? "start-shot" : "cancel-shot";
}
sendEvent(event, inputType, {incognito: tab.incognito});
}).catch((error) => {
throw error;
});
}));
});
};
function urlEnabled(url) {
if (shouldOpenMyShots(url)) {

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

@ -1,4 +1,4 @@
/* globals catcher, communication, log */
/* globals catcher, communication, log, main */
"use strict";
@ -69,7 +69,13 @@ this.selectorLoader = (function() {
exports.loadModules = function(tabId, hasSeenOnboarding) {
catcher.watchPromise(hasSeenOnboarding.then(onboarded => {
loadingTabs.add(tabId);
let promise = downloadOnlyCheck(tabId);
let promise = Promise.resolve();
promise = promise.then(() => {
browser.tabs.executeScript(tabId, {
code: `window.hasAnyShots = ${!!main.hasAnyShots()};`,
runAt: "document_start",
});
});
if (onboarded) {
promise = promise.then(() => {
return executeModules(tabId, standardScripts.concat(selectorScripts));
@ -89,25 +95,6 @@ this.selectorLoader = (function() {
}));
};
function downloadOnlyCheck(tabId) {
return browser.experiments.screenshots.isHistoryEnabled().then((historyEnabled) => {
return browser.experiments.screenshots.isUploadDisabled().then((uploadDisabled) => {
return browser.experiments.screenshots.getUpdateChannel().then((channel) => {
return browser.tabs.get(tabId).then(tab => {
const downloadOnly = !historyEnabled || uploadDisabled || channel === "esr" || tab.incognito;
return browser.tabs.executeScript(tabId, {
// Note: `window` here refers to a global accessible to content
// scripts, but not the scripts in the underlying page. For more
// details, see https://mdn.io/WebExtensions/Content_scripts#Content_script_environment
code: `window.downloadOnly = ${downloadOnly}`,
runAt: "document_start",
});
});
});
});
});
}
function executeModules(tabId, scripts) {
let lastPromise = Promise.resolve(null);
scripts.forEach((file) => {

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

@ -1,4 +1,4 @@
/* globals browser, main, communication */
/* globals browser, main, communication, manifest */
/* This file handles:
clicks on the WebExtension page action
browser.contextMenus.onClicked
@ -10,6 +10,16 @@ const startTime = Date.now();
this.startBackground = (function() {
const exports = {startTime};
// Wait until this many milliseconds to check the server for shots (for the purpose of migration warning):
const CHECK_SERVER_TIME = 5000; // 5 seconds
// If we want to pop open the tab showing the server status, wait this many milliseconds to open it:
const OPEN_SERVER_TAB_TIME = 5000; // 5 seconds
let hasSeenServerStatus = false;
let _resolveServerStatus;
exports.serverStatus = new Promise((resolve, reject) => {
_resolveServerStatus = {resolve, reject};
});
let backend;
const backgroundScripts = [
"log.js",
@ -40,7 +50,7 @@ this.startBackground = (function() {
browser.contextMenus.create({
id: "create-screenshot",
title: browser.i18n.getMessage("contextMenuLabel"),
contexts: ["page"],
contexts: ["page", "selection"],
documentUrlPatterns: ["<all_urls>", "about:reader*"],
});
@ -52,7 +62,21 @@ this.startBackground = (function() {
});
});
browser.experiments.screenshots.initLibraryButton();
browser.commands.onCommand.addListener((cmd) => {
if (cmd !== "take-screenshot") {
return;
}
loadIfNecessary().then(() => {
browser.tabs.query({currentWindow: true, active: true}).then((tabs) => {
const activeTab = tabs[0];
main.onCommand(activeTab);
}).catch((error) => {
throw error;
});
}).catch((error) => {
console.error("Error toggling Screenshots via keyboard shortcut: ", error);
});
});
browser.runtime.onMessage.addListener((req, sender, sendResponse) => {
loadIfNecessary().then(() => {
@ -90,5 +114,84 @@ this.startBackground = (function() {
return loadedPromise;
}
async function checkExpiration() {
const manifest = await browser.runtime.getManifest();
for (const permission of manifest.permissions) {
if (/^https?:\/\//.test(permission)) {
backend = permission.replace(/\/*$/, "");
break;
}
}
const result = await browser.storage.local.get(["registrationInfo", "hasSeenServerStatus", "hasShotsResponse"]);
hasSeenServerStatus = result.hasSeenServerStatus;
const { registrationInfo } = result;
if (!backend || !registrationInfo || !registrationInfo.registered) {
// The add-on hasn't been used, or at least no upload has occurred
_resolveServerStatus.resolve({hasIndefinite: false, hasAny: false});
return;
}
if (result.hasShotsResponse) {
// We've already retrieved information from the server
_resolveServerStatus.resolve(result.hasShotsResponse);
return;
}
const loginUrl = `${backend}/api/login`;
const hasShotsUrl = `${backend}/api/has-shots`;
try {
let resp = await fetch(loginUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
deviceId: registrationInfo.deviceId,
secret: registrationInfo.secret,
}),
});
if (!resp.ok) {
throw new Error(`Bad login response: ${resp.status}`);
}
const { authHeader } = await resp.json();
resp = await fetch(hasShotsUrl, {
method: "GET",
credentials: "include",
headers: Object.assign({}, authHeader, {
"Content-Type": "application/json",
}),
});
if (!resp.ok) {
throw new Error(`Bad response from server: ${resp.status}`);
}
const body = await resp.json();
browser.storage.local.set({hasShotsResponse: body});
_resolveServerStatus.resolve(body);
} catch (e) {
_resolveServerStatus.reject(e);
}
}
exports.serverStatus.then((status) => {
if (status.hasAny) {
browser.experiments.screenshots.initLibraryButton();
}
if (status.hasIndefinite && !hasSeenServerStatus) {
setTimeout(async () => {
await browser.tabs.create({
url: `${backend}/hosting-shutdown`,
});
hasSeenServerStatus = true;
await browser.storage.local.set({hasSeenServerStatus});
}, OPEN_SERVER_TAB_TIME);
}
}).catch((e) => {
console.error("Error finding Screenshots server status:", String(e), e.stack);
});
setTimeout(() => {
window.requestIdleCallback(() => {
checkExpiration();
});
}, CHECK_SERVER_TIME);
return exports;
})();

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

@ -1,6 +1,6 @@
/* Created from build/server/static/css/inline-selection.css */
window.inlineSelectionCss = `
.button, .highlight-button-cancel, .highlight-button-save, .highlight-button-download, .highlight-button-copy, .preview-button-save {
.button, .highlight-button-cancel, .highlight-button-download, .highlight-button-copy {
display: flex;
align-items: center;
justify-content: center;
@ -19,31 +19,31 @@ window.inlineSelectionCss = `
transition: background 150ms cubic-bezier(0.07, 0.95, 0, 1), border 150ms cubic-bezier(0.07, 0.95, 0, 1);
user-select: none;
white-space: nowrap; }
.button.hidden, .hidden.highlight-button-cancel, .hidden.highlight-button-save, .hidden.highlight-button-download, .hidden.highlight-button-copy, .hidden.preview-button-save {
.button.hidden, .hidden.highlight-button-cancel, .hidden.highlight-button-download, .hidden.highlight-button-copy {
display: none; }
.button.small, .small.highlight-button-cancel, .small.highlight-button-save, .small.highlight-button-download, .small.highlight-button-copy, .small.preview-button-save {
.button.small, .small.highlight-button-cancel, .small.highlight-button-download, .small.highlight-button-copy {
height: 32px;
line-height: 32px;
padding: 0 8px; }
.button.active, .active.highlight-button-cancel, .active.highlight-button-save, .active.highlight-button-download, .active.highlight-button-copy, .active.preview-button-save {
.button.active, .active.highlight-button-cancel, .active.highlight-button-download, .active.highlight-button-copy {
background-color: #dedede; }
.button.tiny, .tiny.highlight-button-cancel, .tiny.highlight-button-save, .tiny.highlight-button-download, .tiny.highlight-button-copy, .tiny.preview-button-save {
.button.tiny, .tiny.highlight-button-cancel, .tiny.highlight-button-download, .tiny.highlight-button-copy {
font-size: 14px;
height: 26px;
border: 1px solid #c7c7c7; }
.button.tiny:hover, .tiny.highlight-button-cancel:hover, .tiny.highlight-button-save:hover, .tiny.highlight-button-download:hover, .tiny.highlight-button-copy:hover, .tiny.preview-button-save:hover, .button.tiny:focus, .tiny.highlight-button-cancel:focus, .tiny.highlight-button-save:focus, .tiny.highlight-button-download:focus, .tiny.highlight-button-copy:focus, .tiny.preview-button-save:focus {
.button.tiny:hover, .tiny.highlight-button-cancel:hover, .tiny.highlight-button-download:hover, .tiny.highlight-button-copy:hover, .button.tiny:focus, .tiny.highlight-button-cancel:focus, .tiny.highlight-button-download:focus, .tiny.highlight-button-copy:focus {
background: #ededf0;
border-color: #989898; }
.button.tiny:active, .tiny.highlight-button-cancel:active, .tiny.highlight-button-save:active, .tiny.highlight-button-download:active, .tiny.highlight-button-copy:active, .tiny.preview-button-save:active {
.button.tiny:active, .tiny.highlight-button-cancel:active, .tiny.highlight-button-download:active, .tiny.highlight-button-copy:active {
background: #dedede;
border-color: #989898; }
.button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-save, .block-button.highlight-button-download, .block-button.highlight-button-copy, .block-button.preview-button-save {
.button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-download, .block-button.highlight-button-copy {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border: 0;
border-right: 1px solid #c7c7c7;
border-inline-end: 1px solid #c7c7c7;
box-shadow: 0;
border-radius: 0;
flex-shrink: 0;
@ -52,47 +52,47 @@ window.inlineSelectionCss = `
line-height: 100%;
overflow: hidden; }
@media (max-width: 719px) {
.button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-save, .block-button.highlight-button-download, .block-button.highlight-button-copy, .block-button.preview-button-save {
.button.block-button, .block-button.highlight-button-cancel, .block-button.highlight-button-download, .block-button.highlight-button-copy {
justify-content: flex-start;
font-size: 16px;
height: 72px;
margin-right: 10px;
margin-inline-end: 10px;
padding: 0 5px; } }
.button.block-button:hover, .block-button.highlight-button-cancel:hover, .block-button.highlight-button-save:hover, .block-button.highlight-button-download:hover, .block-button.highlight-button-copy:hover, .block-button.preview-button-save:hover {
.button.block-button:hover, .block-button.highlight-button-cancel:hover, .block-button.highlight-button-download:hover, .block-button.highlight-button-copy:hover {
background: #ededf0; }
.button.block-button:active, .block-button.highlight-button-cancel:active, .block-button.highlight-button-save:active, .block-button.highlight-button-download:active, .block-button.highlight-button-copy:active, .block-button.preview-button-save:active {
.button.block-button:active, .block-button.highlight-button-cancel:active, .block-button.highlight-button-download:active, .block-button.highlight-button-copy:active {
background: #dedede; }
.button.download, .download.highlight-button-cancel, .download.highlight-button-save, .download.highlight-button-download, .download.highlight-button-copy, .download.preview-button-save, .button.edit, .edit.highlight-button-cancel, .edit.highlight-button-save, .edit.highlight-button-download, .edit.highlight-button-copy, .edit.preview-button-save, .button.trash, .trash.highlight-button-cancel, .trash.highlight-button-save, .trash.highlight-button-download, .trash.highlight-button-copy, .trash.preview-button-save, .button.share, .share.highlight-button-cancel, .share.highlight-button-save, .share.highlight-button-download, .share.highlight-button-copy, .share.preview-button-save, .button.flag, .flag.highlight-button-cancel, .flag.highlight-button-save, .flag.highlight-button-download, .flag.highlight-button-copy, .flag.preview-button-save {
.button.download, .download.highlight-button-cancel, .download.highlight-button-download, .download.highlight-button-copy, .button.edit, .edit.highlight-button-cancel, .edit.highlight-button-download, .edit.highlight-button-copy, .button.trash, .trash.highlight-button-cancel, .trash.highlight-button-download, .trash.highlight-button-copy, .button.share, .share.highlight-button-cancel, .share.highlight-button-download, .share.highlight-button-copy, .button.flag, .flag.highlight-button-cancel, .flag.highlight-button-download, .flag.highlight-button-copy {
background-repeat: no-repeat;
background-size: 50%;
background-position: center;
margin-right: 10px;
margin-inline-end: 10px;
transition: background-color 150ms cubic-bezier(0.07, 0.95, 0, 1); }
.button.download, .download.highlight-button-cancel, .download.highlight-button-save, .download.highlight-button-download, .download.highlight-button-copy, .download.preview-button-save {
.button.download, .download.highlight-button-cancel, .download.highlight-button-download, .download.highlight-button-copy {
background-image: url("../img/icon-download.svg"); }
.button.download:hover, .download.highlight-button-cancel:hover, .download.highlight-button-save:hover, .download.highlight-button-download:hover, .download.highlight-button-copy:hover, .download.preview-button-save:hover {
.button.download:hover, .download.highlight-button-cancel:hover, .download.highlight-button-download:hover, .download.highlight-button-copy:hover {
background-color: #ededf0; }
.button.download:active, .download.highlight-button-cancel:active, .download.highlight-button-save:active, .download.highlight-button-download:active, .download.highlight-button-copy:active, .download.preview-button-save:active {
.button.download:active, .download.highlight-button-cancel:active, .download.highlight-button-download:active, .download.highlight-button-copy:active {
background-color: #dedede; }
.button.share, .share.highlight-button-cancel, .share.highlight-button-save, .share.highlight-button-download, .share.highlight-button-copy, .share.preview-button-save {
.button.share, .share.highlight-button-cancel, .share.highlight-button-download, .share.highlight-button-copy {
background-image: url("../img/icon-share.svg"); }
.button.share:hover, .share.highlight-button-cancel:hover, .share.highlight-button-save:hover, .share.highlight-button-download:hover, .share.highlight-button-copy:hover, .share.preview-button-save:hover {
.button.share:hover, .share.highlight-button-cancel:hover, .share.highlight-button-download:hover, .share.highlight-button-copy:hover {
background-color: #ededf0; }
.button.share.active, .share.active.highlight-button-cancel, .share.active.highlight-button-save, .share.active.highlight-button-download, .share.active.highlight-button-copy, .share.active.preview-button-save, .button.share:active, .share.highlight-button-cancel:active, .share.highlight-button-save:active, .share.highlight-button-download:active, .share.highlight-button-copy:active, .share.preview-button-save:active {
.button.share.active, .share.active.highlight-button-cancel, .share.active.highlight-button-download, .share.active.highlight-button-copy, .button.share:active, .share.highlight-button-cancel:active, .share.highlight-button-download:active, .share.highlight-button-copy:active {
background-color: #dedede; }
.button.share.newicon, .share.newicon.highlight-button-cancel, .share.newicon.highlight-button-save, .share.newicon.highlight-button-download, .share.newicon.highlight-button-copy, .share.newicon.preview-button-save {
.button.share.newicon, .share.newicon.highlight-button-cancel, .share.newicon.highlight-button-download, .share.newicon.highlight-button-copy {
background-image: url("../img/icon-share-alternate.svg"); }
.button.trash, .trash.highlight-button-cancel, .trash.highlight-button-save, .trash.highlight-button-download, .trash.highlight-button-copy, .trash.preview-button-save {
.button.trash, .trash.highlight-button-cancel, .trash.highlight-button-download, .trash.highlight-button-copy {
background-image: url("../img/icon-trash.svg"); }
.button.trash:hover, .trash.highlight-button-cancel:hover, .trash.highlight-button-save:hover, .trash.highlight-button-download:hover, .trash.highlight-button-copy:hover, .trash.preview-button-save:hover {
.button.trash:hover, .trash.highlight-button-cancel:hover, .trash.highlight-button-download:hover, .trash.highlight-button-copy:hover {
background-color: #ededf0; }
.button.trash:active, .trash.highlight-button-cancel:active, .trash.highlight-button-save:active, .trash.highlight-button-download:active, .trash.highlight-button-copy:active, .trash.preview-button-save:active {
.button.trash:active, .trash.highlight-button-cancel:active, .trash.highlight-button-download:active, .trash.highlight-button-copy:active {
background-color: #dedede; }
.button.edit, .edit.highlight-button-cancel, .edit.highlight-button-save, .edit.highlight-button-download, .edit.highlight-button-copy, .edit.preview-button-save {
.button.edit, .edit.highlight-button-cancel, .edit.highlight-button-download, .edit.highlight-button-copy {
background-image: url("../img/icon-edit.svg"); }
.button.edit:hover, .edit.highlight-button-cancel:hover, .edit.highlight-button-save:hover, .edit.highlight-button-download:hover, .edit.highlight-button-copy:hover, .edit.preview-button-save:hover {
.button.edit:hover, .edit.highlight-button-cancel:hover, .edit.highlight-button-download:hover, .edit.highlight-button-copy:hover {
background-color: #ededf0; }
.button.edit:active, .edit.highlight-button-cancel:active, .edit.highlight-button-save:active, .edit.highlight-button-download:active, .edit.highlight-button-copy:active, .edit.preview-button-save:active {
.button.edit:active, .edit.highlight-button-cancel:active, .edit.highlight-button-download:active, .edit.highlight-button-copy:active {
background-color: #dedede; }
.app-body {
@ -117,36 +117,36 @@ window.inlineSelectionCss = `
color: #e1e1e6;
text-decoration: underline; }
.button.primary, .primary.highlight-button-cancel, .highlight-button-save, .primary.highlight-button-download, .primary.highlight-button-copy, .preview-button-save {
.button.primary, .primary.highlight-button-cancel, .highlight-button-download, .primary.highlight-button-copy {
background-color: #0a84ff;
color: #fff; }
.button.primary:hover, .primary.highlight-button-cancel:hover, .highlight-button-save:hover, .primary.highlight-button-download:hover, .primary.highlight-button-copy:hover, .preview-button-save:hover, .button.primary:focus, .primary.highlight-button-cancel:focus, .highlight-button-save:focus, .primary.highlight-button-download:focus, .primary.highlight-button-copy:focus, .preview-button-save:focus {
.button.primary:hover, .primary.highlight-button-cancel:hover, .highlight-button-download:hover, .primary.highlight-button-copy:hover, .button.primary:focus, .primary.highlight-button-cancel:focus, .highlight-button-download:focus, .primary.highlight-button-copy:focus {
background-color: #0072e5; }
.button.primary:active, .primary.highlight-button-cancel:active, .highlight-button-save:active, .primary.highlight-button-download:active, .primary.highlight-button-copy:active, .preview-button-save:active {
.button.primary:active, .primary.highlight-button-cancel:active, .highlight-button-download:active, .primary.highlight-button-copy:active {
background-color: #0065cc; }
.button.secondary, .highlight-button-cancel, .secondary.highlight-button-save, .highlight-button-download, .highlight-button-copy, .secondary.preview-button-save {
.button.secondary, .highlight-button-cancel, .secondary.highlight-button-download, .highlight-button-copy {
background-color: #f9f9fa;
color: #38383d; }
.button.secondary:hover, .highlight-button-cancel:hover, .secondary.highlight-button-save:hover, .highlight-button-download:hover, .highlight-button-copy:hover, .secondary.preview-button-save:hover {
.button.secondary:hover, .highlight-button-cancel:hover, .secondary.highlight-button-download:hover, .highlight-button-copy:hover {
background-color: #ededf0; }
.button.secondary:active, .highlight-button-cancel:active, .secondary.highlight-button-save:active, .highlight-button-download:active, .highlight-button-copy:active, .secondary.preview-button-save:active {
.button.secondary:active, .highlight-button-cancel:active, .secondary.highlight-button-download:active, .highlight-button-copy:active {
background-color: #dedede; }
.button.transparent, .transparent.highlight-button-cancel, .transparent.highlight-button-save, .transparent.highlight-button-download, .transparent.highlight-button-copy, .transparent.preview-button-save {
.button.transparent, .transparent.highlight-button-cancel, .transparent.highlight-button-download, .transparent.highlight-button-copy {
background-color: transparent;
color: #38383d; }
.button.transparent:hover, .transparent.highlight-button-cancel:hover, .transparent.highlight-button-save:hover, .transparent.highlight-button-download:hover, .transparent.highlight-button-copy:hover, .transparent.preview-button-save:hover {
.button.transparent:hover, .transparent.highlight-button-cancel:hover, .transparent.highlight-button-download:hover, .transparent.highlight-button-copy:hover {
background-color: #ededf0; }
.button.transparent:focus, .transparent.highlight-button-cancel:focus, .transparent.highlight-button-save:focus, .transparent.highlight-button-download:focus, .transparent.highlight-button-copy:focus, .transparent.preview-button-save:focus, .button.transparent:active, .transparent.highlight-button-cancel:active, .transparent.highlight-button-save:active, .transparent.highlight-button-download:active, .transparent.highlight-button-copy:active, .transparent.preview-button-save:active {
.button.transparent:focus, .transparent.highlight-button-cancel:focus, .transparent.highlight-button-download:focus, .transparent.highlight-button-copy:focus, .button.transparent:active, .transparent.highlight-button-cancel:active, .transparent.highlight-button-download:active, .transparent.highlight-button-copy:active {
background-color: #dedede; }
.button.warning, .warning.highlight-button-cancel, .warning.highlight-button-save, .warning.highlight-button-download, .warning.highlight-button-copy, .warning.preview-button-save {
.button.warning, .warning.highlight-button-cancel, .warning.highlight-button-download, .warning.highlight-button-copy {
color: #fff;
background: #d92215; }
.button.warning:hover, .warning.highlight-button-cancel:hover, .warning.highlight-button-save:hover, .warning.highlight-button-download:hover, .warning.highlight-button-copy:hover, .warning.preview-button-save:hover, .button.warning:focus, .warning.highlight-button-cancel:focus, .warning.highlight-button-save:focus, .warning.highlight-button-download:focus, .warning.highlight-button-copy:focus, .warning.preview-button-save:focus {
.button.warning:hover, .warning.highlight-button-cancel:hover, .warning.highlight-button-download:hover, .warning.highlight-button-copy:hover, .button.warning:focus, .warning.highlight-button-cancel:focus, .warning.highlight-button-download:focus, .warning.highlight-button-copy:focus {
background: #b81d12; }
.button.warning:active, .warning.highlight-button-cancel:active, .warning.highlight-button-save:active, .warning.highlight-button-download:active, .warning.highlight-button-copy:active, .warning.preview-button-save:active {
.button.warning:active, .warning.highlight-button-cancel:active, .warning.highlight-button-download:active, .warning.highlight-button-copy:active {
background: #a11910; }
.subtitle-link {
@ -245,9 +245,9 @@ window.inlineSelectionCss = `
border: 2px dashed rgba(255, 255, 255, 0.4);
bottom: 0;
content: "";
left: 0;
inset-inline-start: 0;
position: absolute;
right: 0;
inset-inline-end: 0;
top: 0; }
body.hcm .hover-highlight {
background-color: white;
@ -256,14 +256,14 @@ window.inlineSelectionCss = `
.mover-target.direction-topLeft {
cursor: nwse-resize;
height: 60px;
left: -30px;
inset-inline-start: -30px;
top: -30px;
width: 60px; }
.mover-target.direction-top {
cursor: ns-resize;
height: 60px;
left: 0;
inset-inline-start: 0;
top: -30px;
width: 100%;
z-index: 4; }
@ -271,14 +271,14 @@ window.inlineSelectionCss = `
.mover-target.direction-topRight {
cursor: nesw-resize;
height: 60px;
right: -30px;
inset-inline-end: -30px;
top: -30px;
width: 60px; }
.mover-target.direction-left {
cursor: ew-resize;
height: 100%;
left: -30px;
inset-inline-start: -30px;
top: 0;
width: 60px;
z-index: 4; }
@ -286,7 +286,7 @@ window.inlineSelectionCss = `
.mover-target.direction-right {
cursor: ew-resize;
height: 100%;
right: -30px;
inset-inline-end: -30px;
top: 0;
width: 60px;
z-index: 4; }
@ -295,14 +295,14 @@ window.inlineSelectionCss = `
bottom: -30px;
cursor: nesw-resize;
height: 60px;
left: -30px;
inset-inline-start: -30px;
width: 60px; }
.mover-target.direction-bottom {
bottom: -30px;
cursor: ns-resize;
height: 60px;
left: 0;
inset-inline-start: 0;
width: 100%;
z-index: 4; }
@ -310,7 +310,7 @@ window.inlineSelectionCss = `
bottom: -30px;
cursor: nwse-resize;
height: 60px;
right: -30px;
inset-inline-end: -30px;
width: 60px; }
.mover-target:hover .mover {
@ -332,7 +332,7 @@ window.inlineSelectionCss = `
.direction-topLeft .mover,
.direction-left .mover,
.direction-bottomLeft .mover {
left: -1px; }
inset-inline-start: -1px; }
.direction-topLeft .mover,
.direction-top .mover,
@ -342,7 +342,7 @@ window.inlineSelectionCss = `
.direction-topRight .mover,
.direction-right .mover,
.direction-bottomRight .mover {
right: -1px; }
inset-inline-end: -1px; }
.direction-bottomRight .mover,
.direction-bottom .mover,
@ -357,90 +357,13 @@ window.inlineSelectionCss = `
background-color: black;
opacity: 0.7; }
.notice {
display: flex;
height: 41px;
left: 50%;
position: fixed;
transform: translate(-50%, 0);
transition: top 125ms ease-out, translate 125ms ease-out;
user-select: none;
will-change: top, translate;
z-index: 10000000000; }
.notice .notice-wrapper {
align-items: center;
background: #737373;
border-radius: 100px;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
padding: 10px 15px; }
.notice .notice-content {
color: #fff;
flex: 1;
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", "helvetica neue", helvetica, ubuntu, roboto, noto, arial, sans-serif;
font-size: 14px;
font-weight: bold;
white-space: nowrap; }
.notice .notice-help {
background-image: url("MOZ_EXTENSION/icons/help-16.svg");
background-position: center center;
background-repeat: no-repeat;
height: 16px;
width: 16px; }
.notice.middle {
display: none;
top: calc(50% - 21px); }
.preview-button-save:active ~ .notice.middle,
.preview-button-save:focus ~ .notice.middle,
.preview-button-save:hover ~ .notice.middle {
display: block; }
.notice-tooltip {
background: #fff;
border-radius: 3px;
border: 1px solid #9d9d9e;
bottom: 60px;
color: #000;
cursor: default;
display: none;
font-family: -apple-system, BlinkMacSystemFont, "segoe ui", "helvetica neue", helvetica, ubuntu, roboto, noto, arial, sans-serif;
font-size: 14px;
font-weight: normal;
line-height: 22px;
overflow-wrap: break-word;
padding: 15px;
position: absolute;
right: -14px;
white-space: normal;
width: 300px;
z-index: 10000000000;
/* down-arrow for the tooltip */ }
.notice:hover .notice-tooltip {
display: block; }
.notice-tooltip p {
margin: 0; }
.notice-tooltip ul {
margin-bottom: 0; }
.notice-tooltip::after {
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid #f9f9fa;
content: "";
height: 0;
left: 86%;
position: absolute;
top: 100%;
width: 0; }
.preview-overlay {
align-items: center;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
height: 100%;
justify-content: center;
left: 0;
inset-inline-start: 0;
margin: 0;
padding: 0;
position: fixed;
@ -455,7 +378,7 @@ window.inlineSelectionCss = `
cursor: crosshair; }
.highlight {
border-radius: 2px;
border-radius: 1px;
border: 2px dashed rgba(255, 255, 255, 0.8);
box-sizing: border-box;
cursor: move;
@ -469,54 +392,38 @@ window.inlineSelectionCss = `
display: flex;
align-items: center;
justify-content: center;
bottom: -55px;
bottom: -58px;
position: absolute;
inset-inline-end: 5px;
z-index: 6; }
html[dir="rtl"] .highlight-buttons {
left: 5px; }
html[dir="ltr"] .highlight-buttons {
right: 5px; }
.bottom-selection .highlight-buttons {
bottom: 5px; }
.left-selection .highlight-buttons {
right: auto;
left: 5px; }
inset-inline-end: auto;
inset-inline-start: 5px; }
.highlight-buttons > button {
box-shadow: 0 0 0 1px rgba(12, 12, 13, 0.1), 0 2px 8px rgba(12, 12, 13, 0.1); }
.highlight-button-cancel {
border: 1px solid #dedede;
margin: 5px;
width: 40px; }
.highlight-button-save {
font-size: 18px;
margin: 5px;
min-width: 80px; }
html[dir="ltr"] .highlight-button-save img {
padding-right: 8px; }
html[dir="rtl"] .highlight-button-save img {
padding-left: 8px; }
.highlight-button-download {
border: 1px solid #dedede;
display: block;
margin: 5px;
width: 40px; }
.highlight-button-download.download-only-button {
font-size: 18px;
width: auto; }
.highlight-button-download.download-only-button img {
height: 16px;
width: 16px; }
html[dir="ltr"] .highlight-button-download.download-only-button img {
padding-right: 8px; }
html[dir="rtl"] .highlight-button-download.download-only-button img {
padding-left: 8px; }
width: auto;
font-size: 18px; }
.highlight-button-download img {
height: 16px;
width: 16px;
padding-inline-end: 8px; }
.highlight-button-copy {
border: 1px solid #dedede;
display: block;
margin: 5px;
width: 40px; }
width: auto; }
.highlight-button-copy img {
height: 16px;
width: 16px;
padding-inline-end: 8px; }
.pixel-dimensions {
position: absolute;
@ -530,40 +437,51 @@ window.inlineSelectionCss = `
.preview-buttons {
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-end;
padding-inline-end: 4px;
inset-inline-end: 0;
width: 100%;
position: absolute;
top: -2px; }
html[dir="rtl"] .preview-buttons {
left: 0; }
html[dir="ltr"] .preview-buttons {
right: 0; }
height: 60px;
border-radius: 4px 4px 0 0;
background: rgba(249, 249, 250, 0.8);
top: 0;
border: 1px solid rgba(249, 249, 250, 0.2);
border-bottom: 0;
box-sizing: border-box; }
.preview-image {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
margin: 24px auto;
position: relative;
height: 80%;
max-width: 100%;
margin: auto 2em;
max-width: 80%;
max-height: 95%;
text-align: center;
animation-delay: 50ms;
animation: bounce-in 300ms forwards ease-in-out; }
display: flex; }
.preview-image > img {
.preview-image-wrapper {
background: rgba(249, 249, 250, 0.8);
border-radius: 0 0 4px 4px;
display: block;
width: auto;
height: auto;
max-width: 100%;
max-height: 90%;
margin: 50px auto;
border: 1px solid rgba(255, 255, 255, 0.8); }
min-width: 320px;
overflow-y: scroll;
padding: 0 60px;
margin-top: 60px;
border: 1px solid rgba(249, 249, 250, 0.2);
border-top: 0; }
.preview-button-save {
font-size: 18px;
margin: 5px;
min-width: 80px; }
html[dir="ltr"] .preview-button-save img {
padding-right: 8px; }
html[dir="rtl"] .preview-button-save img {
padding-left: 8px; }
.preview-image-wrapper > img {
box-shadow: 0 0 0 1px rgba(12, 12, 13, 0.1), 0 2px 8px rgba(12, 12, 13, 0.1);
height: auto;
margin-bottom: 60px;
max-width: 100%;
width: 100%; }
.fixed-container {
align-items: center;
@ -571,7 +489,7 @@ window.inlineSelectionCss = `
flex-direction: column;
height: 100vh;
justify-content: center;
left: 0;
inset-inline-start: 0;
margin: 0;
padding: 0;
pointer-events: none;
@ -597,7 +515,7 @@ window.inlineSelectionCss = `
position: absolute;
border-radius: 100%;
overflow: hidden;
left: 16.4px;
inset-inline-start: 16.4px;
top: 19.8px; }
.eyeball {
@ -606,15 +524,15 @@ window.inlineSelectionCss = `
height: 6px;
background-color: #000;
border-radius: 50%;
left: 2.4px;
inset-inline-start: 2.4px;
top: 4.3px;
z-index: 10; }
.left {
margin-left: 0; }
margin-inline-start: 0; }
.right {
margin-left: 20px; }
margin-inline-start: 20px; }
.preview-instructions {
display: flex;
@ -653,11 +571,9 @@ window.inlineSelectionCss = `
height: 80px;
padding: 8px;
position: absolute;
right: 5px;
top: 5px; }
html[dir="rtl"] .myshots-all-buttons-container {
left: 5px;
right: inherit; }
inset-inline-end: 8px;
top: 8px;
box-shadow: 0 0 0 1px rgba(12, 12, 13, 0.1), 0 2px 8px rgba(12, 12, 13, 0.1); }
.myshots-all-buttons-container .spacer {
background-color: #c9c9c9;
flex: 0 0 1px;
@ -670,6 +586,7 @@ window.inlineSelectionCss = `
align-items: center;
flex-direction: column;
justify-content: flex-end;
color: #3e3d40;
background-color: #f5f5f5;
background-position: center top;
background-repeat: no-repeat;

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

@ -122,7 +122,7 @@ body {
border-radius: 2px;
color: #fff;
font-size: 16px;
margin-left: 5px;
margin-inline-start: 5px;
padding: 2px; }
.slide p {
animation-duration: 350ms;
@ -219,21 +219,15 @@ body {
#prev {
background-image: url("MOZ_EXTENSION/icons/back.svg");
left: 50%; }
html[dir="ltr"] #prev {
margin-left: -385px; }
html[dir="rtl"] #prev {
margin-left: 315px; }
inset-inline-start: 50%;
margin-inline-start: -385px; }
[dir="rtl"] #prev {
transform: rotate(180deg); }
#next,
#done {
left: 50%; }
html[dir="ltr"] #next, html[dir="ltr"]
#done {
margin-left: 315px; }
html[dir="rtl"] #next, html[dir="rtl"]
#done {
margin-left: -385px; }
inset-inline-start: 50%;
margin-inline-start: 315px; }
#prev,
#next,
@ -255,22 +249,18 @@ body {
#next {
background-image: url("MOZ_EXTENSION/icons/back.svg");
transform: rotate(180deg); }
[dir="rtl"] #next {
transform: rotate(0deg); }
.active-slide-1 #next {
background-image: url("MOZ_EXTENSION/icons/back-highlight.svg"); }
[dir='rtl'] #next {
transform: rotate(0deg); }
[dir='rtl'] #prev {
transform: rotate(180deg); }
#skip {
background: none;
border: 0;
color: #fff;
font-size: 16px;
left: 50%;
margin-left: -330px;
inset-inline-start: 50%;
margin-inline-start: -330px;
margin-top: 257px;
opacity: 0.7;
position: absolute;
@ -289,7 +279,7 @@ body {
background-image: url("MOZ_EXTENSION/icons/done.svg");
display: none; }
.active-slide-6 #done {
.active-slide-4 #done {
display: inline-block; }
/* for smaller screen sizes */
@ -314,13 +304,13 @@ body {
font-size: 10px;
line-height: 16px; }
#skip {
margin-left: -205px;
margin-inline-start: -205px;
margin-top: 177px; }
#prev {
margin-left: -260px; }
margin-inline-start: -260px; }
#next,
#done {
margin-left: 190px; } }
margin-inline-start: 190px; } }
`;
null;

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

@ -10,14 +10,14 @@ window.onboardingHtml = `
<body>
<div id="slide-overlay">
<!-- The current slide is set by having .active-slide-1, .active-slide-2, etc on #slide element: -->
<div id="slide-container" data-number-of-slides="6" class="active-slide-1">
<div id="slide-container" data-number-of-slides="4" class="active-slide-1">
<div class="slide slide-1">
<!-- Note: all images must be listed in manifest.json.template under web_accessible_resources -->
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-1.png');"></div>
<div class="slide-content">
<div class="slide-content-aligner">
<h1><span><strong>Firefox</strong> Screenshots</span><sup>Beta</sup></h1>
<p data-l10n-id="tourBodyIntro"></p>
<h1><span><strong>Firefox</strong> Screenshots</span></h1>
<p data-l10n-id="tourBodyIntroServerless"></p>
</div>
<p class="onboarding-legal-notice"><!-- Substituted with termsAndPrivacyNotice --></p>
</div>
@ -43,20 +43,6 @@ window.onboardingHtml = `
<p data-l10n-id="tourBodyFullPage"></p>
</div>
</div>
<div class="slide slide-5">
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-5.png');"></div>
<div class="slide-content">
<h1 data-l10n-id="tourHeaderDownloadUpload"></h1>
<p data-l10n-id="tourBodyDownloadUpload"></p>
</div>
</div>
<div class="slide slide-6">
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-6.png');"></div>
<div class="slide-content">
<h1 data-l10n-id="tourHeaderAccounts"></h1>
<p data-l10n-id="tourBodyAccounts"></p>
</div>
</div>
<!-- Clickable elements should be buttons for accessibility -->
<button id="skip" data-l10n-id="tourSkip" tabindex=1>Skip</button>
@ -68,8 +54,6 @@ window.onboardingHtml = `
<button class="goto-slide goto-slide-2" data-number="2" tabindex=5></button>
<button class="goto-slide goto-slide-3" data-number="3" tabindex=6></button>
<button class="goto-slide goto-slide-4" data-number="4" tabindex=7></button>
<button class="goto-slide goto-slide-5" data-number="5" tabindex=8></button>
<button class="goto-slide goto-slide-6" data-number="6" tabindex=9></button>
</div>
<!-- FIXME: Need to put in privacy / etc links -->
</div>

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

@ -332,6 +332,14 @@ class AbstractShot {
this._origin = val || undefined;
}
get isOwner() {
return this._isOwner;
}
set isOwner(val) {
this._isOwner = val || undefined;
}
get filename() {
let filenameTitle = this.title;
const date = new Date(this.createdDate);

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

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.1 12L4.9 7.9c-.5-.5-1.3-.5-1.8 0s-.5 1.3 0 1.8l6.2 6.2c.5.5 1.3.5 1.8 0l6.2-6.2c.5-.5.5-1.3 0-1.8s-1.3-.5-1.8 0L11.6 12V1.2C11.6.6 11 0 10.3 0c-.7 0-1.2.6-1.2 1.2V12zM4 20c-.7 0-1.2-.6-1.2-1.2s.6-1.2 1.2-1.2h12.5c.7 0 1.2.6 1.2 1.2s-.5 1.2-1.2 1.2H4z" fill="#fff"/></svg>

После

Ширина:  |  Высота:  |  Размер: 343 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 70 KiB

После

Ширина:  |  Высота:  |  Размер: 69 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 34 KiB

После

Ширина:  |  Высота:  |  Размер: 29 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 22 KiB

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

@ -1,10 +1,11 @@
{
"manifest_version": 2,
"name": "Firefox Screenshots",
"version": "35.0.0",
"version": "37.1.0",
"description": "__MSG_addonDescription__",
"author": "__MSG_addonAuthorsList__",
"homepage_url": "https://github.com/mozilla-services/screenshots",
"incognito": "spanning",
"applications": {
"gecko": {
"id": "screenshots@mozilla.org",
@ -18,6 +19,14 @@
"background/startBackground.js"
]
},
"commands": {
"take-screenshot": {
"suggested_key": {
"default": "Ctrl+Shift+S"
},
"description": "Open the Firefox Screenshots UI"
}
},
"content_scripts": [
{
"matches": ["https://screenshots.firefox.com/*"],

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

@ -429,6 +429,7 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["icons"] += [
'icons/copied-notification.svg',
'icons/copy.svg',
'icons/done.svg',
'icons/download-white.svg',
'icons/download.svg',
'icons/help-16.svg',
'icons/icon-highlight-32-v2.svg',
@ -441,9 +442,7 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["icons"] += [
'icons/onboarding-1.png',
'icons/onboarding-2.png',
'icons/onboarding-3.png',
'icons/onboarding-4.png',
'icons/onboarding-5.png',
'icons/onboarding-6.png'
'icons/onboarding-4.png'
]
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["onboarding"] += [
@ -460,12 +459,6 @@ FINAL_TARGET_FILES.features['screenshots@mozilla.org']["selector"] += [
'selector/util.js'
]
FINAL_TARGET_FILES.features['screenshots@mozilla.org']["test"]["browser"] += [
'test/browser/.eslintrc.yml',
'test/browser/browser.ini',
'test/browser/browser_screenshots_ui_check.js'
]
# AUTOMATIC INSERTION END
BROWSER_CHROME_MANIFESTS += [

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

@ -8,14 +8,14 @@
<body>
<div id="slide-overlay">
<!-- The current slide is set by having .active-slide-1, .active-slide-2, etc on #slide element: -->
<div id="slide-container" data-number-of-slides="6" class="active-slide-1">
<div id="slide-container" data-number-of-slides="4" class="active-slide-1">
<div class="slide slide-1">
<!-- Note: all images must be listed in manifest.json.template under web_accessible_resources -->
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-1.png');"></div>
<div class="slide-content">
<div class="slide-content-aligner">
<h1><span><strong>Firefox</strong> Screenshots</span><sup>Beta</sup></h1>
<p data-l10n-id="tourBodyIntro"></p>
<h1><span><strong>Firefox</strong> Screenshots</span></h1>
<p data-l10n-id="tourBodyIntroServerless"></p>
</div>
<p class="onboarding-legal-notice"><!-- Substituted with termsAndPrivacyNotice --></p>
</div>
@ -41,20 +41,6 @@
<p data-l10n-id="tourBodyFullPage"></p>
</div>
</div>
<div class="slide slide-5">
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-5.png');"></div>
<div class="slide-content">
<h1 data-l10n-id="tourHeaderDownloadUpload"></h1>
<p data-l10n-id="tourBodyDownloadUpload"></p>
</div>
</div>
<div class="slide slide-6">
<div class="slide-image" style="background-image: url('MOZ_EXTENSION/icons/onboarding-6.png');"></div>
<div class="slide-content">
<h1 data-l10n-id="tourHeaderAccounts"></h1>
<p data-l10n-id="tourBodyAccounts"></p>
</div>
</div>
<!-- Clickable elements should be buttons for accessibility -->
<button id="skip" data-l10n-id="tourSkip" tabindex=1>Skip</button>
@ -66,8 +52,6 @@
<button class="goto-slide goto-slide-2" data-number="2" tabindex=5></button>
<button class="goto-slide goto-slide-3" data-number="3" tabindex=6></button>
<button class="goto-slide goto-slide-4" data-number="4" tabindex=7></button>
<button class="goto-slide goto-slide-5" data-number="5" tabindex=8></button>
<button class="goto-slide goto-slide-6" data-number="6" tabindex=9></button>
</div>
<!-- FIXME: Need to put in privacy / etc links -->
</div>

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

@ -53,10 +53,13 @@ this.slides = (function() {
doc.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
localizeText(doc);
activateSlide(doc);
// Give the DOM a moment to settle before applying focus
setTimeout(() => {
iframe.contentWindow.focus();
});
resolve();
}), {once: true});
document.body.appendChild(iframe);
iframe.focus();
window.addEventListener("resize", onResize);
});
};

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

@ -79,37 +79,10 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
return (computed && computed.backgroundImage === "none");
}
const isDownloadOnly = exports.isDownloadOnly = function() {
return window.downloadOnly;
const showMyShots = exports.showMyShots = function() {
return window.hasAnyShots;
};
// the download notice is rendered in iframes that match the document height
// or the window height. If parent iframe matches window height, pass in true
function renderDownloadNotice(initAtBottom = false) {
const notice = makeEl("table", "notice");
notice.innerHTML = `
<div class="notice-tooltip">
<p data-l10n-id="downloadOnlyDetails"></p>
<ul>
<li data-l10n-id="downloadOnlyDetailsPrivate"></li>
<li data-l10n-id="downloadOnlyDetailsNeverRemember"></li>
<li data-l10n-id="downloadOnlyDetailsESR"></li>
<li data-l10n-id="downloadOnlyDetailsNoUploadPref"></li>
</ul>
</div>
<tbody>
<tr class="notice-wrapper">
<td class="notice-content" data-l10n-id="downloadOnlyNotice"></td>
<td class="notice-help"></td>
</tr>
<tbody>`;
localizeText(notice);
if (initAtBottom) {
notice.style.bottom = "10px";
}
return notice;
}
function initializeIframe() {
const el = document.createElement("iframe");
el.src = browser.extension.getURL("blank.html");
@ -300,10 +273,10 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
<div class="preview-instructions" data-l10n-id="screenshotInstructions"></div>
<button class="cancel-shot">${browser.i18n.getMessage("cancelScreenshot")}</button>
<div class="myshots-all-buttons-container">
${isDownloadOnly() ? "" : `
${showMyShots() ? `
<button class="myshots-button" tabindex="3" data-l10n-id="myShotsLink"></button>
<div class="spacer"></div>
`}
` : ""}
<button class="visible" tabindex="2" data-l10n-id="saveScreenshotVisibleArea"></button>
<button class="full-page" tabindex="1" data-l10n-id="saveScreenshotFullPage"></button>
</div>
@ -318,7 +291,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
const overlay = this.document.querySelector(".preview-overlay");
localizeText(this.document);
if (!(isDownloadOnly())) {
if (showMyShots()) {
overlay.querySelector(".myshots-button").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onOpenMyShots)));
}
@ -409,22 +382,14 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
data-l10n-title="cancelScreenshot"><img
src="${browser.extension.getURL("icons/cancel.svg")}" /></button>
<button class="highlight-button-copy"
data-l10n-title="copyScreenshot"><img
src="${browser.extension.getURL("icons/copy.svg")}" /></button>
${isDownloadOnly() ?
`<button class="highlight-button-download download-only-button"
data-l10n-title="downloadScreenshot"><img
src="${browser.extension.getURL("icons/download.svg")}"
/>${browser.i18n.getMessage("downloadScreenshot")}</button>` :
`<button class="highlight-button-download"
data-l10n-title="downloadScreenshot"><img
src="${browser.extension.getURL("icons/download.svg")}" /></button>
<button class="preview-button-save"
data-l10n-title="saveScreenshotSelectedArea"><img
src="${browser.extension.getURL("icons/cloud.svg")}"
/>${browser.i18n.getMessage("saveScreenshotSelectedArea")}</button>`
}
data-l10n-title="copyScreenshotTitle"><img
src="${browser.extension.getURL("icons/copy.svg")}" />${browser.i18n.getMessage("copyScreenshot")}</button>
<button class="highlight-button-download"
data-l10n-title="downloadScreenshotTitle"><img
src="${browser.extension.getURL("icons/download-white.svg")}"
/>${browser.i18n.getMessage("downloadScreenshot")}</button>
</div>
<div class="preview-image-wrapper"></div>
</div>
<div class="loader" style="display:none">
<div class="loader-inner"></div>
@ -436,12 +401,6 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.document.documentElement.lang = browser.i18n.getMessage("@@ui_locale");
localizeText(this.document);
const overlay = this.document.querySelector(".preview-overlay");
if (isDownloadOnly()) {
overlay.appendChild(renderDownloadNotice(true));
} else {
overlay.querySelector(".preview-button-save").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onSavePreview)));
}
overlay.querySelector(".highlight-button-copy").addEventListener(
"click", watchFunction(assertIsTrusted(standardOverlayCallbacks.onCopyPreview)));
overlay.querySelector(".highlight-button-download").addEventListener(
@ -471,7 +430,6 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
showLoader() {
this.document.body.querySelector(".preview-image").style.display = "none";
this.document.body.querySelector(".notice").style.display = "none";
this.document.body.querySelector(".loader").style.display = "";
},
@ -642,24 +600,6 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.bgRight.style.height = `${pos.bottom - pos.top}px`;
this.bgRight.style.left = `${pos.right}px`;
this.bgRight.style.width = `calc(100% - ${pos.right}px)`;
// the download notice is injected into an iframe that matches the document size
// in order to reposition it on scroll we need to bind an updated positioning
// function to some window events.
this.repositionDownloadNotice = () => {
if (this.downloadNotice) {
const currentYOffset = window.pageYOffset;
const currentWinBottom = window.innerHeight;
this.downloadNotice.style.top = (currentYOffset + currentWinBottom - 60) + "px";
}
};
if (this.downloadNotice) {
this.downloadNotice.style.top = (pageYOffset + winBottom - 60) + "px";
// event callbacks are delayed 100ms each to keep from overloading things
this.windowChangeStop = this.delayExecution(100, this.repositionDownloadNotice);
window.addEventListener("scroll", watchFunction(assertIsTrusted(this.windowChangeStop)));
window.addEventListener("resize", watchFunction(assertIsTrusted(this.windowChangeStop)));
}
},
// used to eventually move the download-only warning
@ -675,11 +615,7 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
},
remove() {
if (this.downloadNotice) {
window.removeEventListener("scroll", this.windowChangeStop, true);
window.removeEventListener("resize", this.windowChangeStop, true);
}
for (const name of ["el", "bgTop", "bgLeft", "bgRight", "bgBottom", "downloadNotice"]) {
for (const name of ["el", "bgTop", "bgLeft", "bgRight", "bgBottom"]) {
if (name in this) {
util.removeNode(this[name]);
this[name] = null;
@ -702,42 +638,26 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
buttons.appendChild(cancel);
const copy = makeEl("button", "highlight-button-copy");
copy.title = browser.i18n.getMessage("copyScreenshot");
copy.title = browser.i18n.getMessage("copyScreenshotTitle");
const copyImg = makeEl("img");
const copyString = makeEl("span");
copyString.textContent = browser.i18n.getMessage("copyScreenshot");
copyImg.src = browser.extension.getURL("icons/copy.svg");
copy.appendChild(copyImg);
copy.appendChild(copyString);
buttons.appendChild(copy);
let download, save;
if (isDownloadOnly()) {
download = makeEl("button", "highlight-button-download download-only-button");
const downloadImg = makeEl("img");
downloadImg.src = browser.extension.getURL("icons/download.svg");
download.appendChild(downloadImg);
download.append(browser.i18n.getMessage("downloadScreenshot"));
download.title = browser.i18n.getMessage("downloadScreenshot");
} else {
download = makeEl("button", "highlight-button-download");
download.title = browser.i18n.getMessage("downloadScreenshot");
const downloadImg = makeEl("img");
downloadImg.src = browser.extension.getURL("icons/download.svg");
download.appendChild(downloadImg);
save = makeEl("button", "highlight-button-save");
const saveImg = makeEl("img");
saveImg.src = browser.extension.getURL("icons/cloud.svg");
save.appendChild(saveImg);
save.append(browser.i18n.getMessage("saveScreenshotSelectedArea"));
save.title = browser.i18n.getMessage("saveScreenshotSelectedArea");
}
const download = makeEl("button", "highlight-button-download");
const downloadImg = makeEl("img");
downloadImg.src = browser.extension.getURL("icons/download-white.svg");
download.appendChild(downloadImg);
download.append(browser.i18n.getMessage("downloadScreenshot"));
download.title = browser.i18n.getMessage("downloadScreenshotTitle");
buttons.appendChild(download);
if (save) {
buttons.appendChild(save);
}
this.cancel = cancel;
this.download = download;
this.copy = copy;
this.save = save;
boxEl.appendChild(buttons);
for (const name of movements) {
const elTarget = makeEl("div", "mover-target direction-" + name);
@ -754,10 +674,6 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.bgBottom = makeEl("div", "bghighlight");
iframe.document().body.appendChild(this.bgBottom);
iframe.document().body.appendChild(boxEl);
if (isDownloadOnly()) {
this.downloadNotice = renderDownloadNotice();
iframe.document().body.appendChild(this.downloadNotice);
}
this.el = boxEl;
},
@ -838,9 +754,6 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
if (this.el) {
this.el.style.display = "none";
}
if (this.downloadNotice) {
this.downloadNotice.display = "none";
}
},
remove() {
@ -874,22 +787,11 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
};
exports.Preview = {
display(dataUrl, showCropWarning) {
display(dataUrl) {
const img = makeEl("IMG");
const imgBlob = blobConverters.dataUrlToBlob(dataUrl);
img.src = URL.createObjectURL(imgBlob);
iframe.document().querySelector(".preview-image").appendChild(img);
if (showCropWarning && !(isDownloadOnly())) {
const imageCroppedEl = makeEl("table", "notice middle");
imageCroppedEl.innerHTML = `<tbody>
<tr class="notice-wrapper">
<td class="notice-content"></td>
</tr>
</tbody>`;
const contentCell = imageCroppedEl.getElementsByTagName("td");
contentCell[0].textContent = browser.i18n.getMessage("imageCropPopupWarning", buildSettings.maxImageHeight);
iframe.document().querySelector(".preview-buttons").appendChild(imageCroppedEl);
}
iframe.document().querySelector(".preview-image-wrapper").appendChild(img);
},
};

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

@ -911,13 +911,8 @@ this.uicontrol = (function() {
if ((event.key || event.code) === "Enter"
&& getState.state === "selected"
&& ui.iframe.document().activeElement.tagName === "BODY") {
if (ui.isDownloadOnly()) {
sendEvent("download-shot", "keyboard-enter");
downloadShot();
} else {
sendEvent("save-shot", "keyboard-enter");
shooter.takeShot("selection", selectedPos);
}
sendEvent("download-shot", "keyboard-enter");
downloadShot();
}
}