mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-09 04:06:27 -04:00
Incorporate custom update notifier for all apps
Former-commit-id: a81d4282f81cae221ec27576e4ee6b5971481ade [formerly 2d0dc3ef5a0e5d014c14438f767e7742cbcecb7c [formerly 81710ec0493e9f2727baa8bc2eeaa3511229a232]] Former-commit-id: 751684742a550c7d8ca5e057390df773d27cab24 [formerly 2652298d2a974e213cbf899f1140b3dd1938aa89] Former-commit-id: d622327206178622525a611667bec2acc7761e56
This commit is contained in:
parent
99e9cdb360
commit
3a059ad0ff
@ -738,7 +738,7 @@
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="allowInternetAccess" id="allowInternetAccessCheck">
|
||||
<span class="checkmark"></span>
|
||||
<b>Allow Internet access?</b>
|
||||
<b>Allow Internet access?</b> <span id="updateStatus">(and check for updates)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div id="downloadLinks" style="display: none;"></div>
|
||||
|
@ -26,8 +26,8 @@
|
||||
// This uses require.js to structure javascript:
|
||||
// http://requirejs.org/docs/api.html#define
|
||||
|
||||
define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images', 'settingsStore', 'transformStyles', 'kiwixServe'],
|
||||
function ($, zimArchiveLoader, uiUtil, util, utf8, cache, images, settingsStore, transformStyles, kiwixServe) {
|
||||
define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images', 'settingsStore', 'transformStyles', 'kiwixServe', 'updater'],
|
||||
function ($, zimArchiveLoader, uiUtil, util, utf8, cache, images, settingsStore, transformStyles, kiwixServe, updater) {
|
||||
|
||||
/**
|
||||
* The delay (in milliseconds) between two "keepalive" messages
|
||||
@ -866,6 +866,27 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
|
||||
});
|
||||
}
|
||||
|
||||
// Check for GitHub updates
|
||||
function checkUpdateServer() {
|
||||
if (!params.allowInternetAccess) {
|
||||
console.log("The update check was blocked because the user has not allowed Internet access.")
|
||||
return;
|
||||
}
|
||||
updater.getLatestUpdates(function (tag, url, releases) {
|
||||
var updateSpan = document.getElementById('updateStatus');
|
||||
if (!tag) {
|
||||
updateSpan.innerHTML = '[ <b><i>App is up to date</i></b> ]';
|
||||
console.log('No new update was found.');
|
||||
return;
|
||||
}
|
||||
console.log('We found this update: [' + tag + '] ' + url, releases);
|
||||
updateSpan.innerHTML = '[ <b><i><a href="#alertBoxPersistent">New update!</a></i></b> ]';
|
||||
uiUtil.showUpgradeReady(tag.replace(/^v/, ''), 'download', url);
|
||||
});
|
||||
}
|
||||
// Do check on startup
|
||||
setTimeout(checkUpdateServer, 15000);
|
||||
|
||||
function setActiveBtn(activeBtn) {
|
||||
document.getElementById('btnHome').classList.remove("active");
|
||||
document.getElementById('btnRandomArticle').classList.remove("active");
|
||||
@ -1125,7 +1146,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
|
||||
setContentInjectionMode(this.value);
|
||||
// If we're in a PWA UWP app, warn the user that this does not disable the PWA
|
||||
if (this.value === 'jquery' && /^http/i.test(window.location.protocol) && /UWP\|PWA/.test(params.appType) &&
|
||||
settingsStore.getItem('allowInternetAccess') === 'true') {
|
||||
params.allowInternetAccess === 'true') {
|
||||
uiUtil.systemAlert(
|
||||
'<p>Please note that switching content injection mode does not revert to local code.</p>' +
|
||||
'<p>If you wish to exit the PWA, you will need to turn off "Allow Internet access?" above.</p>'
|
||||
@ -1188,8 +1209,11 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
|
||||
});
|
||||
}
|
||||
}
|
||||
settingsStore.setItem('allowInternetAccess', false, Infinity);
|
||||
} else {
|
||||
// We can check for updates if the user has allowed Internet access
|
||||
checkUpdateServer();
|
||||
}
|
||||
settingsStore.setItem('allowInternetAccess', params.allowInternetAccess, Infinity);
|
||||
});
|
||||
$('input:checkbox[name=cssCacheMode]').on('change', function (e) {
|
||||
params.cssCache = this.checked ? true : false;
|
||||
|
@ -99,7 +99,7 @@ params['alphaChar'] = getSetting('alphaChar') || 'A'; //Set default start of alp
|
||||
params['omegaChar'] = getSetting('omegaChar') || 'Z'; //Set default end of alphabet string
|
||||
params['contentInjectionMode'] = getSetting('contentInjectionMode') || ((navigator.serviceWorker && !/^(ms-appx-web:)$/i.test(window.location.protocol)
|
||||
&& !/Android/.test(params.appType) && !window.nw) ? 'serviceworker' : 'jquery'); // Deafault to SW mode if the browser supports it
|
||||
params['allowInternetAccess'] = getSetting('allowInternetAccess');
|
||||
params['allowInternetAccess'] = getSetting('allowInternetAccess') !== null ? getSetting('allowInternetAccess') : true;
|
||||
params['openExternalLinksInNewTabs'] = getSetting('openExternalLinksInNewTabs') !== null ? getSetting('openExternalLinksInNewTabs') : true; // Parameter to turn on/off opening external links in new tab
|
||||
params['windowOpener'] = getSetting('windowOpener'); // 'tab|window|false' A setting that determines whether right-click/long-press of a ZIM link opens a new window/tab
|
||||
params['rightClickType'] = getSetting('rightClickType'); // 'single|double|false' A setting that determines whether a single or double right-click is used to open a new window/tab
|
||||
|
@ -674,17 +674,19 @@ define(rqDef, function(util) {
|
||||
/**
|
||||
* Shows that an upgrade is ready to install
|
||||
* @param {String} ver The version of the upgrade
|
||||
* @param {String} type Either 'load' or 'install' according to the type of upgrade
|
||||
* @param {String} type Either 'load', 'install' or 'download' according to the type of upgrade
|
||||
* @param {String} url An optional download URL
|
||||
*/
|
||||
function showUpgradeReady(ver, type) {
|
||||
function showUpgradeReady(ver, type, url) {
|
||||
params.upgradeNeeded = true;
|
||||
document.getElementById('alertBoxPersistent').innerHTML =
|
||||
'<div id="upgradeAlert" class="alert alert-info alert-dismissible">\n' +
|
||||
' <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>\n' +
|
||||
' <span id="persistentMessage"></span>\n' +
|
||||
'</div>\n';
|
||||
document.getElementById('persistentMessage').innerHTML = 'Version ' + ver + ' is ready to '
|
||||
+ type + '! (Re-launch app to ' + type + '.)';
|
||||
document.getElementById('persistentMessage').innerHTML = 'Version ' + ver +
|
||||
(url ? ' is available to ' + type + '! Go to <a href="' + url + '" style="color:white;" target="_blank">' + url + '</a>'
|
||||
: ' is ready to ' + type + '! (Re-launch app to ' + type + '.)');
|
||||
}
|
||||
|
||||
/**
|
||||
|
114
www/js/lib/updater.js
Normal file
114
www/js/lib/updater.js
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
* updater.js : Functions for checking and initiating app updtes
|
||||
*
|
||||
* Copyright 2013-2022 Jaifroid, Mossroy and contributors
|
||||
* License GPL v3:
|
||||
*
|
||||
* This file is part of Kiwix.
|
||||
*
|
||||
* Kiwix is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Kiwix is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
define(['uiUtil'], function (uiUtil) {
|
||||
|
||||
/**
|
||||
* The update server configuration
|
||||
*/
|
||||
params.updateServer = {
|
||||
url: 'https://api.github.com/repos/kiwix/kiwix-js-windows/',
|
||||
releases: 'releases'
|
||||
};
|
||||
|
||||
// A RegExp prototype string to match the current app's releases
|
||||
const baseApp = (params.packagedFile && /wikivoyage/.test(params.packagedFile)) ? 'wikivoyage' :
|
||||
(params.packagedFile && /wikmed|mdwiki/.test(params.packagedFile)) ? 'wikimed' :
|
||||
'windows|electron|kiwixwebapp_'; // Default value
|
||||
|
||||
// A RegExp to match download URLs of releases
|
||||
const regexpMatchGitHubReleases = RegExp('"browser_download_url[":\\s]+"(https:.*download\\/([^\\/]+).*(?:' + baseApp + ')[^"]+)"', 'ig');
|
||||
|
||||
/**
|
||||
* Get and return the JSON list of releases from the update server's REST API
|
||||
*
|
||||
* @param {Function} callback The function to call with the data
|
||||
* @returns {String} A JSON string containing hierarchical release data
|
||||
*/
|
||||
function getReleasesObject(callback) {
|
||||
uiUtil.XHR(params.updateServer.url + params.updateServer.releases, 'text',
|
||||
function (response, mimetype, status) {
|
||||
if (status === 200) {
|
||||
callback(response);
|
||||
} else callback('');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to get the latest updates from a GitHub releases source
|
||||
* Only updates that are greater than the current update are returned
|
||||
* Attempts to match by channel, but also matches non-channel releases
|
||||
*
|
||||
* @param {Function} callback A function to call back with the results
|
||||
* @returns {Object} Calls back with update tag, update URL, and array of releases
|
||||
*/
|
||||
function getLatestUpdates(callback) {
|
||||
var updatedReleases = [];
|
||||
var currentRelease = params.appVersion.replace(/^v?([\d.]+)/, '$1');
|
||||
var currentReleaseChannel = params.appVersion.replace(/^[v\d.]+/, '');
|
||||
var updateTag;
|
||||
var channelMatchedTag;
|
||||
var updateUrl;
|
||||
var channelMatchedUpdateUrl;
|
||||
getReleasesObject(function (releases) {
|
||||
var releaseFile;
|
||||
var releaseVersion;
|
||||
var releaseChannel;
|
||||
// Loop through every line in releases
|
||||
var matchedRelease = regexpMatchGitHubReleases.exec(releases);
|
||||
while (matchedRelease != null) {
|
||||
releaseFile = matchedRelease[1];
|
||||
releaseVersion = matchedRelease[2].replace(/^v?([\d.]+).*/, '$1');
|
||||
releaseChannel = matchedRelease[2].replace(/^[v\d.]+/, '');
|
||||
// Compare the releases using a version-type comparison
|
||||
if (releaseVersion.localeCompare(currentRelease, { numeric: true, sensitivity: 'base' }) === 1) {
|
||||
if (!channelMatchedTag && currentReleaseChannel === releaseChannel) {
|
||||
channelMatchedTag = matchedRelease[2];
|
||||
channelMatchedUpdateUrl = releaseFile.replace(/\/download\//, '/tag/').replace(/[^/]+$/, '');
|
||||
}
|
||||
if (!updateTag) updateTag = matchedRelease[2];
|
||||
if (!updateUrl) updateUrl = releaseFile.replace(/\/download\//, '/tag/').replace(/[^/]+$/, '');
|
||||
updatedReleases.push(releaseFile)
|
||||
}
|
||||
matchedRelease = regexpMatchGitHubReleases.exec(releases);
|
||||
}
|
||||
// We should now have a list of all candidate updates, and candidate channel update
|
||||
// Compare the channel-matched update wiht the update, and if they are same underlying version number, choose channel match
|
||||
if (updateTag && updateTag.replace(/^v?([\d.]+).*/, '$1') === channelMatchedTag.replace(/^v?([\d.]+).*/, '$1')) {
|
||||
updateTag = channelMatchedTag;
|
||||
updateUrl = channelMatchedUpdateUrl;
|
||||
}
|
||||
callback(updateTag, updateUrl, updatedReleases);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functions and classes exposed by this module
|
||||
*/
|
||||
return {
|
||||
getLatestUpdates: getLatestUpdates
|
||||
};
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user