VulpesOS/gaia/apps/calendar/js/time_observer.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

108 lines
2.8 KiB
JavaScript
Executable file

define(function(require, exports, module) {
'use strict';
// this module abstracts minute and day changes, it should be used by all the
// views that needs to listen for time changes (ie. update current time/date).
// listeners are enabled/disabled when the document visibility changes,
// reducing battery usage and making sure we always display the proper value.
// ---
// XXX: we don't listen to moztimechange here because the app forces a restart
// when the time changes; even if the app did not restart we would still need
// to trigger a refresh of most of the views (timezone affects the way we
// busytimes are rendered in all the views, even the view/edit event views)
// see: https://bugzilla.mozilla.org/show_bug.cgi?id=1093016#c9
var EventEmitter2 = require('ext/eventemitter2');
exports = module.exports = new EventEmitter2();
exports.on = function() {
EventEmitter2.prototype.on.apply(this, arguments);
this._start();
};
exports.once = function() {
EventEmitter2.prototype.once.apply(this, arguments);
this._start();
};
exports.off = function() {
EventEmitter2.prototype.off.apply(this, arguments);
this._autoStop();
};
exports.removeAllListeners = function() {
EventEmitter2.prototype.removeAllListeners.apply(this, arguments);
this._autoStop();
};
exports._autoStop = function() {
if (!this._hasListeners()) {
this._stop();
}
};
exports._hasListeners = function() {
return this.listeners('day').length > 0 ||
this.listeners('minute').length > 0;
};
exports._timeout = null;
exports._prevTick = null;
exports._start = function() {
if (this._timeout || !this._hasListeners()) {
return;
}
this._prevTick = new Date();
this._timeout = setTimeout(this._tick, this._nextMinute());
};
exports._stop = function() {
if (this._timeout) {
window.clearTimeout(this._timeout);
this._timeout = null;
}
};
exports._tick = function() {
this._stop();
this._exec();
this._start();
}.bind(exports);
exports._nextMinute = function() {
var now = new Date();
return (60 - now.getSeconds()) * 1000;
};
exports._exec = function() {
var now = new Date();
var prev = this._prevTick;
if (prev.getMinutes() !== now.getMinutes()) {
this.emit('minute');
}
if (prev.getDate() !== now.getDate()) {
this.emit('day');
}
};
exports.init = function() {
document.addEventListener('visibilitychange', () => {
exports._toggleStatusOnVisibilityChange(document.hidden);
});
exports._start();
};
exports._toggleStatusOnVisibilityChange = function(hidden) {
// we trigger an update as soon as document is visible to avoid issues with
// timer not being fired (eg. timer was disabled and day/minute changed while
// app was hidden)
if (!hidden) {
exports._exec();
}
var method = hidden ? '_stop' : '_start';
exports[method]();
};
});