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';