2013-12-20 16:31:41 +01:00
/ *
* This file is part of the Doodle3D project ( http : //doodle3d.com).
*
* Copyright ( c ) 2013 , Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later .
* See file LICENSE . txt or visit http : //www.gnu.org/licenses/gpl.html for full license details.
* /
2013-10-22 03:31:12 +02:00
function UpdatePanel ( ) {
2014-02-24 15:48:39 +01:00
var _form = new FormPanel ( ) ;
2013-10-22 03:31:12 +02:00
this . wifiboxURL ;
this . element ;
2014-02-24 15:58:50 +01:00
this . statusCheckInterval = 1000 ;
this . statusCheckDelayer ; // setTimout instance
this . installedDelay = 90 * 1000 ; // Since we can't retrieve status during installation we show the installed text after a fixed delay
this . installedDelayer ; // setTimout instance
this . retryDelay = 1000 ;
this . retryDelayer ; // setTimout instance
//this.timeoutTime = 3000;
this . canUpdate = false ;
this . currentVersion = "" ;
this . newestVersion ;
2014-02-25 17:06:08 +01:00
this . currentReleaseDate ;
this . newestReleaseDate ;
2013-10-22 03:31:12 +02:00
this . progress ;
this . imageSize ;
2014-02-07 12:35:15 +01:00
var _inAccessPointMode ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
// states from api, see Doodle3D firmware src/script/d3d-updater.lua
2014-02-24 15:58:50 +01:00
UpdatePanel . NONE = 1 ; // default state
UpdatePanel . DOWNLOADING = 2 ;
UpdatePanel . DOWNLOAD _FAILED = 3 ;
2014-02-24 17:26:34 +01:00
UpdatePanel . IMAGE _READY = 4 ; // download successful and checked
2014-02-24 15:58:50 +01:00
UpdatePanel . INSTALLING = 5 ;
UpdatePanel . INSTALLED = 6 ;
UpdatePanel . INSTALL _FAILED = 7 ;
this . state ; // update state from api
this . stateText = "" ; // update state text from api
2013-10-22 03:31:12 +02:00
var self = this ;
this . init = function ( wifiboxURL , updatePanelElement ) {
2014-02-24 15:48:39 +01:00
_form . init ( wifiboxURL , wifiboxURL , updatePanelElement ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
this . wifiboxURL = wifiboxURL ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
this . element = updatePanelElement ;
2014-01-02 16:46:36 +01:00
this . retainCheckbox = this . element . find ( "#retainConfiguration" ) ;
2014-02-24 15:48:39 +01:00
this . includeBetasCheckbox = this . element . find ( "#includeBetas" ) ;
2013-10-22 03:31:12 +02:00
this . btnUpdate = this . element . find ( "#update" ) ;
this . statusDisplay = this . element . find ( "#updateState" ) ;
this . infoDisplay = this . element . find ( "#updateInfo" ) ;
2014-02-24 15:58:50 +01:00
2014-01-02 16:46:36 +01:00
this . retainCheckbox . change ( this . retainChanged ) ;
2014-02-24 15:48:39 +01:00
this . includeBetasCheckbox . change ( this . includeBetasChanged ) ;
2013-10-22 03:31:12 +02:00
this . btnUpdate . click ( this . update ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
this . checkStatus ( false ) ;
}
2014-02-25 17:06:08 +01:00
2014-01-02 16:46:36 +01:00
this . retainChanged = function ( e ) {
2014-02-10 14:46:23 +01:00
//console.log("UpdatePanel:retainChanged");
2014-02-24 15:48:39 +01:00
//this call ensures that the update button gets enabled if (!retainChanged && !canUpdate)
2013-12-23 17:40:14 +01:00
self . setState ( self . state , true ) ;
}
2014-02-25 17:06:08 +01:00
2014-02-24 15:48:39 +01:00
this . includeBetasChanged = function ( ) {
//console.log("UpdatePanel:includeBetasChanged");
_form . saveSettings ( _form . readForm ( ) , function ( validated , data ) {
if ( validated ) self . checkStatus ( false ) ;
} ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . update = function ( ) {
console . log ( "UpdatePanel:update" ) ;
self . downloadUpdate ( ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . downloadUpdate = function ( ) {
console . log ( "UpdatePanel:downloadUpdate" ) ;
$ . ajax ( {
url : self . wifiboxURL + "/update/download" ,
type : "POST" ,
dataType : 'json' ,
success : function ( response ) {
console . log ( "UpdatePanel:downloadUpdate response: " , response ) ;
}
} ) . fail ( function ( ) {
console . log ( "UpdatePanel:downloadUpdate: failed" ) ;
} ) ;
self . setState ( UpdatePanel . DOWNLOADING ) ;
self . startCheckingStatus ( ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . installUpdate = function ( ) {
console . log ( "UpdatePanel:installUpdate" ) ;
2014-02-24 15:58:50 +01:00
2014-01-02 16:46:36 +01:00
// should personal sketches and settings be retained over update?
var retain = self . retainCheckbox . prop ( 'checked' ) ;
console . log ( " retain: " , retain ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
self . stopCheckingStatus ( ) ;
2014-01-02 16:46:36 +01:00
postData = { no _retain : ! retain }
2013-10-22 03:31:12 +02:00
$ . ajax ( {
url : self . wifiboxURL + "/update/install" ,
type : "POST" ,
2013-12-23 17:40:14 +01:00
data : postData ,
2013-10-22 03:31:12 +02:00
dataType : 'json' ,
success : function ( response ) {
console . log ( "UpdatePanel:installUpdate response: " , response ) ;
}
} ) . fail ( function ( ) {
2014-02-10 14:46:23 +01:00
//console.log("UpdatePanel:installUpdate: no respons (there shouldn't be)");
2013-10-22 03:31:12 +02:00
} ) ;
self . setState ( UpdatePanel . INSTALLING ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
clearTimeout ( self . installedDelayer ) ;
self . installedDelayer = setTimeout ( function ( ) { self . setState ( UpdatePanel . INSTALLED ) } , self . installedDelay ) ;
}
2014-02-24 15:58:50 +01:00
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . startCheckingStatus = function ( ) {
clearTimeout ( self . statusCheckDelayer ) ;
clearTimeout ( self . retryDelayer ) ;
self . statusCheckDelayer = setTimeout ( function ( ) { self . checkStatus ( true ) } , self . statusCheckInterval ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . stopCheckingStatus = function ( ) {
clearTimeout ( self . statusCheckDelayer ) ;
clearTimeout ( self . retryDelayer ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . checkStatus = function ( keepChecking ) {
2014-02-24 15:58:50 +01:00
if ( ! communicateWithWifibox ) return ;
2013-10-22 03:31:12 +02:00
$ . ajax ( {
url : self . wifiboxURL + "/update/status" ,
type : "GET" ,
dataType : 'json' ,
//timeout: self.timeoutTime,
success : function ( response ) {
console . log ( "UpdatePanel:checkStatus response: " , response ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
// Keep checking ?
if ( keepChecking ) {
switch ( self . state ) {
2014-02-24 15:58:50 +01:00
case UpdatePanel . DOWNLOADING :
2013-10-22 03:31:12 +02:00
case UpdatePanel . INSTALLING :
clearTimeout ( self . statusCheckDelayer ) ;
self . statusCheckDelayer = setTimeout ( function ( ) { self . checkStatus ( keepChecking ) } , self . statusCheckInterval ) ;
break ;
}
}
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
if ( response . status != "error" ) {
var data = response . data ;
self . handleStatusData ( data ) ;
2014-02-24 17:26:34 +01:00
} else {
console . log ( "API update/status call returned an error: '" + response . msg + "'" ) ;
2013-10-22 03:31:12 +02:00
}
}
} ) . fail ( function ( ) {
//console.log("UpdatePanel:checkStatus: failed");
if ( keepChecking ) {
clearTimeout ( self . retryDelayer ) ;
self . retryDelayer = setTimeout ( function ( ) { self . checkStatus ( keepChecking ) } , self . retryDelay ) ; // retry after delay
}
} ) ;
}
2014-02-24 15:58:50 +01:00
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . handleStatusData = function ( data ) {
//console.log("UpdatePanel:handleStatusData");
2014-02-25 17:06:08 +01:00
//status texts and button state might have to be updated if the newest version changes (e.g., after (un)ticking include betas checkbox)
var refreshUI = ( self . newestVersion != data . newest _version ) ;
2014-02-24 15:48:39 +01:00
2013-10-22 03:31:12 +02:00
self . canUpdate = data . can _update ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
if ( self . currentVersion != data . current _version || self . newestVersion != data . newest _version ) {
self . currentVersion = data . current _version ;
self . newestVersion = data . newest _version ;
2014-02-25 17:06:08 +01:00
self . currentReleaseDate = data . current _release _date ; // not always available (for older versions)
self . newestReleaseDate = data . newest _release _date ; // not always available (for older versions)
2013-10-22 03:31:12 +02:00
self . updateInfoDisplay ( ) ;
}
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
self . stateText = data . state _text ;
self . progress = data . progress ; // not always available
self . imageSize = data . image _size ; // not always available
2014-02-24 15:58:50 +01:00
2014-02-24 15:48:39 +01:00
self . setState ( data . state _code , refreshUI ) ;
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
switch ( this . state ) {
case UpdatePanel . IMAGE _READY :
self . installUpdate ( ) ;
break ;
}
}
2014-02-25 17:06:08 +01:00
2013-12-23 17:40:14 +01:00
this . setState = function ( newState , refresh ) {
2014-02-10 14:46:23 +01:00
//console.log("UpdatePanel:setState");
2013-12-23 17:40:14 +01:00
if ( ! refresh && this . state == newState ) return ;
2014-02-07 12:35:15 +01:00
console . log ( "UpdatePanel:setState: " , this . state , " > " , newState , "(" , this . stateText , ") (in Access Point Mode: " , _inAccessPointMode , ") (newestVersion: " , self . newestVersion , ") (refresh: " , refresh , ")" ) ;
2013-10-22 03:31:12 +02:00
this . state = newState ;
2014-02-24 15:58:50 +01:00
2014-01-02 16:46:36 +01:00
// should personal sketches and settings be retained over update?
var retain = self . retainCheckbox . prop ( 'checked' ) ;
2014-02-10 14:46:23 +01:00
//console.log(" retain", retain);
2014-02-24 15:58:50 +01:00
2013-10-22 03:31:12 +02:00
// download button
2014-02-24 15:58:50 +01:00
// if there isn't newestVersion data something went wrong,
2013-12-23 17:40:14 +01:00
// probably accessing the internet
2014-02-10 14:46:23 +01:00
//console.log(" self.newestVersion: ",self.newestVersion);
2013-10-22 03:31:12 +02:00
if ( self . newestVersion != undefined ) {
2014-02-10 14:46:23 +01:00
//console.log(" this.state: ",this.state);
2013-10-22 03:31:12 +02:00
switch ( this . state ) {
2014-02-24 15:58:50 +01:00
case UpdatePanel . NONE :
2013-10-22 03:31:12 +02:00
case UpdatePanel . DOWNLOAD _FAILED :
case UpdatePanel . INSTALL _FAILED :
2014-02-10 14:46:23 +01:00
//console.log(" self.canUpdate: ",self.canUpdate);
2014-01-02 16:46:36 +01:00
if ( self . canUpdate || ! retain ) {
2013-10-22 03:31:12 +02:00
self . btnUpdate . removeAttr ( "disabled" ) ;
} else {
self . btnUpdate . attr ( "disabled" , true ) ;
}
break ;
default :
self . btnUpdate . attr ( "disabled" , true ) ;
2014-02-24 15:58:50 +01:00
break ;
2013-10-22 03:31:12 +02:00
}
} else {
self . btnUpdate . attr ( "disabled" , true ) ;
}
this . updateStatusDisplay ( ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . updateStatusDisplay = function ( ) {
var text = "" ;
if ( self . newestVersion != undefined ) {
switch ( this . state ) {
case UpdatePanel . NONE :
if ( self . canUpdate ) {
2014-02-25 17:06:08 +01:00
var currIsBeta = self . versionIsBeta ( self . currentVersion ) ;
var newIsBeta = self . versionIsBeta ( self . newestVersion ) ;
var relIsNewer = ( self . newestReleaseDate && self . currentReleaseDate ) ? ( self . newestReleaseDate - self . currentReleaseDate > 0 ) : true ;
if ( ! newIsBeta ) {
if ( relIsNewer ) text = "Update available." ;
else text = "You can switch back to the latest stable release." ; //this case is always a beta->stable 'downgrade'
} else {
//NOTE: actually, an older beta will never be presented as update by the API
var prefixText = currIsBeta ? "A" : ( relIsNewer ? "A newer" : "An older" ) ;
text = prefixText + " beta release is available." ;
}
2013-10-22 03:31:12 +02:00
} else {
text = "You're up to date." ;
}
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . DOWNLOADING :
2013-10-22 03:31:12 +02:00
text = "Downloading update..." ;
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . DOWNLOAD _FAILED :
2013-10-22 03:31:12 +02:00
text = "Downloading update failed." ;
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . IMAGE _READY :
2013-10-22 03:31:12 +02:00
text = "Update downloaded." ;
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . INSTALLING :
2013-10-22 03:31:12 +02:00
text = "Installing update... (will take a minute)" ;
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . INSTALLED :
2014-03-14 12:23:57 +01:00
//text = "Update complete, please reconnect by connecting your device to the access point of your WiFi box and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>";
text = "Update complete, please <a href='javascript:location.reload(true);'>refresh Page</a>." ;
2013-10-22 03:31:12 +02:00
break ;
2014-02-24 15:58:50 +01:00
case UpdatePanel . INSTALL _FAILED :
2013-10-22 03:31:12 +02:00
text = "Installing update failed." ;
break ;
}
} else {
2014-02-07 12:35:15 +01:00
if ( _inAccessPointMode ) {
2013-10-22 03:31:12 +02:00
text = "Can't access internet in access point mode." ;
} else {
text = "Can't access internet." ;
}
}
this . statusDisplay . html ( text ) ;
}
2014-02-25 17:06:08 +01:00
2013-10-22 03:31:12 +02:00
this . updateInfoDisplay = function ( ) {
2014-02-25 17:06:08 +01:00
var html = 'Current version: ' + self . currentVersion ;
if ( self . currentReleaseDate ) html += '; released: ' + self . formatDate ( self . currentReleaseDate ) ;
html += ' (<a target="d3d-curr-relnotes" href="ReleaseNotes.html">release notes</a>).' ;
2013-10-22 03:31:12 +02:00
if ( self . canUpdate ) {
2014-02-25 17:06:08 +01:00
html += '<br/>Latest version: ' + self . newestVersion ;
if ( self . newestReleaseDate ) html += '; released: ' + self . formatDate ( self . newestReleaseDate ) ;
html += ' (<a target="d3d-new-relnotes" href="http://doodle3d.com/updates/images/ReleaseNotes.md">release notes</a>).' ;
2013-10-22 03:31:12 +02:00
}
2013-12-12 14:14:34 +01:00
self . infoDisplay . html ( html ) ;
2013-10-22 03:31:12 +02:00
}
2014-02-07 12:35:15 +01:00
2014-02-25 17:06:08 +01:00
2014-02-07 12:35:15 +01:00
this . setInAccessPointMode = function ( inAccessPointMode ) {
_inAccessPointMode = inAccessPointMode ;
self . updateStatusDisplay ( ) ;
2013-10-22 03:31:12 +02:00
}
2014-02-24 17:26:34 +01:00
2014-02-25 17:06:08 +01:00
this . formatDate = function ( ts ) {
if ( ! ts || ts . length != 8 || ! /^[0-9]+$/ . test ( ts ) ) return null ;
var fields = [ ts . substr ( 0 , 4 ) , ts . substr ( 4 , 2 ) , ts . substr ( 6 , 2 ) ] ;
if ( ! fields || fields . length != 3 || fields [ 1 ] > 12 ) return null ;
2015-09-15 10:42:45 +02:00
var abbrMonths = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ] ;
2014-02-25 17:06:08 +01:00
return abbrMonths [ fields [ 1 ] - 1 ] + " " + fields [ 2 ] + ", " + fields [ 0 ] ;
}
2014-02-24 17:26:34 +01:00
this . versionIsBeta = function ( version ) {
2014-02-25 17:06:08 +01:00
return version ? /.*-.*/g . test ( version ) : null ;
2014-02-24 17:26:34 +01:00
}
2013-12-12 14:14:34 +01:00
}