mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-11 13:18:21 -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">
|
<label class="checkbox">
|
||||||
<input type="checkbox" name="allowInternetAccess" id="allowInternetAccessCheck">
|
<input type="checkbox" name="allowInternetAccess" id="allowInternetAccessCheck">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
<b>Allow Internet access?</b>
|
<b>Allow Internet access?</b> <span id="updateStatus">(and check for updates)</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="downloadLinks" style="display: none;"></div>
|
<div id="downloadLinks" style="display: none;"></div>
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
// This uses require.js to structure javascript:
|
// This uses require.js to structure javascript:
|
||||||
// http://requirejs.org/docs/api.html#define
|
// http://requirejs.org/docs/api.html#define
|
||||||
|
|
||||||
define(['jquery', '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) {
|
function ($, zimArchiveLoader, uiUtil, util, utf8, cache, images, settingsStore, transformStyles, kiwixServe, updater) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The delay (in milliseconds) between two "keepalive" messages
|
* 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) {
|
function setActiveBtn(activeBtn) {
|
||||||
document.getElementById('btnHome').classList.remove("active");
|
document.getElementById('btnHome').classList.remove("active");
|
||||||
document.getElementById('btnRandomArticle').classList.remove("active");
|
document.getElementById('btnRandomArticle').classList.remove("active");
|
||||||
@ -1125,7 +1146,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images
|
|||||||
setContentInjectionMode(this.value);
|
setContentInjectionMode(this.value);
|
||||||
// If we're in a PWA UWP app, warn the user that this does not disable the PWA
|
// 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) &&
|
if (this.value === 'jquery' && /^http/i.test(window.location.protocol) && /UWP\|PWA/.test(params.appType) &&
|
||||||
settingsStore.getItem('allowInternetAccess') === 'true') {
|
params.allowInternetAccess === 'true') {
|
||||||
uiUtil.systemAlert(
|
uiUtil.systemAlert(
|
||||||
'<p>Please note that switching content injection mode does not revert to local code.</p>' +
|
'<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>'
|
'<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) {
|
$('input:checkbox[name=cssCacheMode]').on('change', function (e) {
|
||||||
params.cssCache = this.checked ? true : false;
|
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['omegaChar'] = getSetting('omegaChar') || 'Z'; //Set default end of alphabet string
|
||||||
params['contentInjectionMode'] = getSetting('contentInjectionMode') || ((navigator.serviceWorker && !/^(ms-appx-web:)$/i.test(window.location.protocol)
|
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
|
&& !/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['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['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
|
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
|
* Shows that an upgrade is ready to install
|
||||||
* @param {String} ver The version of the upgrade
|
* @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;
|
params.upgradeNeeded = true;
|
||||||
document.getElementById('alertBoxPersistent').innerHTML =
|
document.getElementById('alertBoxPersistent').innerHTML =
|
||||||
'<div id="upgradeAlert" class="alert alert-info alert-dismissible">\n' +
|
'<div id="upgradeAlert" class="alert alert-info alert-dismissible">\n' +
|
||||||
' <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>\n' +
|
' <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>\n' +
|
||||||
' <span id="persistentMessage"></span>\n' +
|
' <span id="persistentMessage"></span>\n' +
|
||||||
'</div>\n';
|
'</div>\n';
|
||||||
document.getElementById('persistentMessage').innerHTML = 'Version ' + ver + ' is ready to '
|
document.getElementById('persistentMessage').innerHTML = 'Version ' + ver +
|
||||||
+ type + '! (Re-launch app to ' + type + '.)';
|
(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