Enable autoload of packaged file

Former-commit-id: 7d4d3dc16728a2fded8b25ca1e2f2368e00c17c2 [formerly df72001df9e2003281d0b650e37555b339e4bf90]
Former-commit-id: ba49c446544a4f4e1e6e0c1f40fc03507723a3a9
This commit is contained in:
Jaifroid 2019-07-29 00:03:03 +01:00
parent ad29aa660b
commit 065b2c450b
7 changed files with 129 additions and 42 deletions

8
index.html Normal file
View File

@ -0,0 +1,8 @@
<!doctype html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=www/index.html">
<title>Redirection to index.html</title>
<body>
</body>
</html>

32
main.js
View File

@ -11,7 +11,7 @@ protocol.registerSchemesAsPrivileged([{
scheme: 'app',
privileges: {
standard: true,
secure: true,
//secure: true,
allowServiceWorkers: true,
supportFetchAPI: true
}
@ -25,16 +25,22 @@ function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600
//, webPreferences: {
// preload: path.join(__dirname, 'preload.js')
// }
height: 600,
webPreferences: {
// nodeIntegration: false,
// contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
// preload: __dirname + '/www/preload.js'
, webSecurity: false
// preload: 'app://www/preload.js'
}
});
// and load the index.html of the app.
mainWindow.loadURL('app://www/index.html');
// DEV: If you need Service Worker more than you need document.cookie, load app like this:
// mainWindow.loadFile('www/index.html');
// mainWindow.loadFile('index.html');
// DEV: Enable code below to check cookies saved by app in console log
// mainWindow.webContents.on('did-finish-load', function() {
// mainWindow.webContents.session.cookies.get({}, (error, cookies) => {
@ -54,19 +60,29 @@ function createWindow() {
});
}
// let dirnameParts = __dirname.match(/[^\/\\]+(?:[\/\\]|$)/g);
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
protocol.registerFileProtocol('app', (request, callback) => {
//protocol.registerHttpProtocol('app', (request, callback) => {
const url = request.url.substr(6);
let url = request.url.replace(/^app:\/\/([./]*)(.*)$/, function(_p0, relPath, linkUrl) {
// // @TODO: Complete routine to recognize relative links below (../)
// let i = 0;
// let parsedPath = relPath.replace(/\.\.\//g, function(p0) {
// i++;
// });
return relPath + linkUrl;
});
callback({
path: path.normalize(`${__dirname}/${url}`)
// url: 'file://' + path.normalize(`${__dirname}/${url}`),
// method: 'GET'
});
console.log(path.normalize(`${__dirname}/${url}` + ':' + url));
// console.log(path.normalize(`${__dirname}/${url}` + ':' + url));
}, (error) => {
if (error) console.error('Failed to register protocol');
});

View File

@ -1,12 +1,36 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text;
}
'use strict';
// const { remote } = require('electron');
// var win = remote.getCurrentWebContents();
const { open, read, close, stat } = require('fs');
window.fs = {
open: open,
read: read,
close: close,
stat: stat
};
// window.Buffer = Buffer;
// console.log(win.session.cookies);
// win.session.cookies.get({}, (error, cookies) => {
// console.log('Cookies:' + cookies);
// });
console.log("Looks like preload launched...");
// window.addEventListener('DOMContentLoaded', () => {
// const replaceText = (selector, text) => {
// const element = document.getElementById(selector)
// if (element) element.innerText = text;
// }
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type]);
}
});
// for (const type of ['chrome', 'node', 'electron']) {
// replaceText(`${type}-version`, process.versions[type]);
// }
// });

View File

@ -1,3 +0,0 @@
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All of the Node.js APIs are available in this process.

View File

@ -403,9 +403,12 @@
<div id="returntoArticle" class="returntoArticle" style="text-align:center;padding-top:20px;"></div>
<div class="row">
<h2 style="margin-top:0;">Configuration</h2>
<p>
Packaged ZIM archive: <b><span class="fileVersion"></span></b>
<button style="display:none;" id="reloadPackagedArchive" type="button" class="btn btn-primary btn-xs">Reload</button>
</p>
<p id="currentArchive" style="display: none;"></p>
<p id="downloadLinksText">This application needs a ZIM archive to work.<br />
<a id="otherLangs" href="#btnRescanDeviceStorage"><i>Download one from the <b>Archive Library</b>.</i></a></p><p></p>
<p id="downloadLinksText"><a id="otherLangs" href="#btnRescanDeviceStorage">Get more archives (in other languages)</a></p><p></p>
<p id="moreInfo">For more information see <a href="#" onclick="document.getElementById('btnAbout').click();">About tab <span class="glyphicon glyphicon-info-sign"></span></a> (top right)</p>
</div>
<div id="hideFileSelectors">
@ -469,9 +472,9 @@
<div class="row">
<h3>Download links</h3>
<div id="libraryArea" class="col-xs-12">
<p>
Files can be very large, <b>do not attempt to download using mobile data!</b>
</p>
<p>
Files can be very large, <b>do not attempt to download using mobile data!</b>
</p>
<table>
<tr>
<td><input id="downloadTrigger" type="button" class="btn btn-primary" value="Open library" style="float:left; margin-right:1em;" /></td>
@ -583,9 +586,9 @@
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="returntoArticle" style="text-align:center;"></div>
<div>
<div class="row">

View File

@ -98,7 +98,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
}
$(document).ready(resizeIFrame);
$(window).resize(function() {
resizeIFrame;
resizeIFrame();
// We need to load any images exposed by the resize
var scrollFunc = document.getElementById('articleContent').contentWindow;
scrollFunc = scrollFunc ? scrollFunc.onscroll : null;
@ -1351,17 +1351,31 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
return new abstractFilesystemAccess.StorageFirefoxOS(s);
});
}
if (storages !== null && storages.length > 0 ||
typeof Windows !== 'undefined' && typeof Windows.Storage !== 'undefined') {
typeof Windows !== 'undefined' && typeof Windows.Storage !== 'undefined' ||
typeof window.fs !== 'undefined') {
// Make a fake first access to device storage, in order to ask the user for confirmation if necessary.
// This way, it is only done once at this moment, instead of being done several times in callbacks
// After that, we can start looking for archives
//storages[0].get("fake-file-to-read").then(searchForArchivesInPreferencesOrStorage,
if (!params.pickedFile) {
searchForArchivesInPreferencesOrStorage();
} else {
} else if (typeof window.fs === 'undefined') {
processPickedFileUWP(params.pickedFile);
} else {
// We're in an Electron app with a packaged file that we need to read from the node File System
console.log("Loading packaged ZIM for Electron...");
// Create a fake File object (this avoids extensive patching of later code)
var file = {};
file.name = params.packagedFile;
// @TODO: Use fs.stat to query the file size
file.size = 824209647;
// @TODO: Create a params.filePath in init.js
file.path = 'archives';
file.readMode = 'electron';
setLocalArchiveFromFileList([file]);
params.pickedFile = file;
document.getElementById('hideFileSelectors').style.display = params.showFileSelectors ? 'inline' : 'none';
}
} else {
// If DeviceStorage is not available, we display the file select components
@ -1799,6 +1813,13 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
params.pickedFolder = params.localStorage;
scanUWPFolderforArchives(params.localStorage);
if (!params.rescan) setLocalArchiveFromArchiveList(params.storedFile);
} else if (typeof window.fs !== 'undefined') {
// We're in an Electron packaged app
params.storedFile = params.packagedFile || '';
if (!params.rescan) {
if (params.showFileSelectors) $('input:checkbox[name=displayFileSelectors]').click();
}
setLocalArchiveFromFileList([params.pickedFile]);
}
}
@ -1807,6 +1828,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'images', 'cooki
*/
function setLocalArchiveFromFileSelect() {
setLocalArchiveFromFileList(document.getElementById('archiveFilesLegacy').files);
params.rescan = false;
}
/**

View File

@ -20,6 +20,7 @@
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/
'use strict';
define(['q'], function (q) {
/**
@ -204,21 +205,37 @@ define(['q'], function (q) {
/**
* Reads a Uint8Array from the given file starting at byte offset begin and
* for given size.
* @param {File} file
* @param {Integer} begin
* @param {Integer} size
* @param {File} file The file to read
* @param {Integer} begin The first byte in the file to read
* @param {Integer} size The number of bytes to read
* @returns {Promise} Promise
*/
function readFileSlice(file, begin, size) {
var deferred = q.defer();
var reader = new FileReader();
reader.onload = function (e) {
deferred.resolve(new Uint8Array(e.target.result));
};
reader.onerror = reader.onabort = function (e) {
deferred.reject(e);
};
reader.readAsArrayBuffer(file.slice(begin, begin + size));
if (file.readMode === 'electron') {
// We are reading a packaged file and have to use Electron fs.read (so we don't have to pick the file)
var buffer = new Uint8Array(size);
// @TODO: Add errorchecking to electron routine
fs.open(file.path + '/' + file.name, 'r', function (err, fd) {
fs.read(fd, buffer, 0, size, begin, function (err, bytesRead, data) {
deferred.resolve(data);
// console.log(buffer.toString('utf8'));
fs.close(fd, function (err) {
if (err) console.log('Could not close file...', err);
});
});
});
} else {
// We are reading a picked file, so use vanilla JS methods
var reader = new FileReader();
reader.onload = function (e) {
deferred.resolve(new Uint8Array(e.target.result));
};
reader.onerror = reader.onabort = function (e) {
deferred.reject(e);
};
reader.readAsArrayBuffer(file.slice(begin, begin + size));
}
return deferred.promise;
}