mirror of
https://github.com/Doodle3D/doodle3d-client.git
synced 2024-11-24 18:17:56 +01:00
Merge branch 'develop'
This commit is contained in:
commit
f3577669d2
1
Makefile
1
Makefile
@ -62,6 +62,7 @@ define Package/doodle3d-client/install
|
|||||||
$(CP) $(PKG_BUILD_DIR)/www/index.html $(1)/www/
|
$(CP) $(PKG_BUILD_DIR)/www/index.html $(1)/www/
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/
|
$(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/
|
$(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/
|
||||||
|
$(CP) $(PKG_BUILD_DIR)/www/redirect.html $(1)/www/
|
||||||
|
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/
|
$(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/
|
||||||
$(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/
|
$(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/
|
||||||
|
@ -24,21 +24,21 @@ function Message() {
|
|||||||
this.init = function($element) {
|
this.init = function($element) {
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
}
|
}
|
||||||
this.set = function(text,mode,autoHide,disableEffect) {
|
this.set = function(contents,mode,autoHide,disableEffect) {
|
||||||
console.log("Message:set: ",text,mode,autoHide,disableEffect);
|
console.log("Message:set: ",contents,mode,autoHide,disableEffect);
|
||||||
if(disableEffect) {
|
if(disableEffect) {
|
||||||
self.fill(text,mode,autoHide)
|
self.fill(contents,mode,autoHide)
|
||||||
} else{
|
} else{
|
||||||
self.hide(function() {
|
self.hide(function() {
|
||||||
self.show();
|
self.show();
|
||||||
self.fill(text,mode,autoHide)
|
self.fill(contents,mode,autoHide)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fill = function(text,mode,autoHide) {
|
this.fill = function(contents,mode,autoHide) {
|
||||||
//console.log("Message:fill: ",text,mode,autoHide);
|
//console.log("Message:fill: ",text,mode,autoHide);
|
||||||
self.clear();
|
self.clear();
|
||||||
self.$element.text(text);
|
self.$element.html(contents);
|
||||||
self.$element.addClass(mode);
|
self.$element.addClass(mode);
|
||||||
self.mode = mode;
|
self.mode = mode;
|
||||||
clearTimeout(autohideTimeout);
|
clearTimeout(autohideTimeout);
|
||||||
@ -47,7 +47,7 @@ function Message() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.clear = function($element) {
|
this.clear = function($element) {
|
||||||
this.$element.text("");
|
this.$element.html("");
|
||||||
this.$element.removeClass(this.mode);
|
this.$element.removeClass(this.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,14 @@ function Printer() {
|
|||||||
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
|
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
|
||||||
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
|
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
|
||||||
Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected
|
Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected
|
||||||
Printer.IDLE_STATE = "idle"; // printer found, but idle
|
Printer.CONNECTING_STATE = "connecting"; // printer connecting (printer found, but driver has not yet finished setting up the connection)
|
||||||
|
Printer.IDLE_STATE = "idle"; // printer found and ready to use, but idle
|
||||||
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
||||||
Printer.PRINTING_STATE = "printing";
|
Printer.PRINTING_STATE = "printing";
|
||||||
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
||||||
Printer.TOUR_STATE = "tour"; // when in joyride mode
|
Printer.TOUR_STATE = "tour"; // when in joyride mode
|
||||||
|
|
||||||
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being send to the printer, leaving will result in a incomplete 3D print";
|
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being sent to the printer, leaving will result in a incomplete 3D print";
|
||||||
|
|
||||||
this.temperature = 0;
|
this.temperature = 0;
|
||||||
this.targetTemperature = 0;
|
this.targetTemperature = 0;
|
||||||
@ -47,7 +48,7 @@ function Printer() {
|
|||||||
this.sendPrintPartTimeoutTime = 5000;
|
this.sendPrintPartTimeoutTime = 5000;
|
||||||
|
|
||||||
this.gcode; // gcode to be printed
|
this.gcode; // gcode to be printed
|
||||||
this.sendLength = 500; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
|
this.sendLength = 500; // max amount of gcode lines per post (limited because WiFi box can't handle too much)
|
||||||
|
|
||||||
this.retryDelay = 2000; // retry setTimout delay
|
this.retryDelay = 2000; // retry setTimout delay
|
||||||
this.retrySendPrintPartDelay; // retry setTimout instance
|
this.retrySendPrintPartDelay; // retry setTimout instance
|
||||||
@ -80,11 +81,7 @@ function Printer() {
|
|||||||
this.preheat = function() {
|
this.preheat = function() {
|
||||||
console.log("Printer:preheat");
|
console.log("Printer:preheat");
|
||||||
|
|
||||||
if( this.state == Printer.BUFFERING_STATE ||
|
if (this.state != Printer.IDLE_STATE) return;
|
||||||
this.state == Printer.PRINTING_STATE ||
|
|
||||||
this.state == Printer.STOPPING_STATE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
if (communicateWithWifibox) {
|
if (communicateWithWifibox) {
|
||||||
@ -131,8 +128,9 @@ function Printer() {
|
|||||||
console.log(" gcodeSize: ",gcodeSize);
|
console.log(" gcodeSize: ",gcodeSize);
|
||||||
|
|
||||||
if(gcodeSize > Printer.MAX_GCODE_SIZE) {
|
if(gcodeSize > Printer.MAX_GCODE_SIZE) {
|
||||||
alert("Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)");
|
var msg = "Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)";
|
||||||
console.log("Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)");
|
alert(msg);
|
||||||
|
console.log(msg);
|
||||||
|
|
||||||
this.overruleState(Printer.IDLE_STATE);
|
this.overruleState(Printer.IDLE_STATE);
|
||||||
this.startStatusCheckInterval();
|
this.startStatusCheckInterval();
|
||||||
@ -146,9 +144,11 @@ function Printer() {
|
|||||||
|
|
||||||
this.sendPrintPart(this.sendIndex, this.sendLength);
|
this.sendPrintPart(this.sendIndex, this.sendLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.byteSize = function(s){
|
this.byteSize = function(s){
|
||||||
return~-encodeURI(s).split(/%..|./).length;
|
return~-encodeURI(s).split(/%..|./).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendPrintPart = function(sendIndex,sendLength) {
|
this.sendPrintPart = function(sendIndex,sendLength) {
|
||||||
console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength);
|
console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength);
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ function Printer() {
|
|||||||
message.set("Doodle has been sent to printer...",Message.INFO,true);
|
message.set("Doodle has been sent to printer...",Message.INFO,true);
|
||||||
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||||
} else {
|
} else {
|
||||||
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
|
// only if the state hasn't been changed (by for example pressing stop) we send more gcode
|
||||||
|
|
||||||
//console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")");
|
//console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")");
|
||||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
||||||
@ -255,9 +255,10 @@ function Printer() {
|
|||||||
self.startStatusCheckInterval();
|
self.startStatusCheckInterval();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log ("Printer >> f:communicateWithWifibox() >> communicateWithWifibox is false, so not executing this function");
|
console.log ("Printer >> f:stop() >> communicateWithWifibox is false, so not executing this function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.startStatusCheckInterval = function() {
|
this.startStatusCheckInterval = function() {
|
||||||
console.log("Printer:startStatusCheckInterval");
|
console.log("Printer:startStatusCheckInterval");
|
||||||
self.checkStatus();
|
self.checkStatus();
|
||||||
@ -265,11 +266,13 @@ function Printer() {
|
|||||||
clearTimeout(self.retryCheckStatusDelay);
|
clearTimeout(self.retryCheckStatusDelay);
|
||||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stopStatusCheckInterval = function() {
|
this.stopStatusCheckInterval = function() {
|
||||||
console.log("Printer:stopStatusCheckInterval");
|
console.log("Printer:stopStatusCheckInterval");
|
||||||
clearTimeout(self.checkStatusDelay);
|
clearTimeout(self.checkStatusDelay);
|
||||||
clearTimeout(self.retryCheckStatusDelay);
|
clearTimeout(self.retryCheckStatusDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkStatus = function() {
|
this.checkStatus = function() {
|
||||||
//console.log("Printer:checkStatus");
|
//console.log("Printer:checkStatus");
|
||||||
this.stateOverruled = false;
|
this.stateOverruled = false;
|
||||||
@ -301,6 +304,7 @@ function Printer() {
|
|||||||
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleStatusUpdate = function(response) {
|
this.handleStatusUpdate = function(response) {
|
||||||
//console.log("Printer:handleStatusUpdate response: ",response);
|
//console.log("Printer:handleStatusUpdate response: ",response);
|
||||||
var data = response.data;
|
var data = response.data;
|
||||||
@ -332,6 +336,7 @@ function Printer() {
|
|||||||
}
|
}
|
||||||
$(document).trigger(Printer.UPDATE);
|
$(document).trigger(Printer.UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.overruleState = function(newState) {
|
this.overruleState = function(newState) {
|
||||||
this.stateOverruled = true;
|
this.stateOverruled = true;
|
||||||
console.log(" stateOverruled: ",this.stateOverruled);
|
console.log(" stateOverruled: ",this.stateOverruled);
|
||||||
@ -346,6 +351,7 @@ function Printer() {
|
|||||||
this.removeLeaveWarning = function() {
|
this.removeLeaveWarning = function() {
|
||||||
window.onbeforeunload = null;
|
window.onbeforeunload = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addLeaveWarning = function() {
|
this.addLeaveWarning = function() {
|
||||||
window.onbeforeunload = function() {
|
window.onbeforeunload = function() {
|
||||||
console.log("WARNING:"+Printer.ON_BEFORE_UNLOAD_MESSAGE);
|
console.log("WARNING:"+Printer.ON_BEFORE_UNLOAD_MESSAGE);
|
||||||
|
@ -21,10 +21,13 @@ var hasControl;
|
|||||||
var gcodeGenerateDelayer;
|
var gcodeGenerateDelayer;
|
||||||
var gcodeGenerateDelay = 50;
|
var gcodeGenerateDelay = 50;
|
||||||
|
|
||||||
|
|
||||||
var preheatDelay;
|
var preheatDelay;
|
||||||
var preheatDelayTime = 15*1000;
|
var preheatDelayTime = 15*1000;
|
||||||
|
|
||||||
|
var connectingHintDelay = null;
|
||||||
|
var connectingHintDelayTime = 20 * 1000;
|
||||||
|
|
||||||
|
|
||||||
function initButtonBehavior() {
|
function initButtonBehavior() {
|
||||||
console.log("f:initButtonBehavior");
|
console.log("f:initButtonBehavior");
|
||||||
|
|
||||||
@ -104,6 +107,7 @@ function initButtonBehavior() {
|
|||||||
function onLogo() {
|
function onLogo() {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onBtnAdd() {
|
function onBtnAdd() {
|
||||||
buttonGroupAdd.fadeToggle(BUTTON_GROUP_SHOW_DURATION);
|
buttonGroupAdd.fadeToggle(BUTTON_GROUP_SHOW_DURATION);
|
||||||
}
|
}
|
||||||
@ -201,7 +205,6 @@ function initButtonBehavior() {
|
|||||||
|
|
||||||
function stopPrint() {
|
function stopPrint() {
|
||||||
console.log("f:stopPrint() >> sendPrintCommands = " + sendPrintCommands);
|
console.log("f:stopPrint() >> sendPrintCommands = " + sendPrintCommands);
|
||||||
//if (!confirm("Weet je zeker dat je huidige print wilt stoppen?")) return;
|
|
||||||
if (sendPrintCommands) printer.stop();
|
if (sendPrintCommands) printer.stop();
|
||||||
//setState(Printer.STOPPING_STATE,printer.hasControl);
|
//setState(Printer.STOPPING_STATE,printer.hasControl);
|
||||||
printer.overruleState(Printer.STOPPING_STATE);
|
printer.overruleState(Printer.STOPPING_STATE);
|
||||||
@ -247,10 +250,6 @@ function print(e) {
|
|||||||
console.log("f:print >> not enough points!");
|
console.log("f:print >> not enough points!");
|
||||||
}
|
}
|
||||||
|
|
||||||
//alert("Je tekening zal nu geprint worden");
|
|
||||||
//$(".btnPrint").css("display","block");
|
|
||||||
|
|
||||||
|
|
||||||
// $.post("/doodle3d.of", { data:output }, function(data) {
|
// $.post("/doodle3d.of", { data:output }, function(data) {
|
||||||
// btnPrint.disabled = false;
|
// btnPrint.disabled = false;
|
||||||
// });
|
// });
|
||||||
@ -337,8 +336,6 @@ function resetTwist() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
|
|
||||||
|
|
||||||
setState(printer.state,printer.hasControl);
|
setState(printer.state,printer.hasControl);
|
||||||
|
|
||||||
thermometer.update(printer.temperature, printer.targetTemperature);
|
thermometer.update(printer.temperature, printer.targetTemperature);
|
||||||
@ -394,6 +391,7 @@ function setState(newState,newHasControl) {
|
|||||||
|
|
||||||
/* settings button */
|
/* settings button */
|
||||||
switch(newState) {
|
switch(newState) {
|
||||||
|
case Printer.CONNECTING_STATE: /* fall-through */
|
||||||
case Printer.IDLE_STATE:
|
case Printer.IDLE_STATE:
|
||||||
btnSettings.enable();
|
btnSettings.enable();
|
||||||
break;
|
break;
|
||||||
@ -421,18 +419,33 @@ function setState(newState,newHasControl) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(connectingHintDelay && newState != Printer.CONNECTING_STATE) {
|
||||||
|
clearTimeout(connectingHintDelay);
|
||||||
|
connectingHintDelay = null;
|
||||||
|
}
|
||||||
|
|
||||||
if(newState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
if(newState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||||
message.set("Lost connection to WiFi box",Message.ERROR);
|
message.set("Lost connection to WiFi box",Message.ERROR);
|
||||||
} else if(prevState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
} else if(prevState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||||
message.set("Connected to WiFi box",Message.INFO,true);
|
message.set("Connected to WiFi box",Message.INFO,true);
|
||||||
} else if(newState == Printer.DISCONNECTED_STATE) {
|
} else if(newState == Printer.DISCONNECTED_STATE) {
|
||||||
message.set("Printer disconnected",Message.WARNING,true);
|
message.set("Printer disconnected",Message.WARNING,true);
|
||||||
|
} else if(newState == Printer.CONNECTING_STATE) {
|
||||||
|
message.set("Printer connecting...",Message.INFO,false);
|
||||||
|
if (prevState != Printer.CONNECTING_STATE) { //enable 'watchdog' if we entered from a different state
|
||||||
|
clearTimeout(connectingHintDelay);
|
||||||
|
connectingHintDelay = setTimeout(function() {
|
||||||
|
message.set("Printer still not connected, did you<br/>select the correct printer type?", Message.WARNING, false);
|
||||||
|
connectingHintDelay = null;
|
||||||
|
}, connectingHintDelayTime);
|
||||||
|
}
|
||||||
} else if(prevState == Printer.DISCONNECTED_STATE && newState == Printer.IDLE_STATE ||
|
} else if(prevState == Printer.DISCONNECTED_STATE && newState == Printer.IDLE_STATE ||
|
||||||
prevState == Printer.UNKNOWN_STATE && newState == Printer.IDLE_STATE) {
|
prevState == Printer.UNKNOWN_STATE && newState == Printer.IDLE_STATE ||
|
||||||
|
prevState == Printer.CONNECTING_STATE && newState == Printer.IDLE_STATE) {
|
||||||
message.set("Printer connected",Message.INFO,true);
|
message.set("Printer connected",Message.INFO,true);
|
||||||
console.log(" preheat: ",settings["printer.heatup.enabled"]);
|
console.log(" preheat: ",settings["printer.heatup.enabled"]);
|
||||||
if(settings["printer.heatup.enabled"]) {
|
if(settings["printer.heatup.enabled"]) {
|
||||||
// HACK: we delay the preheat because the driver needs time to connect
|
// HACK: we delay the preheat because the makerbot driver needs time to connect
|
||||||
clearTimeout(preheatDelay);
|
clearTimeout(preheatDelay);
|
||||||
preheatDelay = setTimeout(printer.preheat,preheatDelayTime); // retry after delay
|
preheatDelay = setTimeout(printer.preheat,preheatDelayTime); // retry after delay
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function UpdatePanel() {
|
function UpdatePanel() {
|
||||||
|
var _form = new FormPanel();
|
||||||
|
|
||||||
this.wifiboxURL;
|
this.wifiboxURL;
|
||||||
this.element;
|
this.element;
|
||||||
|
|
||||||
@ -21,6 +23,8 @@ function UpdatePanel() {
|
|||||||
this.canUpdate = false;
|
this.canUpdate = false;
|
||||||
this.currentVersion = "";
|
this.currentVersion = "";
|
||||||
this.newestVersion;
|
this.newestVersion;
|
||||||
|
this.currentReleaseDate;
|
||||||
|
this.newestReleaseDate;
|
||||||
this.progress;
|
this.progress;
|
||||||
this.imageSize;
|
this.imageSize;
|
||||||
var _inAccessPointMode;
|
var _inAccessPointMode;
|
||||||
@ -29,7 +33,7 @@ function UpdatePanel() {
|
|||||||
UpdatePanel.NONE = 1; // default state
|
UpdatePanel.NONE = 1; // default state
|
||||||
UpdatePanel.DOWNLOADING = 2;
|
UpdatePanel.DOWNLOADING = 2;
|
||||||
UpdatePanel.DOWNLOAD_FAILED = 3;
|
UpdatePanel.DOWNLOAD_FAILED = 3;
|
||||||
UpdatePanel.IMAGE_READY = 4; // download successfull and checked
|
UpdatePanel.IMAGE_READY = 4; // download successful and checked
|
||||||
UpdatePanel.INSTALLING = 5;
|
UpdatePanel.INSTALLING = 5;
|
||||||
UpdatePanel.INSTALLED = 6;
|
UpdatePanel.INSTALLED = 6;
|
||||||
UpdatePanel.INSTALL_FAILED = 7;
|
UpdatePanel.INSTALL_FAILED = 7;
|
||||||
@ -40,28 +44,43 @@ function UpdatePanel() {
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.init = function(wifiboxURL,updatePanelElement) {
|
this.init = function(wifiboxURL,updatePanelElement) {
|
||||||
|
_form.init(wifiboxURL,wifiboxURL,updatePanelElement);
|
||||||
|
|
||||||
this.wifiboxURL = wifiboxURL;
|
this.wifiboxURL = wifiboxURL;
|
||||||
|
|
||||||
this.element = updatePanelElement;
|
this.element = updatePanelElement;
|
||||||
this.retainCheckbox = this.element.find("#retainConfiguration");
|
this.retainCheckbox = this.element.find("#retainConfiguration");
|
||||||
|
this.includeBetasCheckbox = this.element.find("#includeBetas");
|
||||||
this.btnUpdate = this.element.find("#update");
|
this.btnUpdate = this.element.find("#update");
|
||||||
this.statusDisplay = this.element.find("#updateState");
|
this.statusDisplay = this.element.find("#updateState");
|
||||||
this.infoDisplay = this.element.find("#updateInfo");
|
this.infoDisplay = this.element.find("#updateInfo");
|
||||||
|
|
||||||
this.retainCheckbox.change(this.retainChanged);
|
this.retainCheckbox.change(this.retainChanged);
|
||||||
|
this.includeBetasCheckbox.change(this.includeBetasChanged);
|
||||||
this.btnUpdate.click(this.update);
|
this.btnUpdate.click(this.update);
|
||||||
|
|
||||||
this.checkStatus(false);
|
this.checkStatus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.retainChanged = function(e) {
|
this.retainChanged = function(e) {
|
||||||
//console.log("UpdatePanel:retainChanged");
|
//console.log("UpdatePanel:retainChanged");
|
||||||
|
//this call ensures that the update button gets enabled if (!retainChanged && !canUpdate)
|
||||||
self.setState(self.state,true);
|
self.setState(self.state,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.includeBetasChanged = function() {
|
||||||
|
//console.log("UpdatePanel:includeBetasChanged");
|
||||||
|
_form.saveSettings(_form.readForm(),function(validated, data) {
|
||||||
|
if(validated) self.checkStatus(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.update = function() {
|
this.update = function() {
|
||||||
console.log("UpdatePanel:update");
|
console.log("UpdatePanel:update");
|
||||||
self.downloadUpdate();
|
self.downloadUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.downloadUpdate = function() {
|
this.downloadUpdate = function() {
|
||||||
console.log("UpdatePanel:downloadUpdate");
|
console.log("UpdatePanel:downloadUpdate");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -77,6 +96,7 @@ function UpdatePanel() {
|
|||||||
self.setState(UpdatePanel.DOWNLOADING);
|
self.setState(UpdatePanel.DOWNLOADING);
|
||||||
self.startCheckingStatus();
|
self.startCheckingStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.installUpdate = function() {
|
this.installUpdate = function() {
|
||||||
console.log("UpdatePanel:installUpdate");
|
console.log("UpdatePanel:installUpdate");
|
||||||
|
|
||||||
@ -103,15 +123,18 @@ function UpdatePanel() {
|
|||||||
self.installedDelayer = setTimeout(function() { self.setState(UpdatePanel.INSTALLED) },self.installedDelay);
|
self.installedDelayer = setTimeout(function() { self.setState(UpdatePanel.INSTALLED) },self.installedDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.startCheckingStatus = function() {
|
this.startCheckingStatus = function() {
|
||||||
clearTimeout(self.statusCheckDelayer);
|
clearTimeout(self.statusCheckDelayer);
|
||||||
clearTimeout(self.retryDelayer);
|
clearTimeout(self.retryDelayer);
|
||||||
self.statusCheckDelayer = setTimeout(function() { self.checkStatus(true) },self.statusCheckInterval);
|
self.statusCheckDelayer = setTimeout(function() { self.checkStatus(true) },self.statusCheckInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.stopCheckingStatus = function() {
|
this.stopCheckingStatus = function() {
|
||||||
clearTimeout(self.statusCheckDelayer);
|
clearTimeout(self.statusCheckDelayer);
|
||||||
clearTimeout(self.retryDelayer);
|
clearTimeout(self.retryDelayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkStatus = function(keepChecking) {
|
this.checkStatus = function(keepChecking) {
|
||||||
if (!communicateWithWifibox) return;
|
if (!communicateWithWifibox) return;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -136,6 +159,8 @@ function UpdatePanel() {
|
|||||||
if(response.status != "error") {
|
if(response.status != "error") {
|
||||||
var data = response.data;
|
var data = response.data;
|
||||||
self.handleStatusData(data);
|
self.handleStatusData(data);
|
||||||
|
} else {
|
||||||
|
console.log("API update/status call returned an error: '" + response.msg + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
@ -147,13 +172,19 @@ function UpdatePanel() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.handleStatusData = function(data) {
|
this.handleStatusData = function(data) {
|
||||||
//console.log("UpdatePanel:handleStatusData");
|
//console.log("UpdatePanel:handleStatusData");
|
||||||
|
//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);
|
||||||
|
|
||||||
self.canUpdate = data.can_update;
|
self.canUpdate = data.can_update;
|
||||||
|
|
||||||
if(self.currentVersion != data.current_version || self.newestVersion != data.newest_version) {
|
if(self.currentVersion != data.current_version || self.newestVersion != data.newest_version) {
|
||||||
self.currentVersion = data.current_version;
|
self.currentVersion = data.current_version;
|
||||||
self.newestVersion = data.newest_version;
|
self.newestVersion = data.newest_version;
|
||||||
|
self.currentReleaseDate = data.current_release_date; // not always available (for older versions)
|
||||||
|
self.newestReleaseDate = data.newest_release_date; // not always available (for older versions)
|
||||||
self.updateInfoDisplay();
|
self.updateInfoDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +192,7 @@ function UpdatePanel() {
|
|||||||
self.progress = data.progress; // not always available
|
self.progress = data.progress; // not always available
|
||||||
self.imageSize = data.image_size; // not always available
|
self.imageSize = data.image_size; // not always available
|
||||||
|
|
||||||
self.setState(data.state_code);
|
self.setState(data.state_code, refreshUI);
|
||||||
|
|
||||||
switch(this.state){
|
switch(this.state){
|
||||||
case UpdatePanel.IMAGE_READY:
|
case UpdatePanel.IMAGE_READY:
|
||||||
@ -169,6 +200,7 @@ function UpdatePanel() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState = function(newState,refresh) {
|
this.setState = function(newState,refresh) {
|
||||||
//console.log("UpdatePanel:setState");
|
//console.log("UpdatePanel:setState");
|
||||||
if(!refresh && this.state == newState) return;
|
if(!refresh && this.state == newState) return;
|
||||||
@ -205,13 +237,25 @@ function UpdatePanel() {
|
|||||||
}
|
}
|
||||||
this.updateStatusDisplay();
|
this.updateStatusDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateStatusDisplay = function() {
|
this.updateStatusDisplay = function() {
|
||||||
var text = "";
|
var text = "";
|
||||||
if(self.newestVersion != undefined) {
|
if(self.newestVersion != undefined) {
|
||||||
switch(this.state){
|
switch(this.state){
|
||||||
case UpdatePanel.NONE:
|
case UpdatePanel.NONE:
|
||||||
if(self.canUpdate) {
|
if(self.canUpdate) {
|
||||||
text = "Update(s) available.";
|
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.";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
text = "You're up to date.";
|
text = "You're up to date.";
|
||||||
}
|
}
|
||||||
@ -229,8 +273,8 @@ function UpdatePanel() {
|
|||||||
text = "Installing update... (will take a minute)";
|
text = "Installing update... (will take a minute)";
|
||||||
break;
|
break;
|
||||||
case UpdatePanel.INSTALLED:
|
case UpdatePanel.INSTALLED:
|
||||||
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 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>.";
|
text = "Update complete, please <a href='javascript:location.reload(true);'>refresh Page</a>.";
|
||||||
break;
|
break;
|
||||||
case UpdatePanel.INSTALL_FAILED:
|
case UpdatePanel.INSTALL_FAILED:
|
||||||
text = "Installing update failed.";
|
text = "Installing update failed.";
|
||||||
@ -245,18 +289,36 @@ function UpdatePanel() {
|
|||||||
}
|
}
|
||||||
this.statusDisplay.html(text);
|
this.statusDisplay.html(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateInfoDisplay = function() {
|
this.updateInfoDisplay = function() {
|
||||||
var html = 'Current version: ' + self.currentVersion +
|
var html = 'Current version: ' + self.currentVersion;
|
||||||
' (<a target="d3d-curr-relnotes" href="ReleaseNotes.html">release notes</a>). ';
|
if (self.currentReleaseDate) html += '; released: ' + self.formatDate(self.currentReleaseDate);
|
||||||
|
html += ' (<a target="d3d-curr-relnotes" href="ReleaseNotes.html">release notes</a>).';
|
||||||
|
|
||||||
if(self.canUpdate) {
|
if(self.canUpdate) {
|
||||||
html += 'Latest version: ' + self.newestVersion +
|
html += '<br/>Latest version: ' + self.newestVersion;
|
||||||
' (<a target="d3d-new-relnotes" href="http://doodle3d.com/updates/images/ReleaseNotes.md">release notes</a>).';
|
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>).';
|
||||||
}
|
}
|
||||||
self.infoDisplay.html(html);
|
self.infoDisplay.html(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.setInAccessPointMode = function(inAccessPointMode) {
|
this.setInAccessPointMode = function(inAccessPointMode) {
|
||||||
_inAccessPointMode = inAccessPointMode;
|
_inAccessPointMode = inAccessPointMode;
|
||||||
self.updateStatusDisplay();
|
self.updateStatusDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
var abbrMonths = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Sep', 'Aug', 'Oct', 'Nov', 'Dec' ];
|
||||||
|
return abbrMonths[fields[1] - 1] + " " + fields[2] + ", " + fields[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.versionIsBeta = function(version) {
|
||||||
|
return version ? /.*-.*/g.test(version) : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#message {
|
#message {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
text-align: right;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ form {
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input {
|
form input {
|
||||||
margin: 1px;
|
margin: 1px;
|
||||||
}
|
}
|
||||||
@ -10,6 +11,7 @@ body,th,td {
|
|||||||
font-family: Helvetica, Arial, "Nimbus Sans L", sans-serif;
|
font-family: Helvetica, Arial, "Nimbus Sans L", sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settingsContainer {
|
.settingsContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
/*min-width: 370px;*/
|
/*min-width: 370px;*/
|
||||||
@ -29,12 +31,14 @@ form fieldset {
|
|||||||
padding: 8px;
|
padding: 8px;
|
||||||
/*padding-right: 8px;*/
|
/*padding-right: 8px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset fieldset {
|
form fieldset fieldset {
|
||||||
max-width: 580px;
|
max-width: 580px;
|
||||||
margin: 15px 0 5px 0;
|
margin: 15px 0 5px 0;
|
||||||
clear: left;
|
clear: left;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.collapsed {
|
form fieldset.collapsed {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
-webkit-border-radius: 0;
|
-webkit-border-radius: 0;
|
||||||
@ -42,25 +46,33 @@ form fieldset.collapsed {
|
|||||||
border-width: 1px 0 0 0;
|
border-width: 1px 0 0 0;
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.collapsible {
|
form fieldset.collapsible {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.collapsible div {
|
form fieldset.collapsible div {
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset legend {
|
form fieldset legend {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.collapsible legend {
|
form fieldset.collapsible legend {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.expanded legend {
|
form fieldset.expanded legend {
|
||||||
background: transparent url(../img/buttons/expanded.gif) no-repeat center left;
|
background: transparent url(../img/buttons/expanded.gif) no-repeat
|
||||||
|
center left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form fieldset.collapsed legend {
|
form fieldset.collapsed legend {
|
||||||
background: transparent url(../img/buttons/collapsed.gif) no-repeat center left;
|
background: transparent url(../img/buttons/collapsed.gif) no-repeat
|
||||||
|
center left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form label {
|
form label {
|
||||||
@ -70,22 +82,30 @@ form label {
|
|||||||
margin: 1px 0 0 0;
|
margin: 1px 0 0 0;
|
||||||
clear: left;
|
clear: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form div {
|
form div {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
form input[type="text"], form input[type="number"], form input[type="password"] {
|
|
||||||
|
form input[type="text"],form input[type="number"], form input[type="password"]
|
||||||
|
{
|
||||||
border: 1px solid rgb(144, 192, 255);
|
border: 1px solid rgb(144, 192, 255);
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
-webkit-border-radius: 4px;
|
-webkit-border-radius: 4px;
|
||||||
-moz-border-radius: 4px;
|
-moz-border-radius: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
form input[type="text"].small, form input[type="number"].small, form input[type="password"].small {
|
|
||||||
|
form input[type="text"].small,form input[type="number"].small, form input[type="password"].small
|
||||||
|
{
|
||||||
width: 50px;
|
width: 50px;
|
||||||
}
|
}
|
||||||
form input[type="text"].large, form input[type="number"].large, form input[type="password"].large {
|
|
||||||
|
form input[type="text"].large,form input[type="number"].large, form input[type="password"].large
|
||||||
|
{
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form input[type="radio"] {
|
form input[type="radio"] {
|
||||||
margin: 4px 4px 0 0;
|
margin: 4px 4px 0 0;
|
||||||
}
|
}
|
||||||
@ -96,21 +116,25 @@ form textarea {
|
|||||||
-moz-border-radius: 5px;
|
-moz-border-radius: 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form .startgcode_left {
|
form .startgcode_left {
|
||||||
float: left;
|
float: left;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form textarea.gcode {
|
form textarea.gcode {
|
||||||
width: 252px;
|
width: 252px;
|
||||||
/*max-width: 262px;*/
|
/*max-width: 262px;*/
|
||||||
/*min-width: 200px;*/
|
/*min-width: 200px;*/
|
||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form small {
|
form small {
|
||||||
margin: 3px 0 0 0;
|
margin: 3px 0 0 0;
|
||||||
display: block;
|
display: block;
|
||||||
clear: left;
|
clear: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
form .button {
|
form .button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
@ -122,22 +146,27 @@ form #passwordLabel, form #password {
|
|||||||
form input.error, form textarea.error, form select.error {
|
form input.error, form textarea.error, form select.error {
|
||||||
border: #f00 solid 2px;
|
border: #f00 solid 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form .errorMsg {
|
form .errorMsg {
|
||||||
color: #f00;
|
color: #f00;
|
||||||
margin: 0 0 0 1em;
|
margin: 0 0 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
form .intro {
|
form .intro {
|
||||||
margin: 0 0 0.5em 0;
|
margin: 0 0 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form dl {
|
form dl {
|
||||||
margin: 0.5em 0 0 0;
|
margin: 0.5em 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
form dl dt {
|
form dl dt {
|
||||||
float: left;
|
float: left;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
width: 10em;
|
width: 10em;
|
||||||
}
|
}
|
||||||
#updatePanel #retainConfigurationLabel {
|
|
||||||
|
#updatePanel #retainConfigurationLabel, #updatePanel #includeBetasLabel {
|
||||||
display: inline;
|
display: inline;
|
||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
@ -5,10 +5,13 @@
|
|||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
|
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui">
|
||||||
|
|
||||||
<link rel="icon" type="image/ico" href="./favicon_alt.ico"/>
|
<link rel="icon" type="image/ico" href="./favicon_alt.ico"/>
|
||||||
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png"/>
|
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png"/>
|
||||||
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" sizes="144x144" />
|
<link rel="apple-touch-icon-precomposed" href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" sizes="144x144" />
|
||||||
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
|
||||||
<link href="css/styles.min.css" rel="stylesheet" media="screen">
|
<link href="css/styles.min.css" rel="stylesheet" media="screen">
|
||||||
<link href="css/debug.min.css" rel="stylesheet" media="screen">
|
<link href="css/debug.min.css" rel="stylesheet" media="screen">
|
||||||
|
|
||||||
@ -63,8 +66,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="message"></div>
|
|
||||||
|
|
||||||
<!-- center panel -->
|
<!-- center panel -->
|
||||||
<div id="centerpanel">
|
<div id="centerpanel">
|
||||||
|
|
||||||
@ -153,6 +154,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="message"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="portrait">
|
<div id="portrait">
|
||||||
|
@ -165,8 +165,9 @@
|
|||||||
|
|
||||||
<fieldset id="updatePanel">
|
<fieldset id="updatePanel">
|
||||||
<legend>Update</legend>
|
<legend>Update</legend>
|
||||||
<input id="retainConfiguration" type="checkbox" name="" value="retainConfiguration" checked="true"> <label for="retainConfiguration" id="retainConfigurationLabel">Preserve personal sketches and settings</label>
|
<input id="retainConfiguration" type="checkbox" name="" value="retainConfiguration" checked="true"> <label for="retainConfiguration" id="retainConfigurationLabel">Preserve personal sketches and settings</label><br/>
|
||||||
<br/><br/>
|
<input id="includeBetas" type="checkbox" name="doodle3d.update.includeBetas" value="includeBetas"> <label for="includeBetas" id="includeBetasLabel">Include beta releases (<a target="beta-info" href="http://doodle3d.com/help/beta">read more</a>)</label><br/>
|
||||||
|
<br/>
|
||||||
<input type="button" name="update" value="Update" class="button" id="update"/>
|
<input type="button" name="update" value="Update" class="button" id="update"/>
|
||||||
<span id="updateState"></span><br/>
|
<span id="updateState"></span><br/>
|
||||||
<small id="updateInfo"></small>
|
<small id="updateInfo"></small>
|
||||||
|
Loading…
Reference in New Issue
Block a user