Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
Show loader animation on truncated full page download/copy. (#3861)
Browse files Browse the repository at this point in the history
  • Loading branch information
chenba committed Feb 8, 2018
1 parent 75f6a38 commit 6fa7f3a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 56 deletions.
21 changes: 20 additions & 1 deletion addon/webextension/background/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* globals selectorLoader, analytics, communication, catcher, log, makeUuid, auth, senderror, startBackground, blobConverters */
/* globals selectorLoader, analytics, communication, catcher, log, makeUuid, auth, senderror, startBackground, blobConverters buildSettings */

"use strict";

Expand Down Expand Up @@ -206,6 +206,25 @@ this.main = (function() {
return null;
});

// This is used for truncated full page downloads and copy to clipboards.
// Those longer operations need to display an animated spinner/loader, so
// it's preferable to perform toDataURL() in the background.
communication.register("canvasToDataURL", (sender, imageData) => {
const canvas = document.createElement("canvas");
canvas.width = imageData.width;
canvas.height = imageData.height;
canvas.getContext("2d").putImageData(imageData, 0, 0);
let dataUrl = canvas.toDataURL();
if (buildSettings.pngToJpegCutoff && dataUrl.length > buildSettings.pngToJpegCutoff) {
const jpegDataUrl = canvas.toDataURL("image/jpeg");
if (jpegDataUrl.length < dataUrl.length) {
// Only use the JPEG if it is actually smaller
dataUrl = jpegDataUrl;
}
}
return dataUrl;
});

communication.register("copyShotToClipboard", (sender, blob) => {
return blobConverters.blobToArray(blob).then(buffer => {
return browser.clipboard.setImageData(
Expand Down
16 changes: 2 additions & 14 deletions addon/webextension/background/takeshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ this.takeshot = (function() {
if (!shot.clipNames().length) {
// canvas.drawWindow isn't available, so we fall back to captureVisibleTab
capturePromise = screenshotPage(selectedPos, scroll).then((dataUrl) => {
imageBlob = buildSettings.uploadBinary ? blobConverters.dataUrlToBlob(dataUrl) : null;
shot.addClip({
createdDate: Date.now(),
image: {
url: "data:",
url: buildSettings.uploadBinary ? "" : dataUrl,
captureType,
text: captureText,
location: selectedPos,
Expand All @@ -33,17 +34,6 @@ this.takeshot = (function() {
});
});
}
let convertBlobPromise = Promise.resolve();
if (buildSettings.uploadBinary && !imageBlob) {
const clipImage = shot.getClip(shot.clipNames()[0]).image;
imageBlob = blobConverters.dataUrlToBlob(clipImage.url);
clipImage.url = "";
} else if (!buildSettings.uploadBinary && imageBlob) {
convertBlobPromise = blobConverters.blobToDataUrl(imageBlob).then((dataUrl) => {
shot.getClip(shot.clipNames()[0]).image.url = dataUrl;
});
imageBlob = null;
}
const shotAbTests = {};
const abTests = auth.getAbTests();
for (const testName of Object.keys(abTests)) {
Expand All @@ -55,8 +45,6 @@ this.takeshot = (function() {
shot.abTests = shotAbTests;
}
return catcher.watchPromise(capturePromise.then(() => {
return convertBlobPromise;
}).then(() => {
if (buildSettings.uploadBinary) {
const blobToUrlPromise = blobConverters.blobToDataUrl(imageBlob);
return thumbnailGenerator.createThumbnailBlobFromPromise(shot, blobToUrlPromise);
Expand Down
99 changes: 60 additions & 39 deletions addon/webextension/selector/shooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
supportsDrawWindow = !!ctx.drawWindow;
})();

const screenshotPage = exports.screenshotPage = function(selectedPos, captureType) {
if (!supportsDrawWindow) {
return null;
}
function captureToCanvas(selectedPos, captureType) {
const height = selectedPos.bottom - selectedPos.top;
const width = selectedPos.right - selectedPos.left;
const canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
Expand All @@ -61,6 +58,14 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
}
ui.iframe.hide();
ctx.drawWindow(window, selectedPos.left, selectedPos.top, width, height, "#fff");
return canvas;
}

const screenshotPage = exports.screenshotPage = function(selectedPos, captureType) {
if (!supportsDrawWindow) {
return null;
}
const canvas = captureToCanvas(selectedPos, captureType);
const limit = buildSettings.pngToJpegCutoff;
let dataUrl = canvas.toDataURL();
if (limit && dataUrl.length > limit) {
Expand All @@ -73,6 +78,18 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
return dataUrl;
};

function screenshotPageAsync(selectedPos, captureType) {
if (!supportsDrawWindow) {
return Promise.resolve(null);
}
const canvas = captureToCanvas(selectedPos, captureType);
ui.iframe.showLoader();
const width = selectedPos.right - selectedPos.left;
const height = selectedPos.bottom - selectedPos.top;
const imageData = canvas.getContext("2d").getImageData(0, 0, width, height);
return callBackground("canvasToDataURL", imageData);
}

let isSaving = null;

exports.takeShot = function(captureType, selectedPos, url) {
Expand Down Expand Up @@ -109,12 +126,12 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
let type = blobConverters.getTypeFromDataUrl(dataUrl);
type = type ? type.split("/", 2)[1] : null;
if (dataUrl) {
imageBlob = blobConverters.dataUrlToBlob(dataUrl);
imageBlob = buildSettings.uploadBinary ? blobConverters.dataUrlToBlob(dataUrl) : null;
shotObject.delAllClips();
shotObject.addClip({
createdDate: Date.now(),
image: {
url: "data:",
url: buildSettings.uploadBinary ? "" : dataUrl,
type,
captureType,
text: captureText,
Expand Down Expand Up @@ -164,34 +181,36 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
};

exports.downloadShot = function(selectedPos, previewDataUrl) {
const dataUrl = previewDataUrl || screenshotPage(selectedPos);
let promise = Promise.resolve(dataUrl);
if (!dataUrl) {
promise = callBackground(
"screenshotPage",
selectedPos.asJson(),
{
scrollX: window.scrollX,
scrollY: window.scrollY,
innerHeight: window.innerHeight,
innerWidth: window.innerWidth
const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : screenshotPageAsync(selectedPos, "fullPage");
catcher.watchPromise(shotPromise.then(dataUrl => {
let promise = Promise.resolve(dataUrl);
if (!dataUrl) {
promise = callBackground(
"screenshotPage",
selectedPos.asJson(),
{
scrollX: window.scrollX,
scrollY: window.scrollY,
innerHeight: window.innerHeight,
innerWidth: window.innerWidth
});
}
catcher.watchPromise(promise.then((dataUrl) => {
let type = blobConverters.getTypeFromDataUrl(dataUrl);
type = type ? type.split("/", 2)[1] : null;
shotObject.delAllClips();
shotObject.addClip({
createdDate: Date.now(),
image: {
url: dataUrl,
type,
location: selectedPos
}
});
}
catcher.watchPromise(promise.then((dataUrl) => {
let type = blobConverters.getTypeFromDataUrl(dataUrl);
type = type ? type.split("/", 2)[1] : null;
shotObject.delAllClips();
shotObject.addClip({
createdDate: Date.now(),
image: {
url: dataUrl,
type,
location: selectedPos
}
});
ui.triggerDownload(dataUrl, shotObject.filename);
uicontrol.deactivate();
}));
ui.triggerDownload(dataUrl, shotObject.filename);
uicontrol.deactivate();
}));
}))
};

let copyInProgress = null;
Expand All @@ -212,12 +231,14 @@ this.shooter = (function() { // eslint-disable-line no-unused-vars
copyInProgress = null;
}
}
const dataUrl = previewDataUrl || screenshotPage(selectedPos);
const blob = blobConverters.dataUrlToBlob(dataUrl);
catcher.watchPromise(callBackground("copyShotToClipboard", blob).then(() => {
uicontrol.deactivate();
unsetCopyInProgress();
}, unsetCopyInProgress));
const shotPromise = previewDataUrl ? Promise.resolve(previewDataUrl) : screenshotPageAsync(selectedPos, "fullPage");
catcher.watchPromise(shotPromise.then(dataUrl => {
const blob = blobConverters.dataUrlToBlob(dataUrl);
catcher.watchPromise(callBackground("copyShotToClipboard", blob).then(() => {
uicontrol.deactivate();
unsetCopyInProgress();
}, unsetCopyInProgress));
}));
};

exports.sendEvent = function(...args) {
Expand Down
16 changes: 16 additions & 0 deletions addon/webextension/selector/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,9 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
}
</div>
</div>
<div class="loader" style="display:none">
<div class="loader-inner"></div>
</div>
</div>
</body>`;
installHandlerOnDocument(this.document);
Expand Down Expand Up @@ -460,6 +463,12 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.element.focus();
},

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 = "";
},

remove() {
this.hide();
util.removeNode(this.element);
Expand All @@ -486,6 +495,13 @@ this.ui = (function() { // eslint-disable-line no-unused-vars
this.currentIframe.unhide();
},

showLoader() {
if (this.currentIframe.showLoader) {
this.currentIframe.showLoader();
this.currentIframe.unhide();
}
},

getElementFromPoint(x, y) {
return this.currentIframe.getElementFromPoint(x, y);
},
Expand Down
4 changes: 2 additions & 2 deletions addon/webextension/selector/uicontrol.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,15 @@ this.uicontrol = (function() {
},
onDownloadPreview: () => {
sendEvent(`download-${captureType.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}`, "download-preview-button");
// Downloaded shots don't have dimension limits
const previewDataUrl = (captureType === "fullPageTruncated") ? null : dataUrl;
// Downloaded shots don't have dimension limits
removeDimensionLimitsOnFullPageShot();
shooter.downloadShot(selectedPos, previewDataUrl);
},
onCopyPreview: () => {
sendEvent(`copy-${captureType.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()}`, "copy-preview-button");
// Copied shots don't have dimension limits
const previewDataUrl = (captureType === "fullPageTruncated") ? null : dataUrl;
// Copied shots don't have dimension limits
removeDimensionLimitsOnFullPageShot();
shooter.copyShot(selectedPos, previewDataUrl);
}
Expand Down

0 comments on commit 6fa7f3a

Please # to comment.