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';
|
2021-10-16 03:07:13 +08:00
|
|
|
import PadsService from '/imports/ui/components/pads/service';
|
|
|
|
import SpeechService from '/imports/ui/components/captions/speech/service';
|
2019-05-17 04:11:10 +08:00
|
|
|
import { makeCall } from '/imports/ui/services/api';
|
|
|
|
import { Meteor } from 'meteor/meteor';
|
|
|
|
import { Session } from 'meteor/session';
|
2022-03-11 02:02:20 +08:00
|
|
|
import { isCaptionsEnabled } from '/imports/ui/services/features';
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const CAPTIONS_CONFIG = Meteor.settings.public.captions;
|
2019-08-22 20:05:06 +08:00
|
|
|
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
2021-10-16 03:07:13 +08:00
|
|
|
const LINE_BREAK = '\n';
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const getAvailableLocales = () => {
|
2021-10-16 03:07:13 +08:00
|
|
|
const availableLocales = Captions.find(
|
|
|
|
{ meetingId: Auth.meetingID, ownerId: '' },
|
2021-03-12 02:33:48 +08:00
|
|
|
{ sort: { locale: 1 } },
|
2021-10-16 03:07:13 +08:00
|
|
|
{ fields: { ownerId: 1, locale: 1, name: 1 } },
|
|
|
|
).fetch();
|
|
|
|
|
|
|
|
return availableLocales;
|
2019-05-17 04:11:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const getOwnedLocales = () => {
|
2021-10-16 03:07:13 +08:00
|
|
|
const ownedLocales = Captions.find(
|
|
|
|
{ meetingId: Auth.meetingID, ownerId: { $not: '' } },
|
|
|
|
{ fields: { ownerId: 1, locale: 1, name: 1 } },
|
|
|
|
).fetch();
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
return ownedLocales;
|
2019-05-17 04:11:10 +08:00
|
|
|
};
|
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const updateCaptionsOwner = (locale, name) => makeCall('updateCaptionsOwner', locale, name);
|
2021-05-16 21:06:16 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const startDictation = (locale) => makeCall('startDictation', locale);
|
2019-06-22 04:52:54 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const stopDictation = (locale) => makeCall('stopDictation', locale);
|
|
|
|
|
|
|
|
const getCaptionsSettings = () => {
|
|
|
|
const settings = Session.get('captionsSettings');
|
|
|
|
if (settings) return settings;
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const {
|
|
|
|
background,
|
|
|
|
font,
|
|
|
|
} = CAPTIONS_CONFIG;
|
2020-04-30 21:46:30 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
return {
|
|
|
|
backgroundColor: background,
|
|
|
|
fontColor: font.color,
|
|
|
|
fontFamily: font.family,
|
|
|
|
fontSize: font.size,
|
|
|
|
};
|
2019-06-22 04:52:54 +08:00
|
|
|
};
|
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const setCaptionsSettings = (settings) => Session.set('captionsSettings', settings);
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const getCaptionsLocale = () => Session.get('captionsLocale') || '';
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const getCaptions = () => {
|
|
|
|
const locale = getCaptionsLocale();
|
|
|
|
if (locale) {
|
2019-05-29 22:31:27 +08:00
|
|
|
const {
|
2021-10-16 03:07:13 +08:00
|
|
|
name,
|
|
|
|
ownerId,
|
|
|
|
dictating,
|
|
|
|
} = Captions.findOne({
|
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
locale,
|
|
|
|
});
|
|
|
|
|
2019-05-29 22:31:27 +08:00
|
|
|
return {
|
2021-10-16 03:07:13 +08:00
|
|
|
locale,
|
|
|
|
name,
|
|
|
|
ownerId,
|
|
|
|
dictating,
|
2019-05-29 22:31:27 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
}
|
2021-10-16 03:07:13 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
locale,
|
|
|
|
name: '',
|
|
|
|
ownerId: '',
|
|
|
|
dictating: false,
|
|
|
|
};
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const setCaptionsLocale = (locale) => Session.set('captionsLocale', locale);
|
|
|
|
|
|
|
|
const getCaptionsActive = () => Session.get('captionsActive') || '';
|
|
|
|
|
|
|
|
const formatCaptionsText = (text) => {
|
|
|
|
const splitText = text.split(LINE_BREAK);
|
|
|
|
const filteredText = splitText.filter((line, index) => {
|
|
|
|
const lastLine = index === (splitText.length - 1);
|
|
|
|
const emptyLine = line.length === 0;
|
|
|
|
|
|
|
|
return (!emptyLine || lastLine);
|
|
|
|
});
|
|
|
|
|
|
|
|
while (filteredText.length > CAPTIONS_CONFIG.lines) filteredText.shift();
|
|
|
|
|
|
|
|
return filteredText.join(LINE_BREAK);
|
2021-03-30 05:35:33 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const getCaptionsData = () => {
|
|
|
|
const locale = getCaptionsActive();
|
|
|
|
if (locale) {
|
|
|
|
const captions = Captions.findOne({
|
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
locale,
|
|
|
|
dictating: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
let data = '';
|
|
|
|
if (captions) {
|
|
|
|
data = captions.transcript;
|
|
|
|
} else {
|
|
|
|
data = PadsService.getPadTail(locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
return formatCaptionsText(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
};
|
|
|
|
|
|
|
|
const setCaptionsActive = (locale) => Session.set('captionsActive', locale);
|
|
|
|
|
|
|
|
const amICaptionsOwner = (ownerId) => ownerId === Auth.userID;
|
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
const isCaptionsAvailable = () => {
|
2023-11-30 23:10:36 +08:00
|
|
|
if (!CAPTIONS_CONFIG.showButton) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
if (isCaptionsEnabled()) {
|
2019-05-17 04:11:10 +08:00
|
|
|
const ownedLocales = getOwnedLocales();
|
2021-10-16 03:07:13 +08:00
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
return (ownedLocales.length > 0);
|
|
|
|
}
|
2021-10-16 03:07:13 +08:00
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
return false;
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const isCaptionsActive = () => {
|
|
|
|
const enabled = isCaptionsEnabled();
|
2021-10-16 03:07:13 +08:00
|
|
|
const activated = getCaptionsActive() !== '';
|
|
|
|
|
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
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const deactivateCaptions = () => setCaptionsActive('');
|
2019-05-17 04:11:10 +08:00
|
|
|
|
|
|
|
const activateCaptions = (locale, settings) => {
|
|
|
|
setCaptionsSettings(settings);
|
2021-10-16 03:07:13 +08:00
|
|
|
setCaptionsActive(locale);
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const amIModerator = () => {
|
|
|
|
const user = Users.findOne(
|
|
|
|
{ userId: Auth.userID },
|
|
|
|
{ fields: { role: 1 } },
|
|
|
|
);
|
|
|
|
|
|
|
|
return user && user.role === ROLE_MODERATOR;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getName = (locale) => {
|
|
|
|
const captions = Captions.findOne({
|
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
locale,
|
2019-05-21 01:39:04 +08:00
|
|
|
});
|
2021-10-16 03:07:13 +08:00
|
|
|
|
2023-11-30 23:10:36 +08:00
|
|
|
return captions?.name;
|
2021-10-16 03:07:13 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const createCaptions = (locale) => {
|
|
|
|
const name = getName(locale);
|
|
|
|
PadsService.createGroup(locale, CAPTIONS_CONFIG.id, name);
|
|
|
|
updateCaptionsOwner(locale, name);
|
|
|
|
setCaptionsLocale(locale);
|
|
|
|
};
|
|
|
|
|
|
|
|
const hasPermission = () => {
|
|
|
|
if (amIModerator()) {
|
|
|
|
const { ownerId } = getCaptions();
|
|
|
|
|
|
|
|
return Auth.userID === ownerId;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2019-05-21 01:39:04 +08:00
|
|
|
};
|
2019-05-17 04:11:10 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
const getDictationStatus = () => {
|
|
|
|
if (!CAPTIONS_CONFIG.dictation || !amIModerator()) {
|
|
|
|
return {
|
|
|
|
locale: '',
|
|
|
|
dictating: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const captions = Captions.findOne({
|
|
|
|
meetingId: Auth.meetingID,
|
|
|
|
ownerId: Auth.userID,
|
|
|
|
}, {
|
|
|
|
fields: {
|
|
|
|
locale: 1,
|
|
|
|
dictating: 1,
|
|
|
|
},
|
|
|
|
});
|
2019-05-22 03:21:46 +08:00
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
if (captions) {
|
|
|
|
return {
|
|
|
|
locale: captions.locale,
|
|
|
|
dictating: captions.dictating,
|
|
|
|
};
|
2019-06-22 04:52:54 +08:00
|
|
|
}
|
|
|
|
|
2021-10-16 03:07:13 +08:00
|
|
|
return {
|
|
|
|
locale: '',
|
|
|
|
dictating: false,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const canIDictateThisPad = (ownerId) => {
|
|
|
|
if (!CAPTIONS_CONFIG.dictation) return false;
|
|
|
|
|
|
|
|
if (ownerId !== Auth.userID) return false;
|
|
|
|
|
|
|
|
if (!SpeechService.hasSpeechRecognitionSupport()) return false;
|
|
|
|
|
|
|
|
return true;
|
2019-06-22 04:52:54 +08:00
|
|
|
};
|
|
|
|
|
2019-05-17 04:11:10 +08:00
|
|
|
export default {
|
2021-10-16 03:07:13 +08:00
|
|
|
ID: CAPTIONS_CONFIG.id,
|
2019-05-17 04:11:10 +08:00
|
|
|
getAvailableLocales,
|
|
|
|
getOwnedLocales,
|
2021-10-16 03:07:13 +08:00
|
|
|
updateCaptionsOwner,
|
|
|
|
startDictation,
|
|
|
|
stopDictation,
|
2019-05-17 04:11:10 +08:00
|
|
|
getCaptionsSettings,
|
2021-10-16 03:07:13 +08:00
|
|
|
getCaptionsData,
|
|
|
|
getCaptions,
|
|
|
|
hasPermission,
|
|
|
|
amICaptionsOwner,
|
2019-05-17 04:11:10 +08:00
|
|
|
isCaptionsEnabled,
|
|
|
|
isCaptionsAvailable,
|
|
|
|
isCaptionsActive,
|
|
|
|
deactivateCaptions,
|
|
|
|
activateCaptions,
|
2019-05-21 01:39:04 +08:00
|
|
|
formatCaptionsText,
|
2019-05-22 03:21:46 +08:00
|
|
|
amIModerator,
|
2021-10-16 03:07:13 +08:00
|
|
|
createCaptions,
|
|
|
|
getCaptionsLocale,
|
|
|
|
setCaptionsLocale,
|
|
|
|
getDictationStatus,
|
|
|
|
canIDictateThisPad,
|
2019-05-17 04:11:10 +08:00
|
|
|
};
|