Skip to content

Commit

Permalink
Synchronize timers between multiple users (#6885)
Browse files Browse the repository at this point in the history
* 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: Jamie V <jamie.j.vigliotta@nasa.gov>
Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com>
  • Loading branch information
4 people committed Aug 2, 2023
1 parent c630569 commit 676bb81
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 40 deletions.
58 changes: 18 additions & 40 deletions src/plugins/timer/components/Timer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
timeDelta() {
if (this.configuration.pausedTime) {
return Date.parse(this.configuration.pausedTime) - this.startTimeMs;
} else {
return this.lastTimestamp - this.startTimeMs;
}
return relativeTimestamp;
},
timeDelta() {
return this.lastTimestamp - this.relativeTimestamp;
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) {
Expand Down Expand Up @@ -179,20 +164,17 @@ 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';
this.triggerAction(`timer.${timerAction}`);
}
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(
Expand All @@ -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');
Expand Down
34 changes: 34 additions & 0 deletions src/utils/throttle.js
Original file line number Diff line number Diff line change
@@ -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;
};
}

0 comments on commit 676bb81

Please sign in to comment.