104550d46f
Changes the behavior of activating the timer. The behavior set by this commit is: when the timer is activated, only the moderator who triggered it will see the sidebar content switch to the timer. This change required hanging an observer to catch the timer activation and dispatch the sidebar content change since timer messages are passing through akka.
349 lines
7.7 KiB
JavaScript
349 lines
7.7 KiB
JavaScript
import { Meteor } from 'meteor/meteor';
|
|
import Timer from '/imports/api/timer';
|
|
import Auth from '/imports/ui/services/auth';
|
|
import { makeCall } from '/imports/ui/services/api';
|
|
import { Session } from 'meteor/session';
|
|
import Users from '/imports/api/users';
|
|
import Logger from '/imports/startup/client/logger';
|
|
import { ACTIONS, PANELS } from '../layout/enums';
|
|
|
|
const TIMER_CONFIG = Meteor.settings.public.timer;
|
|
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
|
const OFFSET_INTERVAL = TIMER_CONFIG.interval.offset;
|
|
|
|
const MILLI_IN_HOUR = 3600000;
|
|
const MILLI_IN_MINUTE = 60000;
|
|
const MILLI_IN_SECOND = 1000;
|
|
|
|
const MAX_HOURS = 23;
|
|
|
|
const TRACKS = [
|
|
'noTrack',
|
|
'track1',
|
|
'track2',
|
|
'track3',
|
|
];
|
|
|
|
const isMusicEnabled = () => TIMER_CONFIG.music.enabled;
|
|
|
|
const getCurrentTrack = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { track: 1 } },
|
|
);
|
|
|
|
if (timer) return isMusicEnabled() && timer.track;
|
|
|
|
return false;
|
|
};
|
|
|
|
const isEnabled = () => TIMER_CONFIG.enabled;
|
|
|
|
const getMaxHours = () => MAX_HOURS;
|
|
|
|
const isAlarmEnabled = () => isEnabled() && TIMER_CONFIG.alarm;
|
|
|
|
const isMusicActive = () => getCurrentTrack() !== TRACKS[0];
|
|
|
|
const getMusicVolume = () => TIMER_CONFIG.music.volume;
|
|
|
|
const getMusicTrack = () => TIMER_CONFIG.music.track;
|
|
|
|
const isActive = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { active: 1 } },
|
|
);
|
|
|
|
if (timer) return timer.active;
|
|
return false;
|
|
};
|
|
|
|
const getDefaultTime = () => TIMER_CONFIG.time * MILLI_IN_MINUTE;
|
|
|
|
const getInterval = () => TIMER_CONFIG.interval.clock;
|
|
|
|
const isRunning = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { running: 1 } },
|
|
);
|
|
|
|
if (timer) return timer.running;
|
|
return false;
|
|
};
|
|
|
|
const isStopwatch = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { stopwatch: 1 } },
|
|
);
|
|
|
|
if (timer) return timer.stopwatch;
|
|
return false;
|
|
};
|
|
|
|
const startTimer = () => makeCall('startTimer');
|
|
|
|
const stopTimer = () => makeCall('stopTimer');
|
|
|
|
const switchTimer = (stopwatch) => makeCall('switchTimer', stopwatch);
|
|
|
|
const setTimer = (time) => makeCall('setTimer', time);
|
|
|
|
const resetTimer = () => makeCall('resetTimer');
|
|
|
|
const activateTimer = (layoutContextDispatch) => {
|
|
makeCall('activateTimer');
|
|
//Set an observer to switch to timer tab as soon as the timer is activated
|
|
const handle =Timer.find({ meetingId: Auth.meetingID }).observeChanges({
|
|
changed(id, timer) {
|
|
if (timer.active === true) {
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN,
|
|
value: true,
|
|
});
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL,
|
|
value: PANELS.TIMER,
|
|
});
|
|
}
|
|
handle.stop();
|
|
}
|
|
});
|
|
};
|
|
|
|
const deactivateTimer = () => makeCall('deactivateTimer');
|
|
|
|
const timerEnded = () => makeCall('timerEnded');
|
|
|
|
const setTrack = (track) => {
|
|
makeCall('setTrack', track);
|
|
};
|
|
|
|
const fetchTimeOffset = () => {
|
|
const t0 = Date.now();
|
|
|
|
makeCall('getServerTime').then((result) => {
|
|
if (result === 0) return;
|
|
const t3 = Date.now();
|
|
|
|
const ts = result;
|
|
const rtt = t3 - t0;
|
|
const timeOffset = Math.round(ts - rtt / 2 - t0);
|
|
|
|
Session.set('timeOffset', timeOffset);
|
|
});
|
|
};
|
|
|
|
const getTimeOffset = () => {
|
|
const timeOffset = Session.get('timeOffset');
|
|
|
|
if (timeOffset) return timeOffset;
|
|
|
|
return 0;
|
|
};
|
|
|
|
const getElapsedTime = (running, timestamp, timeOffset, accumulated) => {
|
|
if (!running) return accumulated;
|
|
|
|
const now = Date.now();
|
|
|
|
return accumulated + Math.abs(now - timestamp + timeOffset);
|
|
};
|
|
|
|
const getStopwatch = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { stopwatch: 1 } },
|
|
);
|
|
|
|
if (timer) return timer.stopwatch;
|
|
|
|
return true;
|
|
};
|
|
|
|
const getTimer = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{
|
|
fields:
|
|
{
|
|
stopwatch: 1,
|
|
running: 1,
|
|
time: 1,
|
|
accumulated: 1,
|
|
timestamp: 1,
|
|
},
|
|
},
|
|
);
|
|
|
|
if (timer) {
|
|
const {
|
|
stopwatch,
|
|
running,
|
|
time,
|
|
accumulated,
|
|
timestamp,
|
|
} = timer;
|
|
|
|
return {
|
|
stopwatch,
|
|
running,
|
|
time,
|
|
accumulated,
|
|
timestamp,
|
|
};
|
|
}
|
|
|
|
return {
|
|
stopwatch: true,
|
|
running: false,
|
|
time: getDefaultTime(),
|
|
accumulated: 0,
|
|
timestamp: 0,
|
|
};
|
|
};
|
|
|
|
const getTimeAsString = (time) => {
|
|
const milliseconds = time;
|
|
|
|
const hours = Math.floor(milliseconds / MILLI_IN_HOUR);
|
|
const mHours = hours * MILLI_IN_HOUR;
|
|
|
|
const minutes = Math.floor((milliseconds - mHours) / MILLI_IN_MINUTE);
|
|
const mMinutes = minutes * MILLI_IN_MINUTE;
|
|
|
|
const seconds = Math.floor((milliseconds - mHours - mMinutes) / MILLI_IN_SECOND);
|
|
|
|
let timeAsString = '';
|
|
|
|
if (hours < 10) {
|
|
timeAsString += `0${hours}:`;
|
|
} else {
|
|
timeAsString += `${hours}:`;
|
|
}
|
|
|
|
if (minutes < 10) {
|
|
timeAsString += `0${minutes}:`;
|
|
} else {
|
|
timeAsString += `${minutes}:`;
|
|
}
|
|
|
|
if (seconds < 10) {
|
|
timeAsString += `0${seconds}`;
|
|
} else {
|
|
timeAsString += `${seconds}`;
|
|
}
|
|
|
|
return timeAsString;
|
|
};
|
|
|
|
const closePanel = (layoutContextDispatch) => {
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN,
|
|
value: false,
|
|
});
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL,
|
|
value: PANELS.NONE,
|
|
});
|
|
};
|
|
|
|
const togglePanel = (sidebarContentPanel, layoutContextDispatch) => {
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_IS_OPEN,
|
|
value: sidebarContentPanel !== PANELS.TIMER,
|
|
});
|
|
layoutContextDispatch({
|
|
type: ACTIONS.SET_SIDEBAR_CONTENT_PANEL,
|
|
value: sidebarContentPanel === PANELS.TIMER
|
|
? PANELS.NONE
|
|
: PANELS.TIMER,
|
|
});
|
|
};
|
|
|
|
const isModerator = () => Users.findOne(
|
|
{ userId: Auth.userID },
|
|
{ fields: { role: 1 } },
|
|
).role === ROLE_MODERATOR;
|
|
|
|
const setHours = (hours, time) => {
|
|
if (!Number.isNaN(hours) && hours >= 0 && hours <= MAX_HOURS) {
|
|
const currentHours = Math.floor(time / MILLI_IN_HOUR);
|
|
|
|
const diff = (hours - currentHours) * MILLI_IN_HOUR;
|
|
setTimer(time + diff);
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
const setMinutes = (minutes, time) => {
|
|
if (!Number.isNaN(minutes) && minutes >= 0 && minutes <= 59) {
|
|
const currentHours = Math.floor(time / MILLI_IN_HOUR);
|
|
const mHours = currentHours * MILLI_IN_HOUR;
|
|
|
|
const currentMinutes = Math.floor((time - mHours) / MILLI_IN_MINUTE);
|
|
|
|
const diff = (minutes - currentMinutes) * MILLI_IN_MINUTE;
|
|
setTimer(time + diff);
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
const setSeconds = (seconds, time) => {
|
|
if (!Number.isNaN(seconds) && seconds >= 0 && seconds <= 59) {
|
|
const currentHours = Math.floor(time / MILLI_IN_HOUR);
|
|
const mHours = currentHours * MILLI_IN_HOUR;
|
|
|
|
const currentMinutes = Math.floor((time - mHours) / MILLI_IN_MINUTE);
|
|
const mMinutes = currentMinutes * MILLI_IN_MINUTE;
|
|
|
|
const currentSeconds = Math.floor((time - mHours - mMinutes) / MILLI_IN_SECOND);
|
|
|
|
const diff = (seconds - currentSeconds) * MILLI_IN_SECOND;
|
|
setTimer(time + diff);
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
export default {
|
|
OFFSET_INTERVAL,
|
|
TRACKS,
|
|
isActive,
|
|
isEnabled,
|
|
isMusicEnabled,
|
|
isMusicActive,
|
|
getCurrentTrack,
|
|
getMusicVolume,
|
|
getMusicTrack,
|
|
isRunning,
|
|
isStopwatch,
|
|
isAlarmEnabled,
|
|
startTimer,
|
|
stopTimer,
|
|
switchTimer,
|
|
setHours,
|
|
setMinutes,
|
|
setSeconds,
|
|
resetTimer,
|
|
activateTimer,
|
|
deactivateTimer,
|
|
fetchTimeOffset,
|
|
setTrack,
|
|
getTimeOffset,
|
|
getElapsedTime,
|
|
getInterval,
|
|
getMaxHours,
|
|
getStopwatch,
|
|
getTimer,
|
|
getTimeAsString,
|
|
closePanel,
|
|
togglePanel,
|
|
isModerator,
|
|
timerEnded,
|
|
};
|