@sendbird/uikit-react
Version:
Sendbird UIKit for React: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.
135 lines (132 loc) • 7.27 kB
JavaScript
import React__default, { createContext, useState, useEffect, useCallback, useContext } from 'react';
import { u as useLocalization } from '../chunks/bundle-Del33VzI.js';
import { M as Modal } from '../chunks/bundle-CtQtfJlT.js';
import { B as BROWSER_SUPPORT_MIME_TYPE_LIST, V as VOICE_RECORDER_AUDIO_BIT_RATE, a as VOICE_MESSAGE_FILE_NAME, b as VOICE_MESSAGE_MIME_TYPE } from '../chunks/bundle-CqLLOVG5.js';
import { n as noop } from '../chunks/bundle-MlG9piGf.js';
import { u as useSendbird } from '../chunks/bundle-i_3w58Zd.js';
import '../chunks/bundle-yl5d1NoZ.js';
import '../chunks/bundle-C1dqPUnT.js';
import '../chunks/bundle-BZGITC2g.js';
import 'react-dom';
import '../chunks/bundle-DBhJIxHw.js';
import '../ui/IconButton.js';
import '../ui/Button.js';
import '../chunks/bundle-viBng0Kh.js';
import '../ui/Icon.js';
import '../chunks/bundle-DGh2T5IL.js';
import '../chunks/bundle-BUYU9H94.js';
import '@sendbird/chat';
import '@sendbird/chat/groupChannel';
import '@sendbird/chat/openChannel';
var Context = createContext({
start: noop,
stop: noop,
isRecordable: false,
});
var VoiceRecorderProvider = function (props) {
var _a;
var children = props.children;
var state = useSendbird().state;
var config = state.config;
var logger = config.logger, groupChannel = config.groupChannel;
var _b = useState(null), mediaRecorder = _b[0], setMediaRecorder = _b[1];
var _c = useState(false), isRecordable = _c[0], setIsRecordable = _c[1];
var _d = useState(false), permissionWarning = _d[0], setPermissionWarning = _d[1];
var stringSet = useLocalization().stringSet;
var isVoiceMessageEnabled = groupChannel.enableVoiceMessage;
var _e = useState(null), webAudioUtils = _e[0], setWebAudioUtils = _e[1];
var browserSupportMimeType = (_a = BROWSER_SUPPORT_MIME_TYPE_LIST.find(function (mimeType) { return MediaRecorder.isTypeSupported(mimeType); })) !== null && _a !== void 0 ? _a : '';
if (isVoiceMessageEnabled && !browserSupportMimeType) {
logger.error('VoiceRecorder: Browser does not support mimeType', { mimmeTypes: BROWSER_SUPPORT_MIME_TYPE_LIST });
}
useEffect(function () {
if (isVoiceMessageEnabled && !webAudioUtils) {
import('../chunks/bundle-BMfuf1lc.js').then(function (module) { return setWebAudioUtils(module); });
}
}, [isVoiceMessageEnabled, webAudioUtils]);
var start = useCallback(function (eventHandler) {
var _a, _b;
if (isVoiceMessageEnabled && !webAudioUtils) {
logger.error('VoiceRecorder: Recording audio processor is being loaded.');
return;
}
var checkPermission = function () {
try {
// Type '"microphone"' is not assignable to type 'PermissionName'.ts(2322)
// this is typescript issue
// https://github.com/microsoft/TypeScript/issues/33923
// @ts-expect-error
navigator.permissions.query({ name: 'microphone' }).then(function (result) {
if (result.state === 'denied') {
logger.warning('VoiceRecorder: Permission denied.');
setPermissionWarning(true);
}
});
}
catch (error) {
logger.warning('VoiceRecorder: Failed to check permission.', error);
}
};
logger.info('VoiceRecorder: Start recording.');
if (mediaRecorder) {
stop();
logger.info('VoiceRecorder: Previous mediaRecorder is stopped.');
}
checkPermission();
(_b = (_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) === null || _b === void 0 ? void 0 : _b.call(_a, { audio: true }).then(function (stream) {
var _a;
logger.info('VoiceRecorder: Succeeded getting media stream.', stream);
setIsRecordable(true);
var mediaRecorder = new MediaRecorder(stream, {
mimeType: browserSupportMimeType,
audioBitsPerSecond: VOICE_RECORDER_AUDIO_BIT_RATE,
});
// when recording stops
mediaRecorder.ondataavailable = function (e) {
logger.info('VoiceRecorder: Succeeded getting an available data.', e.data);
var audioFile = new File([e.data], VOICE_MESSAGE_FILE_NAME, {
lastModified: new Date().getTime(),
type: VOICE_MESSAGE_MIME_TYPE,
});
webAudioUtils === null || webAudioUtils === void 0 ? void 0 : webAudioUtils.downsampleToWav(audioFile, function (buffer) {
var _a;
var mp3Buffer = webAudioUtils === null || webAudioUtils === void 0 ? void 0 : webAudioUtils.encodeMp3(buffer);
var mp3blob = new Blob(mp3Buffer, { type: VOICE_MESSAGE_MIME_TYPE });
var convertedAudioFile = new File([mp3blob], VOICE_MESSAGE_FILE_NAME, {
lastModified: new Date().getTime(),
type: VOICE_MESSAGE_MIME_TYPE,
});
(_a = eventHandler === null || eventHandler === void 0 ? void 0 : eventHandler.onRecordingEnded) === null || _a === void 0 ? void 0 : _a.call(eventHandler, convertedAudioFile);
logger.info('VoiceRecorder: Succeeded converting audio file.', convertedAudioFile);
});
var tracks = stream.getAudioTracks();
tracks.forEach(function (track) { return track.stop(); });
setIsRecordable(false);
};
mediaRecorder.onstart = (_a = eventHandler === null || eventHandler === void 0 ? void 0 : eventHandler.onRecordingStarted) !== null && _a !== void 0 ? _a : noop;
mediaRecorder === null || mediaRecorder === void 0 ? void 0 : mediaRecorder.start();
setMediaRecorder(mediaRecorder);
}).catch(function (err) {
logger.error('VoiceRecorder: Failed getting media stream.', err);
setMediaRecorder(null);
});
}, [mediaRecorder, webAudioUtils]);
var stop = useCallback(function () {
// Stop recording
mediaRecorder === null || mediaRecorder === void 0 ? void 0 : mediaRecorder.stop();
setMediaRecorder(null);
setIsRecordable(false);
logger.info('VoiceRecorder: Stop recording.');
}, [mediaRecorder]);
return (React__default.createElement(Context.Provider, { value: { start: start, stop: stop, isRecordable: isRecordable } },
children,
permissionWarning && (React__default.createElement(Modal, { hideFooter: true, onClose: function () { return setPermissionWarning(false); } },
React__default.createElement(React__default.Fragment, null, stringSet.VOICE_RECORDING_PERMISSION_DENIED)))));
};
var useVoiceRecorderContext = function () { return useContext(Context); };
var index = {
VoiceRecorderProvider: VoiceRecorderProvider,
useVoiceRecorderContext: useVoiceRecorderContext,
};
export { VoiceRecorderProvider, index as default, useVoiceRecorderContext };
//# sourceMappingURL=context.js.map