2019-05-21 00:43:31 +08:00
|
|
|
import _ from 'lodash';
|
2019-05-17 04:11:10 +08:00
|
|
|
import Captions from '/imports/api/captions';
|
2019-05-22 03:21:46 +08:00
|
|
|
import Users from '/imports/api/users';
|
2019-05-17 04:11:10 +08:00
|
|
|
import Auth from '/imports/ui/services/auth';
|
|
|
|
import { makeCall } from '/imports/ui/services/api';
|
|
|
|
import { Meteor } from 'meteor/meteor';
|
|
|
|
import { Session } from 'meteor/session';
|
|
|
|
|
|
|
|
const CAPTIONS_CONFIG = Meteor.settings.public.captions;
|
|
|
|
const CAPTIONS = '_captions_';
|
2019-05-21 01:39:04 +08:00
|
|
|
const LINE_BREAK = '\n';
|
2019-08-22 20:05:06 +08:00
|
|
|
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2019-05-23 22:51:01 +08:00
|
|
|
const getActiveCaptions = () => {
|
|
|
|
const activeCaptions = Session.get('activeCaptions');
|
|
|
|
if (!activeCaptions) return '';
|
|
|
|
return activeCaptions;
|
|
|
|
};
|
|
|
|
|
2019-08-22 20:05:06 +08:00
|
|
|
const getCaptions = locale => Captions.findOne({
|
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
padId: { $regex: `${CAPTIONS}${locale}$` },
|
|
|
|
});
|
2019-05-23 22:51:01 +08:00
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
const getCaptionsData = () => {
|
|
|
|
const activeCaptions = getActiveCaptions();
|
2019-05-29 22:31:27 +08:00
|
|
|
let padId = '';
|
2019-05-21 00:43:31 +08:00
|
|
|
let revs = 0;
|
2019-05-29 22:31:27 +08:00
|
|
|
let data = '';
|
2019-05-17 04:11:10 +08:00
|
|
|
if (activeCaptions) {
|
2019-05-21 00:43:31 +08:00
|
|
|
const captions = getCaptions(activeCaptions);
|
|
|
|
if (!_.isEmpty(captions)) {
|
2019-05-29 22:31:27 +08:00
|
|
|
padId = captions.padId; // eslint-disable-line prefer-destructuring
|
|
|
|
revs = captions.revs; // eslint-disable-line prefer-destructuring
|
|
|
|
data = captions.data; // eslint-disable-line prefer-destructuring
|
2019-05-21 00:43:31 +08:00
|
|
|
}
|
2019-05-17 04:11:10 +08:00
|
|
|
}
|
|
|
|
|
2019-05-21 00:43:31 +08:00
|
|
|
return { padId, revs, data };
|
2019-05-17 04:11:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const getAvailableLocales = () => {
|
|
|
|
const { meetingID } = Auth;
|
2019-05-29 22:31:27 +08:00
|
|
|
const locales = [];
|
2019-08-22 20:05:06 +08:00
|
|
|
Captions.find({ meetingId: meetingID },
|
|
|
|
{ fields: { ownerId: 1, locale: 1 } })
|
|
|
|
.forEach((caption) => {
|
|
|
|
if (caption.ownerId === '') {
|
|
|
|
locales.push(caption.locale);
|
|
|
|
}
|
|
|
|
});
|
2019-05-17 04:11:10 +08:00
|
|
|
return locales;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getOwnedLocales = () => {
|
|
|
|
const { meetingID } = Auth;
|
2019-05-29 22:31:27 +08:00
|
|
|
const locales = [];
|
2019-08-22 20:05:06 +08:00
|
|
|
Captions.find({ meetingId: meetingID }, { fields: { ownerId: 1, locale: 1 } })
|
|
|
|
.forEach((caption) => {
|
|
|
|
if (caption.ownerId !== '') {
|
|
|
|
locales.push(caption.locale);
|
|
|
|
}
|
|
|
|
});
|
2019-05-17 04:11:10 +08:00
|
|
|
return locales;
|
|
|
|
};
|
|
|
|
|
2019-05-29 22:31:27 +08:00
|
|
|
const takeOwnership = (locale) => {
|
2019-05-17 04:11:10 +08:00
|
|
|
makeCall('takeOwnership', locale);
|
|
|
|
};
|
|
|
|
|
2019-06-22 04:52:54 +08:00
|
|
|
const formatEntry = (entry) => {
|
|
|
|
const letterIndex = entry.charAt(0) === ' ' ? 1 : 0;
|
|
|
|
const formattedEntry = `${entry.charAt(letterIndex).toUpperCase() + entry.slice(letterIndex + 1)}.\n\n`;
|
|
|
|
return formattedEntry;
|
|
|
|
};
|
|
|
|
|
|
|
|
const appendText = (text, locale) => {
|
|
|
|
makeCall('appendText', formatEntry(text), locale);
|
|
|
|
};
|
|
|
|
|
2019-05-29 22:31:27 +08:00
|
|
|
const canIOwnThisPad = (ownerId) => {
|
2019-05-17 04:11:10 +08:00
|
|
|
const { userID } = Auth;
|
|
|
|
if (!CAPTIONS_CONFIG.takeOwnership) return false;
|
2019-05-29 22:31:27 +08:00
|
|
|
if (ownerId === '') return false;
|
2019-05-17 04:11:10 +08:00
|
|
|
return ownerId !== userID;
|
|
|
|
};
|
|
|
|
|
2019-06-22 04:52:54 +08:00
|
|
|
const canIDictateThisPad = (ownerId) => {
|
|
|
|
const { userID } = Auth;
|
|
|
|
if (!CAPTIONS_CONFIG.enableDictation) return false;
|
|
|
|
if (ownerId === '') return false;
|
|
|
|
const SpeechRecognitionAPI = getSpeechRecognitionAPI();
|
|
|
|
if (!SpeechRecognitionAPI) return false;
|
|
|
|
return ownerId === userID;
|
|
|
|
};
|
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
const setActiveCaptions = (locale) => {
|
|
|
|
Session.set('activeCaptions', locale);
|
|
|
|
};
|
|
|
|
|
|
|
|
const setCaptionsSettings = (settings) => {
|
|
|
|
Session.set('captionsSettings', settings);
|
|
|
|
};
|
|
|
|
|
|
|
|
const getCaptionsSettings = () => {
|
|
|
|
const settings = Session.get('captionsSettings');
|
|
|
|
if (!settings) {
|
2019-05-29 22:31:27 +08:00
|
|
|
const {
|
|
|
|
backgroundColor, fontColor, fontFamily, fontSize,
|
|
|
|
} = CAPTIONS_CONFIG;
|
|
|
|
return {
|
|
|
|
backgroundColor, fontColor, fontFamily, fontSize,
|
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
}
|
|
|
|
return settings;
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2019-05-29 22:31:27 +08:00
|
|
|
const isCaptionsEnabled = () => CAPTIONS_CONFIG.enabled;
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const isCaptionsAvailable = () => {
|
|
|
|
if (isCaptionsEnabled) {
|
|
|
|
const ownedLocales = getOwnedLocales();
|
|
|
|
return (ownedLocales.length > 0);
|
|
|
|
}
|
|
|
|
return false;
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const isCaptionsActive = () => {
|
|
|
|
const enabled = isCaptionsEnabled();
|
2019-05-18 04:02:28 +08:00
|
|
|
const activated = getActiveCaptions() !== '';
|
2019-05-17 04:11:10 +08:00
|
|
|
return (enabled && activated);
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const deactivateCaptions = () => {
|
|
|
|
setActiveCaptions('');
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const activateCaptions = (locale, settings) => {
|
|
|
|
setCaptionsSettings(settings);
|
|
|
|
setActiveCaptions(locale);
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
|
|
|
|
2019-05-29 22:31:27 +08:00
|
|
|
const formatCaptionsText = (text) => {
|
2019-05-21 01:39:04 +08:00
|
|
|
const splitText = text.split(LINE_BREAK);
|
|
|
|
const filteredText = splitText.filter((line, index) => {
|
2019-05-23 22:51:01 +08:00
|
|
|
const lastLine = index === (splitText.length - 1);
|
|
|
|
const emptyLine = line.length === 0;
|
2019-05-21 01:39:04 +08:00
|
|
|
return (!emptyLine || lastLine);
|
|
|
|
});
|
|
|
|
while (filteredText.length > CAPTIONS_CONFIG.lines) filteredText.shift();
|
|
|
|
return filteredText.join(LINE_BREAK);
|
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2019-08-22 20:05:06 +08:00
|
|
|
const amIModerator = () => Users.findOne({ userId: Auth.userID },
|
|
|
|
{ fields: { role: 1 } }).role === ROLE_MODERATOR;
|
2019-05-22 03:21:46 +08:00
|
|
|
|
2019-07-26 07:29:52 +08:00
|
|
|
const getSpeechRecognitionAPI = () => window.SpeechRecognition || window.webkitSpeechRecognition;
|
2019-06-22 04:52:54 +08:00
|
|
|
|
|
|
|
const initSpeechRecognition = (locale) => {
|
|
|
|
const SpeechRecognitionAPI = getSpeechRecognitionAPI();
|
|
|
|
let recognition = null;
|
|
|
|
if (SpeechRecognitionAPI) {
|
|
|
|
recognition = new SpeechRecognitionAPI();
|
|
|
|
recognition.continuous = true;
|
|
|
|
recognition.interimResults = true;
|
|
|
|
recognition.lang = locale;
|
|
|
|
}
|
|
|
|
|
|
|
|
return recognition;
|
|
|
|
};
|
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
export default {
|
|
|
|
getCaptionsData,
|
|
|
|
getAvailableLocales,
|
|
|
|
getOwnedLocales,
|
|
|
|
takeOwnership,
|
2019-06-22 04:52:54 +08:00
|
|
|
appendText,
|
2019-05-17 04:11:10 +08:00
|
|
|
getCaptions,
|
|
|
|
canIOwnThisPad,
|
2019-06-22 04:52:54 +08:00
|
|
|
canIDictateThisPad,
|
2019-05-17 04:11:10 +08:00
|
|
|
getCaptionsSettings,
|
|
|
|
isCaptionsEnabled,
|
|
|
|
isCaptionsAvailable,
|
|
|
|
isCaptionsActive,
|
|
|
|
deactivateCaptions,
|
|
|
|
activateCaptions,
|
2019-05-21 01:39:04 +08:00
|
|
|
formatCaptionsText,
|
2019-05-22 03:21:46 +08:00
|
|
|
amIModerator,
|
2019-06-22 04:52:54 +08:00
|
|
|
initSpeechRecognition,
|
2019-05-17 04:11:10 +08:00
|
|
|
};
|