Track browser tab visibility, only activate webcam/gcode viewer when visible
This might help with #1065 if indeed is related to background tab suspending behaviours in browsers, but is a completely blind guess at this point since I still have not been able to reproduce that issue myself.
This commit is contained in:
parent
50c3f99a42
commit
720cdadfbb
5 changed files with 135 additions and 28 deletions
|
|
@ -379,7 +379,7 @@ GCODE.renderer = (function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
var drawLayer = function(layerNum, fromProgress, toProgress, isNotCurrentLayer){
|
var drawLayer = function(layerNum, fromProgress, toProgress, isNotCurrentLayer){
|
||||||
console.log("Drawing layer " + layerNum + " from " + fromProgress + " to " + toProgress + " (current: " + !isNotCurrentLayer + ")");
|
log.trace("Drawing layer " + layerNum + " from " + fromProgress + " to " + toProgress + " (current: " + !isNotCurrentLayer + ")");
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,71 @@ $(function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//~~ some CoreUI specific stuff we put into OctoPrint.coreui
|
||||||
|
|
||||||
|
OctoPrint.coreui = (function() {
|
||||||
|
var exports = {
|
||||||
|
browserTabVisibility: undefined,
|
||||||
|
selectedTab: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
var browserVisibilityCallbacks = [];
|
||||||
|
|
||||||
|
var getHiddenProp = function() {
|
||||||
|
var prefixes = ["webkit", "moz", "ms", "o"];
|
||||||
|
|
||||||
|
// if "hidden" is natively supported just return it
|
||||||
|
if ("hidden" in document) {
|
||||||
|
return "hidden"
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise loop over all the known prefixes until we find one
|
||||||
|
var vendorPrefix = _.find(prefixes, function(prefix) {
|
||||||
|
return (prefix + "Hidden" in document);
|
||||||
|
});
|
||||||
|
if (vendorPrefix !== undefined) {
|
||||||
|
return vendorPrefix + "Hidden";
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing found
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isHidden = function() {
|
||||||
|
var prop = getHiddenProp();
|
||||||
|
if (!prop) return false;
|
||||||
|
|
||||||
|
return document[prop];
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateBrowserVisibility = function() {
|
||||||
|
var visible = !isHidden();
|
||||||
|
exports.browserTabVisible = visible;
|
||||||
|
_.each(browserVisibilityCallbacks, function(callback) {
|
||||||
|
callback(visible);
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// register for browser visibility tracking
|
||||||
|
|
||||||
|
var prop = getHiddenProp();
|
||||||
|
if (!prop) return undefined;
|
||||||
|
|
||||||
|
var eventName = prop.replace(/[H|h]idden/, "") + "visibilitychange";
|
||||||
|
document.addEventListener(eventName, updateBrowserVisibility);
|
||||||
|
|
||||||
|
updateBrowserVisibility();
|
||||||
|
|
||||||
|
// exports
|
||||||
|
|
||||||
|
exports.isVisible = function() { return !isHidden() };
|
||||||
|
exports.onBrowserVisibilityChange = function(callback) {
|
||||||
|
browserVisibilityCallbacks.push(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
return exports;
|
||||||
|
})();
|
||||||
|
|
||||||
//~~ AJAX setup
|
//~~ AJAX setup
|
||||||
|
|
||||||
// work around a stupid iOS6 bug where ajax requests get cached and only work once, as described at
|
// work around a stupid iOS6 bug where ajax requests get cached and only work once, as described at
|
||||||
|
|
@ -410,11 +475,17 @@ $(function() {
|
||||||
$('.nav-pills, .nav-tabs').tabdrop();
|
$('.nav-pills, .nav-tabs').tabdrop();
|
||||||
|
|
||||||
// Allow components to react to tab change
|
// Allow components to react to tab change
|
||||||
|
var onTabChange = function(current, previous) {
|
||||||
|
log.debug("Selected OctoPrint tab changed: previous = " + previous + ", current = " + current);
|
||||||
|
OctoPrint.coreui.selectedTab = current;
|
||||||
|
callViewModels(allViewModels, "onTabChange", [current, previous]);
|
||||||
|
};
|
||||||
|
|
||||||
var tabs = $('#tabs a[data-toggle="tab"]');
|
var tabs = $('#tabs a[data-toggle="tab"]');
|
||||||
tabs.on('show', function (e) {
|
tabs.on('show', function (e) {
|
||||||
var current = e.target.hash;
|
var current = e.target.hash;
|
||||||
var previous = e.relatedTarget.hash;
|
var previous = e.relatedTarget.hash;
|
||||||
callViewModels(allViewModels, "onTabChange", [current, previous]);
|
onTabChange(current, previous);
|
||||||
});
|
});
|
||||||
|
|
||||||
tabs.on('shown', function (e) {
|
tabs.on('shown', function (e) {
|
||||||
|
|
@ -423,6 +494,8 @@ $(function() {
|
||||||
callViewModels(allViewModels, "onAfterTabChange", [current, previous]);
|
callViewModels(allViewModels, "onAfterTabChange", [current, previous]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onTabChange(OCTOPRINT_INITIAL_TAB);
|
||||||
|
|
||||||
// Fix input element click problems on dropdowns
|
// Fix input element click problems on dropdowns
|
||||||
$(".dropdown input, .dropdown label").click(function(e) {
|
$(".dropdown input, .dropdown label").click(function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
@ -516,7 +589,14 @@ $(function() {
|
||||||
callViewModels(allViewModels, "onAllBound", [allViewModels]);
|
callViewModels(allViewModels, "onAllBound", [allViewModels]);
|
||||||
log.info("... binding done");
|
log.info("... binding done");
|
||||||
|
|
||||||
|
// startup complete
|
||||||
callViewModels(allViewModels, "onStartupComplete");
|
callViewModels(allViewModels, "onStartupComplete");
|
||||||
|
|
||||||
|
// make sure we can track the browser tab visibility
|
||||||
|
OctoPrint.coreui.onBrowserVisibilityChange(function(status) {
|
||||||
|
log.debug("Browser tab is now " + (status ? "visible" : "hidden"));
|
||||||
|
callViewModels(allViewModels, "onBrowserTabVisibilityChange", [status]);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!_.has(viewModelMap, "settingsViewModel")) {
|
if (!_.has(viewModelMap, "settingsViewModel")) {
|
||||||
|
|
|
||||||
|
|
@ -357,31 +357,51 @@ $(function() {
|
||||||
|
|
||||||
self.onSettingsBeforeSave = self.updateRotatorWidth;
|
self.onSettingsBeforeSave = self.updateRotatorWidth;
|
||||||
|
|
||||||
|
self._disableWebcam = function() {
|
||||||
|
// only disable webcam stream if tab is out of focus for more than 5s, otherwise we might cause
|
||||||
|
// more load by the constant connection creation than by the actual webcam stream
|
||||||
|
self.webcamDisableTimeout = setTimeout(function () {
|
||||||
|
$("#webcam_image").attr("src", "");
|
||||||
|
}, 5000);
|
||||||
|
};
|
||||||
|
|
||||||
|
self._enableWebcam = function() {
|
||||||
|
if (OctoPrint.coreui.selectedTab != "#control" || !OctoPrint.coreui.browserTabVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.webcamDisableTimeout != undefined) {
|
||||||
|
clearTimeout(self.webcamDisableTimeout);
|
||||||
|
}
|
||||||
|
var webcamImage = $("#webcam_image");
|
||||||
|
var currentSrc = webcamImage.attr("src");
|
||||||
|
if (currentSrc === undefined || currentSrc.trim() == "") {
|
||||||
|
var newSrc = CONFIG_WEBCAM_STREAM;
|
||||||
|
if (CONFIG_WEBCAM_STREAM.lastIndexOf("?") > -1) {
|
||||||
|
newSrc += "&";
|
||||||
|
} else {
|
||||||
|
newSrc += "?";
|
||||||
|
}
|
||||||
|
newSrc += new Date().getTime();
|
||||||
|
|
||||||
|
self.updateRotatorWidth();
|
||||||
|
webcamImage.attr("src", newSrc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.onTabChange = function (current, previous) {
|
self.onTabChange = function (current, previous) {
|
||||||
if (current == "#control") {
|
if (current == "#control") {
|
||||||
if (self.webcamDisableTimeout != undefined) {
|
self._enableWebcam();
|
||||||
clearTimeout(self.webcamDisableTimeout);
|
|
||||||
}
|
|
||||||
var webcamImage = $("#webcam_image");
|
|
||||||
var currentSrc = webcamImage.attr("src");
|
|
||||||
if (currentSrc === undefined || currentSrc.trim() == "") {
|
|
||||||
var newSrc = CONFIG_WEBCAM_STREAM;
|
|
||||||
if (CONFIG_WEBCAM_STREAM.lastIndexOf("?") > -1) {
|
|
||||||
newSrc += "&";
|
|
||||||
} else {
|
|
||||||
newSrc += "?";
|
|
||||||
}
|
|
||||||
newSrc += new Date().getTime();
|
|
||||||
|
|
||||||
self.updateRotatorWidth();
|
|
||||||
webcamImage.attr("src", newSrc);
|
|
||||||
}
|
|
||||||
} else if (previous == "#control") {
|
} else if (previous == "#control") {
|
||||||
// only disable webcam stream if tab is out of focus for more than 5s, otherwise we might cause
|
self._disableWebcam();
|
||||||
// more load by the constant connection creation than by the actual webcam stream
|
}
|
||||||
self.webcamDisableTimeout = setTimeout(function () {
|
};
|
||||||
$("#webcam_image").attr("src", "");
|
|
||||||
}, 5000);
|
self.onBrowserTabVisibilityChange = function(status) {
|
||||||
|
if (status) {
|
||||||
|
self._enableWebcam();
|
||||||
|
} else {
|
||||||
|
self._disableWebcam();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ $(function() {
|
||||||
if(self.loadedFilename
|
if(self.loadedFilename
|
||||||
&& self.loadedFilename == data.job.file.name
|
&& self.loadedFilename == data.job.file.name
|
||||||
&& self.loadedFileDate == data.job.file.date) {
|
&& self.loadedFileDate == data.job.file.date) {
|
||||||
if (self.tabActive && self.currentlyPrinting && self.renderer_syncProgress() && !self.waitForApproval()) {
|
if (OctoPrint.coreui.browserTabVisible && self.tabActive && self.currentlyPrinting && self.renderer_syncProgress() && !self.waitForApproval()) {
|
||||||
var cmdIndex = GCODE.gCodeReader.getCmdIndexForPercentage(data.progress.completion);
|
var cmdIndex = GCODE.gCodeReader.getCmdIndexForPercentage(data.progress.completion);
|
||||||
if(cmdIndex){
|
if(cmdIndex){
|
||||||
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
||||||
|
|
@ -502,12 +502,11 @@ $(function() {
|
||||||
|
|
||||||
self.onBeforeBinding = function() {
|
self.onBeforeBinding = function() {
|
||||||
self.initialize();
|
self.initialize();
|
||||||
}
|
};
|
||||||
|
|
||||||
self.onTabChange = function(current, previous) {
|
self.onTabChange = function(current, previous) {
|
||||||
self.tabActive = current == "#gcode";
|
self.tabActive = current == "#gcode";
|
||||||
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OCTOPRINT_VIEWMODELS.push([
|
OCTOPRINT_VIEWMODELS.push([
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,12 @@
|
||||||
var OCTOPRINT_VIEWMODELS = [];
|
var OCTOPRINT_VIEWMODELS = [];
|
||||||
var ADDITIONAL_VIEWMODELS = [];
|
var ADDITIONAL_VIEWMODELS = [];
|
||||||
var OCTOPRINT_ADDITIONAL_BINDINGS = [];
|
var OCTOPRINT_ADDITIONAL_BINDINGS = [];
|
||||||
|
|
||||||
|
{% if templates.tab.order %}
|
||||||
|
{% set first_tab = templates.tab.order[0] %}
|
||||||
|
{% set entry, data = templates.tab.entries[first_tab] %}
|
||||||
|
var OCTOPRINT_INITIAL_TAB = "#{{ data._div }}";
|
||||||
|
{% else %}
|
||||||
|
var OCTOPRINT_INITIAL_TAB = undefined;
|
||||||
|
{% endif %}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue