389 lines
8.2 KiB
JavaScript
389 lines
8.2 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 MAX_TIME = 999
|
|
+ (59 * MILLI_IN_SECOND)
|
|
+ (59 * MILLI_IN_MINUTE)
|
|
+ (MAX_HOURS * MILLI_IN_HOUR);
|
|
|
|
const getMaxHours = () => MAX_HOURS;
|
|
|
|
const isAlarmEnabled = () => isEnabled() && TIMER_CONFIG.alarm;
|
|
|
|
const isActive = () => {
|
|
const timer = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields: { active: 1 } },
|
|
);
|
|
|
|
if (timer) return timer.active;
|
|
return false;
|
|
};
|
|
|
|
const isEnabled = () => TIMER_CONFIG.enabled;
|
|
|
|
const getDefaultTime = () => TIMER_CONFIG.time * MILLI_IN_MINUTE;
|
|
|
|
const getInterval = () => TIMER_CONFIG.interval.clock;
|
|
|
|
const getPreset = () => {
|
|
const { preset } = TIMER_CONFIG;
|
|
|
|
return preset.map(minutes => minutes * MILLI_IN_MINUTE);
|
|
};
|
|
|
|
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 = () => makeCall('activateTimer');
|
|
|
|
const deactivateTimer = () => makeCall('deactivateTimer');
|
|
|
|
const fetchTimeOffset = () => {
|
|
const t0 = Date.now();
|
|
|
|
makeCall('getServerTime').then(result => {
|
|
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 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 getTimerStatus = () => {
|
|
const timerStatus = Timer.findOne(
|
|
{ meetingId: Auth.meetingID },
|
|
{ fields:
|
|
{
|
|
stopwatch: 1,
|
|
running: 1,
|
|
time: 1,
|
|
},
|
|
},
|
|
);
|
|
|
|
if (timerStatus) {
|
|
const {
|
|
stopwatch,
|
|
running,
|
|
time,
|
|
} = timerStatus;
|
|
|
|
return {
|
|
stopwatch,
|
|
running,
|
|
time,
|
|
}
|
|
}
|
|
|
|
return {
|
|
stopwatch: true,
|
|
running: false,
|
|
time: getDefaultTime(),
|
|
}
|
|
};
|
|
|
|
const getTimeAsString = (time, stopwatch) => {
|
|
let milliseconds = time;
|
|
|
|
let hours = Math.floor(milliseconds / MILLI_IN_HOUR);
|
|
const mHours = hours * MILLI_IN_HOUR;
|
|
|
|
let minutes = Math.floor((milliseconds - mHours) / MILLI_IN_MINUTE);
|
|
const mMinutes = minutes * MILLI_IN_MINUTE;
|
|
|
|
let seconds = Math.floor((milliseconds - mHours - mMinutes) / MILLI_IN_SECOND);
|
|
const mSeconds = seconds * MILLI_IN_SECOND;
|
|
|
|
milliseconds = milliseconds - mHours - mMinutes - mSeconds;
|
|
|
|
let timeAsString = '';
|
|
|
|
// Only add hour if it exists
|
|
if (hours > 0) {
|
|
if (hours < 10) {
|
|
timeAsString += `0${hours}:`;
|
|
} else {
|
|
timeAsString += `${hours}:`;
|
|
}
|
|
}
|
|
|
|
// Add minute if exists, has at least an hour
|
|
// or is not stopwatch
|
|
if (minutes > 0 || hours > 0 || !stopwatch) {
|
|
if (minutes < 10) {
|
|
timeAsString += `0${minutes}:`;
|
|
} else {
|
|
timeAsString += `${minutes}:`;
|
|
}
|
|
}
|
|
|
|
// Always add seconds
|
|
if (seconds < 10) {
|
|
timeAsString += `0${seconds}`;
|
|
} else {
|
|
timeAsString += `${seconds}`;
|
|
}
|
|
|
|
// Only add milliseconds if it's a stopwatch
|
|
if (stopwatch) {
|
|
if (milliseconds < 10) {
|
|
timeAsString += `:00${milliseconds}`;
|
|
} else if (milliseconds < 100) {
|
|
timeAsString += `:0${milliseconds}`;
|
|
} else {
|
|
timeAsString += `:${milliseconds}`;
|
|
}
|
|
}
|
|
|
|
return timeAsString;
|
|
};
|
|
|
|
const isPanelOpen = () => Session.get('openPanel') === 'timer';
|
|
|
|
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 = () => {
|
|
return Users.findOne(
|
|
{ userId: Auth.userID },
|
|
{ fields: { role: 1 } },
|
|
).role === ROLE_MODERATOR;
|
|
};
|
|
|
|
const setHours = (hours, time) => {
|
|
if (!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 (!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 (!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');
|
|
}
|
|
};
|
|
|
|
const subtractTime = (preset, time) => {
|
|
if (!isNaN(preset)) {
|
|
const min = 0;
|
|
setTimer(Math.max(time - preset, min));
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
const setTime = (preset) => {
|
|
if (!isNaN(preset)) {
|
|
setTimer(preset);
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
const addTime = (preset, time) => {
|
|
if (!isNaN(preset)) {
|
|
const max = MAX_TIME;
|
|
setTimer(Math.min(time + preset, max));
|
|
} else {
|
|
Logger.warn('Invalid time');
|
|
}
|
|
};
|
|
|
|
const buildPresetLabel = (preset) => {
|
|
const minutes = preset / MILLI_IN_MINUTE;
|
|
|
|
if (minutes < 10) {
|
|
return `0${minutes}"00'`;
|
|
}
|
|
|
|
return `${minutes}"00'`;
|
|
};
|
|
|
|
export default {
|
|
OFFSET_INTERVAL,
|
|
isActive,
|
|
isEnabled,
|
|
isRunning,
|
|
isStopwatch,
|
|
isAlarmEnabled,
|
|
startTimer,
|
|
stopTimer,
|
|
switchTimer,
|
|
setHours,
|
|
setMinutes,
|
|
setSeconds,
|
|
setTime,
|
|
subtractTime,
|
|
addTime,
|
|
resetTimer,
|
|
activateTimer,
|
|
deactivateTimer,
|
|
fetchTimeOffset,
|
|
getTimeOffset,
|
|
getElapsedTime,
|
|
getInterval,
|
|
getPreset,
|
|
getMaxHours,
|
|
getTimer,
|
|
getTimerStatus,
|
|
getTimeAsString,
|
|
closePanel,
|
|
togglePanel,
|
|
isModerator,
|
|
buildPresetLabel,
|
|
};
|