From 0246799429c735eeb1104c0730da22ad5dc8cf9e Mon Sep 17 00:00:00 2001
From: Jaifroid
Date: Tue, 14 Feb 2023 18:13:36 +0000
Subject: [PATCH] Provide indication of archive download progress in Electron
#365 (#366)
---
main.js | 92 ++++++++++++++++++++++++++--------------
www/js/app.js | 14 ++++++
www/js/lib/kiwixServe.js | 17 +++++---
3 files changed, 85 insertions(+), 38 deletions(-)
diff --git a/main.js b/main.js
index d9e7656d..d9e67e1f 100644
--- a/main.js
+++ b/main.js
@@ -7,30 +7,30 @@ app.commandLine.appendSwitch("enable-experimental-web-platform-features");
const contextMenu = require('electron-context-menu');
contextMenu({
- labels: {
- cut: 'Cut',
- copy: 'Copy',
- paste: 'Paste',
- save: 'Save Image',
- saveImageAs: 'Save Image As…',
- copyLink: 'Copy Link',
- saveLinkAs: 'Save Link As…',
- inspect: 'Inspect Element'
- },
- prepend: () => { },
- append: () => { },
- showCopyImageAddress: true,
- showSaveImageAs: true,
- showInspectElement: true,
- showSaveLinkAs: true,
- cut: true,
- copy: true,
- paste: true,
- save: true,
- saveImageAs: true,
- copyLink: true,
- saveLinkAs: true,
- inspect: true
+ labels: {
+ cut: 'Cut',
+ copy: 'Copy',
+ paste: 'Paste',
+ save: 'Save Image',
+ saveImageAs: 'Save Image As…',
+ copyLink: 'Copy Link',
+ saveLinkAs: 'Save Link As…',
+ inspect: 'Inspect Element'
+ },
+ prepend: () => { },
+ append: () => { },
+ showCopyImageAddress: true,
+ showSaveImageAs: true,
+ showInspectElement: true,
+ showSaveLinkAs: true,
+ cut: true,
+ copy: true,
+ paste: true,
+ save: true,
+ saveImageAs: true,
+ copyLink: true,
+ saveLinkAs: true,
+ inspect: true
});
// This is used to set capabilities of the app: protocol in onready event below
@@ -62,10 +62,10 @@ function createWindow() {
nodeIntegrationInWorker: true
}
});
-
+
// DEV: Uncomment this to open dev tools early in load process
// mainWindow.webContents.openDevTools();
-
+
mainWindow.loadFile('www/index.html');
}
@@ -74,7 +74,7 @@ function registerListeners() {
dialog.showOpenDialog(mainWindow, {
filters: [
{ name: 'ZIM Archives', extensions: ['zim', 'zimaa'] }
- ],
+ ],
properties: ['openFile']
}).then(function ({ filePaths }) {
if (filePaths.length) {
@@ -95,6 +95,36 @@ function registerListeners() {
console.log('Auto-update check request received...\n');
autoUpdater.checkForUpdates();
});
+ // Registers listener for download events
+ mainWindow.webContents.session.on('will-download', (event, item, webContents) => {
+ // Set the save path, making Electron not to prompt a save dialog.
+ // item.setSavePath('/tmp/save.pdf')
+ let receivedBytes = 0;
+ item.on('updated', (event, state) => {
+ if (state === 'interrupted') {
+ console.log('Download is interrupted but can be resumed');
+ mainWindow.webContents.send('dl-received', state);
+ } else if (state === 'progressing') {
+ if (item.isPaused()) {
+ console.log('Download is paused');
+ mainWindow.webContents.send('dl-received', 'paused');
+ } else {
+ let newReceivedBytes = item.getReceivedBytes();
+ if (newReceivedBytes - receivedBytes < 250000) return;
+ receivedBytes = newReceivedBytes;
+ mainWindow.webContents.send('dl-received', receivedBytes);
+ }
+ }
+ });
+ item.once('done', (event, state) => {
+ if (state === 'completed') {
+ console.log('Download successful');
+ } else {
+ console.log(`Download failed: ${state}`);
+ }
+ mainWindow.webContents.send('dl-received', state);
+ });
+ });
}
app.whenReady().then(() => {
@@ -122,11 +152,11 @@ app.whenReady().then(() => {
// Create the new window
createWindow();
registerListeners();
-
+
var appName = app.getName();
console.log('App name: ' + appName);
-
+
// setTimeout(function () {
// // Don't auto update if the app is a packaged app
// if (/wikimed|wikivoyage/i.test(appName)) {
@@ -141,13 +171,13 @@ app.whenReady().then(() => {
autoUpdater.on('update-downloaded', function (info) {
mainWindow.webContents.send('update-available', info);
});
-
+
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
-
+
});
// Quit when all windows are closed.
diff --git a/www/js/app.js b/www/js/app.js
index 1e5c8ef4..ba777b89 100644
--- a/www/js/app.js
+++ b/www/js/app.js
@@ -912,6 +912,20 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
console.log('Upgrade is available:' + data);
uiUtil.showUpgradeReady(data.version, 'install');
});
+ var serverResponse = document.getElementById('serverResponse');
+ electronAPI.on('dl-received', function (data) {
+ // console.warn('Download in progress: ' + data);
+ serverResponse.style.display = 'inline';
+ var colour = data === 'completed' ? 'green' : isNaN(data) ? 'red' : 'goldenrod';
+ serverResponse.style.setProperty('color', colour, 'important');
+ serverResponse.innerHTML = 'Download progress: ' + data;
+ if (data === 'completed') setTimeout(function () {
+ serverResponse.style.removeProperty('color');
+ if (document.getElementById('downloadLinks').style.display === 'none') {
+ serverResponse.style.display = 'none';
+ }
+ }, 10000);
+ });
}
// Check for GitHub and Electron updates
diff --git a/www/js/lib/kiwixServe.js b/www/js/lib/kiwixServe.js
index 7e10fd33..39ed1213 100644
--- a/www/js/lib/kiwixServe.js
+++ b/www/js/lib/kiwixServe.js
@@ -340,6 +340,9 @@ define([], function () {
var downloadLinks = document.getElementById('downloadLinks');
var serverResponse = document.getElementById('serverResponse');
+
+ // Used to decide the target for download links
+ var target = /Electron/.test(params.appType) ? '' : ' target="_blank"';
// DEV: If you support more packaged files, add to this list
var regexpFilter = /_medicine|mdwiki_/.test(params.packagedFile) ? /^(?!.+(_medicine_|mdwiki_))[^_\n\r]+_([^_\n\r]+)_.+\.zi[mp].+$\s+/mig : null;
@@ -432,12 +435,12 @@ define([], function () {
var body = document.getElementById('dl-panel-body');
var bodyDoc = '<< Back to list of files
\r\n';
bodyDoc += 'Directly download ZIM archive:
' +
- '' + requestedURL + '
' +
+ '' + requestedURL + '
' +
(altURL ? 'Possible mirror:
' +
- '' + altURL + '
' : '') +
+ '' + altURL + '
' : '') +
(~URL.indexOf(params.kiwixHiddenDownloadLink) ? '' :
'Download with bittorrent:
' +
- '' + torrentURL + '
');
+ '' + torrentURL + '
');
body.outerHTML = body.outerHTML.replace(/]*)>[\s\S]*?<\/pre>/i, '' + bodyDoc + '
');
downloadLinks.innerHTML = downloadLinks.innerHTML.replace(/Index\s+of/ig, "File in");
downloadLinks.innerHTML = downloadLinks.innerHTML.replace(/panel-success/i, "panel-warning");
@@ -456,7 +459,7 @@ define([], function () {
downloadLinks.innerHTML = '' +
'Unable to access the server. Please see message below for reason.
' +
'You can either try again or else open this link in a new browser window:
' +
- '' + params.kiwixDownloadLink + '
';
+ '' + params.kiwixDownloadLink + '
';
}
downloadLinks.style.display = "block";
}
@@ -473,7 +476,7 @@ define([], function () {
var megabytes$ = megabytes.toString().split('').reverse().join('').replace(/(\d{3}(?!.*\.|$))/g, '$1,').split('').reverse().join('');
doc = "";
for (var i = 1; i < linkArray.length; i++) { //NB we'ere intentionally discarding first link to kiwix.org (not to zim)
- doc += linkArray[i].replace(/]*>([^<]*)<\/url>/i, '$1\r\n');
+ doc += linkArray[i].replace(/]*>([^<]*)<\/url>/i, '$1\r\n');
}
var headerDoc = 'We found the following links to your file:';
var bodyDoc = '<< Back to list of files
\r\n';
@@ -484,9 +487,9 @@ define([], function () {
bodyDoc += 'File size is ' + (megabytes ? megabytes$ + 'MB' : 'unknown') + '' + (size ? ' (' + size + ' bytes)' : '') + '\r\n';
bodyDoc += 'New! Preview this archive in your browser before downloading it
';
if (megabytes > 200) bodyDoc += 'Consider using BitTorrent to download file:
\r\n\r\n';
if (megabytes > 4000 && /\.zim\.meta4$/i.test(URL)) {
bodyDoc += 'If you plan to store this archive on a drive/microSD formatted as FAT32 (most are not), then you will need to download the file on a PC and split it into chunks less than 4GB: see Download a ZIM archive.
\r\n';