@sendbird/uikit-react
Version:
Sendbird UIKit for React: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.
282 lines (275 loc) • 13.7 kB
JavaScript
import React__default, { createContext, useReducer, useContext } from 'react';
import { _ as __assign } from './bundle-DlZj_j5B.js';
import { l as VOICE_MESSAGE_FILE_NAME__XM4A, m as VOICE_MESSAGE_MIME_TYPE__XM4A, a as VOICE_MESSAGE_FILE_NAME, b as VOICE_MESSAGE_MIME_TYPE, n as VOICE_PLAYER_ROOT_ID, c as VOICE_PLAYER_AUDIO_ID } from './bundle-C8kxBudB.js';
import { a as isSafari } from './bundle-OJHU7Q3U.js';
import { u as useSendbird } from './bundle-BnaoVUUl.js';
var INITIALIZE_AUDIO_UNIT = 'INITIALIZE_AUDIO_UNIT';
var RESET_AUDIO_UNIT = 'RESET_AUDIO_UNIT';
var SET_CURRENT_PLAYER = 'SET_CURRENT_PLAYER';
var ON_VOICE_PLAYER_PLAY = 'ON_VOICE_PLAYER_PLAY';
var ON_VOICE_PLAYER_PAUSE = 'ON_VOICE_PLAYER_PAUSE';
var ON_CURRENT_TIME_UPDATE = 'ON_CURRENT_TIME_UPDATE';
var VOICE_PLAYER_STATUS = {
IDLE: 'IDLE',
PREPARING: 'PREPARING',
PLAYING: 'PLAYING',
PAUSED: 'PAUSED',
COMPLETED: 'COMPLETED',
};
var AudioUnitDefaultValue = function () { return ({
audioFile: null,
playbackTime: 0,
duration: 1000,
playingStatus: VOICE_PLAYER_STATUS.IDLE,
}); };
var voicePlayerInitialState = {
currentPlayer: null,
currentGroupKey: '',
audioStorage: {},
};
function voicePlayerReducer(state, action) {
var _a, _b, _c, _d, _e;
var _f, _g, _h, _j;
switch (action.type) {
case INITIALIZE_AUDIO_UNIT: {
var groupKey = action.payload.groupKey;
var audioUnit = (((_f = state.audioStorage) === null || _f === void 0 ? void 0 : _f[groupKey]) ? state.audioStorage[groupKey] : AudioUnitDefaultValue());
audioUnit.playingStatus = VOICE_PLAYER_STATUS.PREPARING;
return __assign(__assign({}, state), { audioStorage: __assign(__assign({}, state.audioStorage), (_a = {}, _a[groupKey] = audioUnit, _a)) });
}
case RESET_AUDIO_UNIT: {
var groupKey = action.payload.groupKey;
return __assign(__assign({}, state), { audioStorage: __assign(__assign({}, state.audioStorage), (_b = {}, _b[groupKey] = AudioUnitDefaultValue(), _b)) });
}
case SET_CURRENT_PLAYER: {
var _k = action.payload, audioPlayer = _k.audioPlayer, groupKey = _k.groupKey;
return __assign(__assign({}, state), { currentPlayer: audioPlayer, currentGroupKey: groupKey });
}
case ON_VOICE_PLAYER_PLAY: {
var _l = action.payload, groupKey = _l.groupKey, audioFile = _l.audioFile;
var audioUnit = (((_g = state.audioStorage) === null || _g === void 0 ? void 0 : _g[groupKey]) ? state.audioStorage[groupKey] : AudioUnitDefaultValue());
audioUnit.audioFile = audioFile;
audioUnit.playingStatus = VOICE_PLAYER_STATUS.PLAYING;
return __assign(__assign({}, state), { audioStorage: __assign(__assign({}, state.audioStorage), (_c = {}, _c[groupKey] = audioUnit, _c)) });
}
case ON_VOICE_PLAYER_PAUSE: {
var _m = action.payload, groupKey = _m.groupKey, duration = _m.duration, currentTime = _m.currentTime;
var audioUnit = (((_h = state.audioStorage) === null || _h === void 0 ? void 0 : _h[groupKey]) ? state.audioStorage[groupKey] : AudioUnitDefaultValue());
audioUnit.playingStatus = VOICE_PLAYER_STATUS.PAUSED;
if (duration === currentTime) {
audioUnit.playbackTime = 0;
}
return __assign(__assign({}, state), { audioStorage: __assign(__assign({}, state.audioStorage), (_d = {}, _d[groupKey] = audioUnit, _d)) });
}
case ON_CURRENT_TIME_UPDATE: {
var groupKey = action.payload.groupKey;
var _o = state.currentPlayer, currentTime = _o.currentTime, duration = _o.duration;
var audioUnit = (((_j = state.audioStorage) === null || _j === void 0 ? void 0 : _j[groupKey]) ? state.audioStorage[groupKey] : AudioUnitDefaultValue());
// sometimes the final time update is fired AFTER the pause event when audio is finished
if (audioUnit.playbackTime === audioUnit.duration && audioUnit.playingStatus === VOICE_PLAYER_STATUS.PAUSED) {
audioUnit.playbackTime = 0;
}
else if (currentTime > 0 && duration > 0) {
audioUnit.playbackTime = currentTime;
audioUnit.duration = duration;
}
return __assign(__assign({}, state), { audioStorage: __assign(__assign({}, state.audioStorage), (_e = {}, _e[groupKey] = audioUnit, _e)) });
}
default:
return state;
}
}
var generateGroupKey = function (channelUrl, key) {
if (channelUrl === void 0) { channelUrl = ''; }
if (key === void 0) { key = ''; }
return ("".concat(channelUrl, "-").concat(key));
};
/**
* Parses and returns the correct MIME type based on the browser.
* If the browser is Safari and the file type is m4a, use 'audio/x-m4a' for the audio player.
* Safari doesn't support 'audio/mp3' well.
* Also, 'audio/m4a' should be converted to 'audio/x-m4a' to be correctly played in Safari.
* @link: https://sendbird.atlassian.net/browse/CLNP-2997
*
* @param mimeType - The original MIME type.
* @returns Converted file name and MIME type.
*/
var getParsedVoiceAudioFileInfo = function (mimeType) {
if (isSafari(navigator.userAgent) && mimeType.includes('m4a')) {
return {
name: VOICE_MESSAGE_FILE_NAME__XM4A,
mimeType: VOICE_MESSAGE_MIME_TYPE__XM4A,
};
}
return {
name: VOICE_MESSAGE_FILE_NAME,
mimeType: VOICE_MESSAGE_MIME_TYPE,
};
};
var ALL = 'ALL';
var noop = function () { };
var VoicePlayerStoreDefaultValue = {
currentGroupKey: '',
currentPlayer: null,
audioStorage: {},
};
var Context = createContext({
play: noop,
pause: noop,
stop: noop,
voicePlayerStore: VoicePlayerStoreDefaultValue,
});
var VoicePlayerProvider = function (_a) {
var children = _a.children;
var _b = useReducer(voicePlayerReducer, voicePlayerInitialState), voicePlayerStore = _b[0], voicePlayerDispatcher = _b[1];
var currentGroupKey = voicePlayerStore.currentGroupKey, currentPlayer = voicePlayerStore.currentPlayer, audioStorage = voicePlayerStore.audioStorage;
var state = useSendbird().state;
var config = state.config;
var logger = config.logger;
var stop = function (text) {
if (text === void 0) { text = ''; }
if (currentGroupKey.includes(text)) {
logger.info('VoicePlayer: Pause playing(by text).');
pause(currentGroupKey);
}
};
var pause = function (groupKey) {
if (currentPlayer) {
if (groupKey === currentGroupKey) {
logger.info('VoicePlayer: Pause playing(by group key).');
currentPlayer.pause();
}
else if (groupKey === ALL) {
logger.info('VoicePlayer: Pause playing(all).');
currentPlayer.pause();
}
}
else {
logger.warning('VoicePlayer: No currentPlayer to pause.');
}
};
var play = function (_a) {
var groupKey = _a.groupKey, audioFile = _a.audioFile, _b = _a.audioFileUrl, audioFileUrl = _b === void 0 ? '' : _b, _c = _a.audioFileMimeType, audioFileMimeType = _c === void 0 ? VOICE_MESSAGE_MIME_TYPE : _c;
if (groupKey !== currentGroupKey) {
pause(currentGroupKey);
}
// Clear the previous AudioPlayer element
var voicePlayerRoot = document.getElementById(VOICE_PLAYER_ROOT_ID);
var voicePlayerAudioElement = document.getElementById(VOICE_PLAYER_AUDIO_ID);
if (voicePlayerRoot && voicePlayerAudioElement) {
voicePlayerRoot.removeChild(voicePlayerAudioElement);
}
logger.info('VoicePlayer: Start getting audio file.');
new Promise(function (resolve, reject) {
var _a;
voicePlayerDispatcher({
type: INITIALIZE_AUDIO_UNIT,
payload: { groupKey: groupKey },
});
// audio file passed as a parameter
if (audioFile) {
logger.info('VoicePlayer: Use the audioFile instance.');
resolve(audioFile);
return;
}
// audio file from the audioStorage
var cachedAudioFile = (_a = audioStorage === null || audioStorage === void 0 ? void 0 : audioStorage[groupKey]) === null || _a === void 0 ? void 0 : _a.audioFile;
if (cachedAudioFile) {
logger.info('VoicePlayer: Get from the audioStorage.');
resolve(cachedAudioFile);
return;
}
// fetch the audio file from URL
fetch(audioFileUrl)
.then(function (res) { return res.blob(); })
.then(function (blob) {
var audioFile = new File([blob], getParsedVoiceAudioFileInfo(audioFileMimeType).name, {
lastModified: new Date().getTime(),
type: getParsedVoiceAudioFileInfo(audioFileMimeType).mimeType,
});
resolve(audioFile);
logger.info('VoicePlayer: Get the audioFile from URL.');
})
.catch(reject);
})
.then(function (audioFile) {
var _a;
var voicePlayerRoot = document.getElementById(VOICE_PLAYER_ROOT_ID);
logger.info('VoicePlayer: Succeeded getting audio file.', { audioFile: audioFile });
var currentAudioUnit = audioStorage[groupKey] || AudioUnitDefaultValue();
var audioPlayer = new Audio((_a = URL === null || URL === void 0 ? void 0 : URL.createObjectURL) === null || _a === void 0 ? void 0 : _a.call(URL, audioFile));
audioPlayer.id = VOICE_PLAYER_AUDIO_ID;
audioPlayer.currentTime = currentAudioUnit.playbackTime;
audioPlayer.volume = 1;
audioPlayer.loop = false;
audioPlayer.onplaying = function () {
logger.info('VoicePlayer: OnPlaying event is called from audioPlayer', { groupKey: groupKey, audioPlayer: audioPlayer });
voicePlayerDispatcher({
type: ON_VOICE_PLAYER_PLAY,
payload: { groupKey: groupKey, audioFile: audioFile },
});
};
audioPlayer.onpause = function () {
logger.info('VoicePlayer: OnPause event is called from audioPlayer', { groupKey: groupKey, audioPlayer: audioPlayer });
voicePlayerDispatcher({
type: ON_VOICE_PLAYER_PAUSE,
payload: { groupKey: groupKey, duration: audioPlayer.duration, currentTime: audioPlayer.currentTime },
});
};
audioPlayer.ontimeupdate = function () {
voicePlayerDispatcher({
type: ON_CURRENT_TIME_UPDATE,
payload: { groupKey: groupKey },
});
};
audioPlayer.onerror = function (error) {
logger.error('VoicePlayer: Failed to load the audioFile on the audio player.', error);
voicePlayerDispatcher({
type: RESET_AUDIO_UNIT,
payload: { groupKey: groupKey },
});
};
audioPlayer.dataset.sbGroupId = groupKey;
// clean up the previous audio player
try {
voicePlayerRoot === null || voicePlayerRoot === void 0 ? void 0 : voicePlayerRoot.childNodes.forEach(function (node) {
var _a, _b;
var element = node;
var thisGroupKey = (_a = element.dataset) === null || _a === void 0 ? void 0 : _a.sbGroupKey;
if (thisGroupKey !== groupKey) {
(_b = element === null || element === void 0 ? void 0 : element.pause) === null || _b === void 0 ? void 0 : _b.call(element);
voicePlayerRoot.removeChild(element);
logger.info('VoicePlayer: Removed other player.', { element: element });
}
});
}
finally {
audioPlayer === null || audioPlayer === void 0 ? void 0 : audioPlayer.play();
voicePlayerRoot === null || voicePlayerRoot === void 0 ? void 0 : voicePlayerRoot.appendChild(audioPlayer);
voicePlayerDispatcher({
type: SET_CURRENT_PLAYER,
payload: { groupKey: groupKey, audioPlayer: audioPlayer },
});
logger.info('VoicePlayer: Succeeded playing audio player.', { groupKey: groupKey, audioPlayer: audioPlayer });
}
})
.catch(function (error) {
logger.warning('VoicePlayer: Failed loading audio file with URL.', error);
voicePlayerDispatcher({
type: RESET_AUDIO_UNIT,
payload: { groupKey: groupKey },
});
});
};
return (React__default.createElement(Context.Provider, { value: {
play: play,
pause: pause,
stop: stop,
voicePlayerStore: voicePlayerStore,
} },
React__default.createElement("div", { id: VOICE_PLAYER_ROOT_ID, style: { display: 'none' } }),
children));
};
var useVoicePlayerContext = function () { return useContext(Context); };
export { AudioUnitDefaultValue as A, VOICE_PLAYER_STATUS as V, VoicePlayerProvider as a, ALL as b, generateGroupKey as g, useVoicePlayerContext as u };
//# sourceMappingURL=bundle-DaRQ4hYm.js.map