New update mecanism - Ref #7910
This commit is contained in:
parent
1d46e0e0e1
commit
13c105e82b
|
@ -1,6 +1,6 @@
|
|||
#ptr {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
color: #fff;
|
||||
|
|
|
@ -41,6 +41,13 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/x-tmpl" id="momo-first-launch-tmpl">
|
||||
<h1>Première utilisation</h1
|
||||
<p>
|
||||
Tirez vers le bas pour mettre à jour l'application
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-tmpl" id="momo-icon-tmpl">
|
||||
{% if(o.icon.startsWith('http://') ||
|
||||
o.icon.startsWith('https://') ||
|
||||
|
@ -164,7 +171,7 @@
|
|||
|
||||
<!-- Flash message template -->
|
||||
<script type="text/x-tmpl" id="momo-flash-message-tmpl">
|
||||
<div class="alert alert-{%= o.type %}">
|
||||
<div class="alert alert-{%= o.type %} pt-page-rotateRoomBottomIn">
|
||||
{%# o.message %}
|
||||
</div>
|
||||
</script>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
"icon": "icon.png",
|
||||
"contact": "info@example.net",
|
||||
"updateFreq": 5,
|
||||
"updateUrl": "http://pwr.link/entrouvert/index.json?0.0.1",
|
||||
"assetsUrl": "http://pwr.link/entrouvert/assets.zip?0.0.1"
|
||||
"manifestUrl": "http://pwr.link/entrouvert/index.json",
|
||||
"assetsUrl": "http://pwr.link/entrouvert/assets.zip"
|
||||
},
|
||||
"title": "Ma ville (Local)",
|
||||
"content": "<p>Bienvenue !</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>",
|
||||
|
|
338
www/js/index.js
338
www/js/index.js
|
@ -25,6 +25,7 @@ var ANIMATION_OUT_CLASS = 'pt-page-moveToLeftEasing pt-page-ontop';
|
|||
var ANIMATION_IN_CLASS = 'pt-page-moveFromRight';
|
||||
var ANIMATION_BACK_OUT_CLASS = 'pt-page-moveToRightEasing pt-page-ontop';
|
||||
var ANIMATION_BACK_IN_CLASS = 'pt-page-moveFromLeft';
|
||||
var ON_PULL = 'checkForUpdate'; // || 'update'
|
||||
|
||||
// Application
|
||||
var app = {
|
||||
|
@ -40,8 +41,10 @@ var app = {
|
|||
meta: {
|
||||
'title': 'Momo Application',
|
||||
'contact': 'contact@cadoles.com',
|
||||
'updateUrl': 'index.json',
|
||||
'updateFreq': 0
|
||||
'manifestUrl': 'index.json',
|
||||
'assetsUrl': 'assets.zip',
|
||||
'updateFreq': 0,
|
||||
'content': tmpl('momo-first-launch-tmpl')
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -61,6 +64,10 @@ var app = {
|
|||
hashHistory : [window.location.hash],
|
||||
historyLength : window.history.length,
|
||||
rootPath : '',
|
||||
hasStarted : false,
|
||||
assetsMtime : null,
|
||||
manifestMtime : null,
|
||||
updateTimeout : null,
|
||||
|
||||
// Application Constructor
|
||||
initialize: function() {
|
||||
|
@ -91,8 +98,20 @@ var app = {
|
|||
|
||||
// Device ready callback
|
||||
onDeviceReady: function() {
|
||||
|
||||
// Init search engine index
|
||||
app.initIndex();
|
||||
app.loadManifest();
|
||||
|
||||
// Load manifest from localStorage
|
||||
app.loadLocalManifest();
|
||||
|
||||
// Check for new updates
|
||||
app.checkForUpdate(app.start, app.start);
|
||||
|
||||
// Update Reminder
|
||||
app.updateTimeout = setTimeout( app.checkForLastUpdateCheck, app.manifest.meta.updateFreq );
|
||||
|
||||
// Touch events faster response patch
|
||||
FastClick.attach(document.body);
|
||||
},
|
||||
|
||||
|
@ -111,43 +130,90 @@ var app = {
|
|||
});
|
||||
},
|
||||
|
||||
// JSON Manifest loading function
|
||||
loadManifest: function(start, cb, force){
|
||||
if(DEBUG) console.log('load '+JSON.stringify(app.manifest));
|
||||
app.utils.setLoadingMsg("Chargement de l'application");
|
||||
|
||||
var updateRequired = true;
|
||||
if(typeof start === "undefined")
|
||||
start = true;
|
||||
if(typeof force === "undefined")
|
||||
force = false;
|
||||
|
||||
// In case the url is incorrect, we get the backup manifest
|
||||
app.safeManifest = app.manifest;
|
||||
|
||||
// Get manifest from localStorage if it exists
|
||||
if(localStorage.getItem("momo-manifest")){
|
||||
try {
|
||||
app.manifest = JSON.parse(localStorage.getItem("momo-manifest"));
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
checkForLastUpdateCheck: function(resolve, reject){
|
||||
// Checklast Update
|
||||
var lastUpdate = localStorage.getItem("momo-timestamp") ? new Date(localStorage.getItem("momo-timestamp")) : new Date(0);
|
||||
var timeDiff = ((new Date()).getTime() - lastUpdate.getTime()) / 1000;
|
||||
updateRequired = timeDiff > app.manifest.meta.updateFreq;
|
||||
var updateRequired = timeDiff > app.manifest.meta.updateFreq;
|
||||
|
||||
// Start Application Return if no need for update
|
||||
if(!updateRequired && !DEBUG && !force){
|
||||
if(start)
|
||||
app.start();
|
||||
if(typeof cb === "function")
|
||||
cb();
|
||||
return;
|
||||
if(updateRequired)
|
||||
app.flash("Vérifiez si de nouvelles mises à jours sont disponibles en tirant la page vers les bas", "info");
|
||||
|
||||
if(typeof resolve === 'function')
|
||||
resolve(updateRequired);
|
||||
},
|
||||
|
||||
checkForUpdate: function(resolve, reject) {
|
||||
app.utils.setLoadingMsg("Verification des mises à jour");
|
||||
|
||||
var manifestReady = false;
|
||||
var assetsReady = false;
|
||||
var updateAvailable = false;
|
||||
var updateError = false;
|
||||
|
||||
var onGetMtime = function(key, mtime, ready) {
|
||||
old_mtime = localStorage.getItem("momo-"+key+"-mtime");
|
||||
if (mtime) {
|
||||
if(mtime != old_mtime) {
|
||||
updateAvailable = true;
|
||||
}
|
||||
} else {
|
||||
updateError = true;
|
||||
}
|
||||
if(ready){
|
||||
if(updateError){
|
||||
if(DEBUG) console.error('Error checking for updates');
|
||||
app.flash("Impossible de détecter des nouvelles mises à jour", 'danger');
|
||||
if(typeof reject === 'function')
|
||||
reject();
|
||||
} else {
|
||||
if(updateAvailable){
|
||||
app.flash(tmpl('momo-update-available-tmpl', {}), 'success');
|
||||
app.utils.setLoadingMsg("Mise à jour disponible !");
|
||||
} else {
|
||||
app.utils.setLoadingMsg("Aucunes nouvelles mises à jour");
|
||||
}
|
||||
if(typeof resolve === 'function')
|
||||
resolve(updateAvailable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
app.utils.getModifiedTime(app.manifest.meta.manifestUrl, function(mtime) {
|
||||
app.manifestMtime = mtime;
|
||||
onGetMtime('manifest', mtime, assetsReady);
|
||||
manifestReady = true;
|
||||
});
|
||||
app.utils.getModifiedTime(app.manifest.meta.assetsUrl, function(mtime) {
|
||||
app.assetsMtime = mtime;
|
||||
onGetMtime('assets', mtime, manifestReady);
|
||||
assetsReady = true;
|
||||
});
|
||||
},
|
||||
|
||||
loadLocalManifest: function() {
|
||||
var manifest;
|
||||
if(manifest = localStorage.getItem("momo-manifest")){
|
||||
try {
|
||||
app.manifest = JSON.parse(manifest);
|
||||
} catch(e) {}
|
||||
}
|
||||
},
|
||||
|
||||
// JSON Manifest loading function
|
||||
loadManifest: function(resolve, reject){
|
||||
if(DEBUG) console.log('load '+JSON.stringify(app.manifest));
|
||||
app.utils.setLoadingMsg("Mise à jour du manifest - 0%");
|
||||
|
||||
// In case the url is incorrect, we get the backup manifest
|
||||
|
||||
app.safeManifest = app.manifest;
|
||||
|
||||
// Get manifest from localStorage if it exists
|
||||
app.loadLocalManifest();
|
||||
|
||||
// Start AJAX
|
||||
var url = app.manifest.meta.updateUrl;
|
||||
var url = app.manifest.meta.manifestUrl;
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.open('GET', app.utils.addParameter(url, 'timestamp', (+new Date), true), true);
|
||||
|
@ -172,34 +238,27 @@ var app = {
|
|||
}
|
||||
|
||||
// Reload if new manifest url
|
||||
if(url != app.manifest.meta.updateUrl){
|
||||
app.loadManifest(start, cb, force);
|
||||
// Otherwise fetch assets and start application
|
||||
} else if(updateRequired) {
|
||||
app.fetchAssets(function(){
|
||||
if(start)
|
||||
app.start();
|
||||
if(typeof cb === "function")
|
||||
cb();
|
||||
});
|
||||
// Start application with no udpates
|
||||
} else {
|
||||
if(start)
|
||||
app.start();
|
||||
if(typeof cb === "function")
|
||||
cb();
|
||||
if(url != app.manifest.meta.manifestUrl){
|
||||
app.loadManifest(resolve, reject);
|
||||
} else {
|
||||
if(typeof resolve === "function")
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle AJAX Error
|
||||
} else {
|
||||
app.onAjaxError(url, request);
|
||||
if(typeof reject === "function")
|
||||
reject();
|
||||
}
|
||||
};
|
||||
|
||||
// Handle AJAX Error
|
||||
request.onerror = function() {
|
||||
app.onAjaxError(url);
|
||||
if(typeof reject === "function")
|
||||
reject();
|
||||
};
|
||||
|
||||
// Send AJAX
|
||||
|
@ -248,10 +307,10 @@ var app = {
|
|||
},
|
||||
|
||||
// Get distant zip asset archive and update local cache
|
||||
fetchAssets: function(cb){
|
||||
loadAssets: function(resolve, reject){
|
||||
|
||||
if(DEBUG) console.log('fetch assets');
|
||||
app.utils.setLoadingMsg("Mise à jour - 0%");
|
||||
app.utils.setLoadingMsg("Téléchargement des assets - 0%");
|
||||
|
||||
if(typeof FileTransfer !== 'undefined' && typeof zip !== 'undefined'){
|
||||
window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, function (fileSystem) {
|
||||
|
@ -264,17 +323,20 @@ var app = {
|
|||
zip.unzip(uri, rootPath,
|
||||
// Success callback
|
||||
function(ret){
|
||||
app.utils.setLoadingMsg("Mise à jour - 100%");
|
||||
if(ret == 0)
|
||||
alert('Success unzip');
|
||||
if(ret == -1)
|
||||
alert('Error unzip');
|
||||
cb();
|
||||
app.utils.setLoadingMsg("Téléchargement des assets - 100%");
|
||||
if(ret == 0) {
|
||||
if(typeof resolve === 'function')
|
||||
resolve();
|
||||
} else
|
||||
if(ret == -1) {
|
||||
if(typeof reject === 'function')
|
||||
reject();
|
||||
}
|
||||
},
|
||||
// Progress callback
|
||||
function(e){
|
||||
var progress = Math.round((e.loaded / e.total) * 100);
|
||||
app.utils.setLoadingMsg("Mise à jour - "+progress+"%");
|
||||
app.utils.setLoadingMsg("Téléchargement des assets - "+progress+"%");
|
||||
});
|
||||
|
||||
// Fetch Assets Zip Archive
|
||||
|
@ -307,11 +369,17 @@ var app = {
|
|||
//);
|
||||
}, function(error){
|
||||
if(DEBUG) console.error('Filesystem error');
|
||||
cb();
|
||||
app.utils.setLoadingMsg("Erreur du système de fichier");
|
||||
app.flash("Erreur du système de fichier", 'danger');
|
||||
if(typeof reject === 'function')
|
||||
reject();
|
||||
});
|
||||
} else {
|
||||
if(DEBUG) console.error('Plugins "zip" & "file-transfer" not available (local mode ?)');
|
||||
cb();
|
||||
app.utils.setLoadingMsg("Plugin 'zip' indisponible");
|
||||
app.flash("Plugin 'zip' indisponible", 'danger');
|
||||
if(typeof reject === 'function')
|
||||
reject();
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -347,9 +415,10 @@ var app = {
|
|||
},
|
||||
|
||||
// Application starter
|
||||
start: function(){
|
||||
start: function(resolve, reject){
|
||||
if(DEBUG) console.log('start '+JSON.stringify(app.manifest));
|
||||
app.utils.setLoadingMsg("Démarrage de l'application");
|
||||
app.hasStarted = true;
|
||||
|
||||
// Default route to home
|
||||
app.manifest.id = app.current_page = 'home';
|
||||
|
@ -363,11 +432,8 @@ var app = {
|
|||
// Render Homepage
|
||||
app.render(app.manifest);
|
||||
app.navigate('home', false, function(){
|
||||
app.flash(tmpl('momo-update-available-tmpl', {}), 'success');
|
||||
// Import Scripts & Styles
|
||||
app.appendAssets(function(){
|
||||
|
||||
});
|
||||
if(typeof resolve == 'function')
|
||||
resolve();
|
||||
});
|
||||
|
||||
// Listen for search form submission
|
||||
|
@ -539,12 +605,7 @@ var app = {
|
|||
$inpage.innerHTML = app.renderPage(page_obj);
|
||||
|
||||
// Pull to update binder
|
||||
WebPullToRefresh.init( {
|
||||
loadingFunction: function(){
|
||||
return new Promise( app.update );
|
||||
},
|
||||
contentEl: $inpage
|
||||
} );
|
||||
app.bindPagePull($inpage);
|
||||
|
||||
if(!ANIMATION_ENABLED || app.current_page == page){
|
||||
$inpage.classList.add('momo-page-current');
|
||||
|
@ -595,6 +656,20 @@ var app = {
|
|||
app.current_page = page;
|
||||
},
|
||||
|
||||
bindPagePull: function($page) {
|
||||
WebPullToRefresh.destroy();
|
||||
WebPullToRefresh.init( {
|
||||
loadingFunction: function(){
|
||||
if(ON_PULL == "checkForUpdate")
|
||||
return new Promise( app.checkForUpdate );
|
||||
else
|
||||
if(ON_PULL == "update")
|
||||
return new Promise( app.update );
|
||||
},
|
||||
contentEl: $page
|
||||
} );
|
||||
},
|
||||
|
||||
// Animation Callback
|
||||
onAnimationEnd: function($outpage, $inpage, back, cb) {
|
||||
app.endCurrPage = false;
|
||||
|
@ -723,54 +798,73 @@ var app = {
|
|||
|
||||
flash: function(message, type) {
|
||||
var elements = document.getElementsByClassName("momo-flash-messages");
|
||||
for (var i = 0; i < elements.length; i++)
|
||||
elements[i].innerHTML += tmpl('momo-flash-message-tmpl', {
|
||||
message: message,
|
||||
type: type ? type : 'info'
|
||||
});
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
elements[i].innerHTML = "";
|
||||
}
|
||||
setTimeout(function(){
|
||||
var elements = document.getElementsByClassName("momo-flash-messages");
|
||||
for (var i = 0; i < elements.length; i++) {
|
||||
elements[i].innerHTML += tmpl('momo-flash-message-tmpl', {
|
||||
message: message,
|
||||
type: type ? type : 'info'
|
||||
});
|
||||
}
|
||||
}, 200);
|
||||
},
|
||||
|
||||
update: function( resolve, reject ) {
|
||||
// Run some async loading code here
|
||||
//window.location.reload();
|
||||
var els = document.getElementsByTagName("a"),
|
||||
els_length = els.length;
|
||||
for (var i = 0, l = els_length; i < l; i++) {
|
||||
var el = els[i];
|
||||
if (el.href.split("#")[1] === 'momo-update') {
|
||||
el.classList.add('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
app.loadManifest(false, function(){
|
||||
for(var page in app.pages){
|
||||
if(typeof app.pages[page].search == 'undefined'){
|
||||
delete app.pages[page];
|
||||
document.getElementById("momo-pages").removeChild(
|
||||
document.getElementById(page)
|
||||
);
|
||||
}
|
||||
app.loadManifest(function(){
|
||||
app.loadAssets(function(){
|
||||
app.reset();
|
||||
if(typeof resolve === 'function')
|
||||
resolve();
|
||||
}, reject);
|
||||
}, reject);
|
||||
},
|
||||
|
||||
reset: function(){
|
||||
for(var page in app.pages){
|
||||
if(typeof app.pages[page].search == 'undefined'){
|
||||
delete app.pages[page];
|
||||
document.getElementById("momo-pages").removeChild(
|
||||
document.getElementById(page)
|
||||
);
|
||||
}
|
||||
// Regiter pages tree
|
||||
app.menu = [];
|
||||
app.manifest.id = 'home';
|
||||
app.registerPage(app.manifest);
|
||||
// Render every page
|
||||
for(var page in app.pages){
|
||||
var $page = document.getElementById(page);
|
||||
if(!$page){
|
||||
$page = document.createElement('div');
|
||||
$page.id = app.pages[page].id;
|
||||
$page.className = "momo-page";
|
||||
document.getElementById('momo-pages').appendChild($page);
|
||||
}
|
||||
}
|
||||
// Regiter pages tree
|
||||
app.menu = [];
|
||||
app.manifest.id = 'home';
|
||||
app.registerPage(app.manifest);
|
||||
// Render every page
|
||||
for(var page in app.pages){
|
||||
var $page = document.getElementById(page);
|
||||
if(!$page){
|
||||
$page = document.createElement('div');
|
||||
$page.id = app.pages[page].id;
|
||||
$page.className = "momo-page";
|
||||
document.getElementById('momo-pages').appendChild($page);
|
||||
}
|
||||
|
||||
// Render Homepage
|
||||
//app.render(app.manifest);
|
||||
|
||||
if(typeof resolve === 'function')
|
||||
resolve();
|
||||
app.utils.setLoadingMsg("Mise à jour effectuée !");
|
||||
if(typeof app.pages[app.current_page].search != 'undefined'){
|
||||
app.search(app.current_query);
|
||||
} else {
|
||||
app.navigate(app.current_page);
|
||||
}
|
||||
}, true); // Force reload manifest
|
||||
//reject();
|
||||
}
|
||||
|
||||
app.utils.setLoadingMsg("Mise à jour effectuée !");
|
||||
|
||||
if(typeof app.pages[app.current_page].search != 'undefined'){
|
||||
app.search(app.current_query);
|
||||
} else {
|
||||
app.navigate(app.current_page);
|
||||
}
|
||||
|
||||
localStorage.setItem('momo-manifest-mtime', app.manifestMtime);
|
||||
localStorage.setItem('momo-assets-mtime', app.assetsMtime);
|
||||
},
|
||||
|
||||
// Various Javascript Helpers
|
||||
|
@ -919,6 +1013,22 @@ var app = {
|
|||
newQueryString += parameterName + "=" + (parameterValue?parameterValue:'');
|
||||
}
|
||||
return urlParts[0] + newQueryString + urlhash;
|
||||
},
|
||||
|
||||
getModifiedTime: function(url, callback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('HEAD', url, true); // use HEAD - we only need the headers
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
var mtime = new Date(xhr.getResponseHeader('Last-Modified'));
|
||||
if (mtime.toString() === 'Invalid Date') {
|
||||
callback(); // dont want to return a bad date
|
||||
} else {
|
||||
callback(mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -81,18 +81,23 @@ var WebPullToRefresh = (function () {
|
|||
}
|
||||
|
||||
|
||||
var h = new Hammer( options.contentEl, { touchAction: 'pan-y' } );
|
||||
options.h = new Hammer( options.contentEl, { touchAction: 'pan-y' } );
|
||||
|
||||
h.get( 'pan' ).set( { direction: Hammer.DIRECTION_ALL } );
|
||||
options.h.get( 'pan' ).set( { direction: Hammer.DIRECTION_ALL } );
|
||||
|
||||
h.on( 'panstart', _panStart );
|
||||
h.on( 'pandown', _panDown );
|
||||
h.on( 'panup', _panUp );
|
||||
h.on( 'panright', _panRight );
|
||||
h.on( 'panleft', _panLeft );
|
||||
h.on( 'panend', _panEnd );
|
||||
options.h.on( 'panstart', _panStart );
|
||||
options.h.on( 'pandown', _panDown );
|
||||
options.h.on( 'panup', _panUp );
|
||||
options.h.on( 'panright', _panRight );
|
||||
options.h.on( 'panleft', _panLeft );
|
||||
options.h.on( 'panend', _panEnd );
|
||||
};
|
||||
|
||||
var destroy = function() {
|
||||
if(options.h)
|
||||
options.h.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether pan events should apply based on scroll position on panstart
|
||||
*
|
||||
|
@ -297,7 +302,8 @@ var WebPullToRefresh = (function () {
|
|||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
init: init,
|
||||
destroy: destroy
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
Reference in New Issue