cherry-pick(#6885): Synchronize timers between multiple users (#6886)

* created a throttle util and using it in timer plugin to throttle refreshing the timer domain object

* Simplify timer logic

* Clarify code a little

* refactor: lint:fix

* Fix linting issue

---------

Co-authored-by: Andrew Henry <akhenry@gmail.com>
Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
This commit is contained in:
Jesse Mazzella 2023-08-02 16:45:47 -07:00 committed by GitHub
parent 796616fe3f
commit 492e8055e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 41 deletions

View File

@ -43,9 +43,11 @@
<script>
import raf from 'utils/raf';
import throttle from '../../../utils/throttle';
const moment = require('moment-timezone');
const momentDurationFormatSetup = require('moment-duration-format');
const refreshRateSeconds = 2;
momentDurationFormatSetup(moment);
@ -68,38 +70,21 @@ export default {
};
},
computed: {
relativeTimestamp() {
let relativeTimestamp;
if (this.configuration && this.configuration.timestamp) {
relativeTimestamp = moment(this.configuration.timestamp).toDate();
} else if (this.configuration && this.configuration.timestamp === undefined) {
relativeTimestamp = undefined;
}
return relativeTimestamp;
},
timeDelta() {
return this.lastTimestamp - this.relativeTimestamp;
if (this.configuration.pausedTime) {
return Date.parse(this.configuration.pausedTime) - this.startTimeMs;
} else {
return this.lastTimestamp - this.startTimeMs;
}
},
startTimeMs() {
return Date.parse(this.configuration.timestamp);
},
timeTextValue() {
if (isNaN(this.timeDelta)) {
return null;
}
const toWholeSeconds = Math.abs(Math.floor(this.timeDelta / 1000) * 1000);
return moment.duration(toWholeSeconds, 'ms').format(this.format, { trim: false });
},
pausedTime() {
let pausedTime;
if (this.configuration && this.configuration.pausedTime) {
pausedTime = moment(this.configuration.pausedTime).toDate();
} else if (this.configuration && this.configuration.pausedTime === undefined) {
pausedTime = undefined;
}
return pausedTime;
},
timerState() {
let timerState = 'started';
if (this.configuration && this.configuration.timerState) {
@ -179,13 +164,9 @@ export default {
}
},
mounted() {
this.unobserve = this.openmct.objects.observe(
this.domainObject,
'configuration',
(configuration) => {
this.configuration = configuration;
}
);
this.unobserve = this.openmct.objects.observe(this.domainObject, '*', (domainObject) => {
this.configuration = domainObject.configuration;
});
this.$nextTick(() => {
if (!this.configuration?.timerState) {
const timerAction = !this.relativeTimestamp ? 'stop' : 'start';
@ -193,6 +174,7 @@ export default {
}
this.handleTick = raf(this.handleTick);
this.refreshTimerObject = throttle(this.refreshTimerObject, refreshRateSeconds * 1000);
this.openmct.time.on('tick', this.handleTick);
this.viewActionsCollection = this.openmct.actions.getActionsCollection(
@ -210,15 +192,11 @@ export default {
},
methods: {
handleTick() {
const isTimerRunning = !['paused', 'stopped'].includes(this.timerState);
if (isTimerRunning) {
this.lastTimestamp = new Date(this.openmct.time.now());
}
if (this.timerState === 'paused' && !this.lastTimestamp) {
this.lastTimestamp = this.pausedTime;
}
this.lastTimestamp = new Date(this.openmct.time.now());
this.refreshTimerObject();
},
refreshTimerObject() {
this.openmct.objects.refresh(this.domainObject);
},
restartTimer() {
this.triggerAction('timer.restart');

34
src/utils/throttle.js Normal file
View File

@ -0,0 +1,34 @@
/**
* Creates a throttled function that only invokes the provided function at most once every
* specified number of milliseconds. Subsequent calls within the waiting period will be ignored.
* @param {Function} func The function to throttle.
* @param {number} wait The number of milliseconds to wait between successive calls to the function.
* @return {Function} Returns the new throttled function.
*/
export default function throttle(func, wait) {
let timeout;
let result;
let previous = 0;
return function (...args) {
const now = new Date().getTime();
const remaining = wait - (now - previous);
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func(...args);
} else if (!timeout) {
timeout = setTimeout(() => {
previous = new Date().getTime();
timeout = null;
result = func(...args);
}, remaining);
}
return result;
};
}