@chatui/core
Version:
The React library for Chatbot UI
142 lines (140 loc) • 5.88 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.VoiceInputStatus = exports.VoiceInput = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _canUse = _interopRequireDefault(require("../../utils/canUse"));
var _ClickOutside = require("../ClickOutside");
var _ConfigProvider = require("../ConfigProvider");
var _Icon = require("../Icon");
var _SoundWave = require("./SoundWave");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
var canPassive = (0, _canUse.default)('passiveListener');
var listenerOpts = canPassive ? {
passive: true
} : false;
var listenerOptsWithoutPassive = canPassive ? {
passive: false
} : false;
var MOVE_INTERVAL = 80;
var ts = 0;
var startY = 0;
/** 语音输入状态枚举 */
var VoiceInputStatus = exports.VoiceInputStatus = {
INITED: 'inited',
RECORDING: 'recording',
WILL_CANCEL: 'willCancel'
};
/** 状态文案映射 */
var statusTextMap = (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, VoiceInputStatus.INITED, 'hold2talk'), VoiceInputStatus.RECORDING, 'releaseOrSwipe'), VoiceInputStatus.WILL_CANCEL, 'release2send');
var VoiceInput = exports.VoiceInput = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
var onStart = props.onStart,
onEnd = props.onEnd,
onCancel = props.onCancel,
onClose = props.onClose,
onStatusChange = props.onStatusChange;
var _useState = (0, _react.useState)(VoiceInputStatus.INITED),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
status = _useState2[0],
setStatus = _useState2[1];
var btnRef = (0, _react.useRef)(null);
var _useLocale = (0, _ConfigProvider.useLocale)('VoiceInput'),
trans = _useLocale.trans;
var updateStatus = (0, _react.useCallback)(function (newStatus) {
setStatus(newStatus);
if (onStatusChange) {
onStatusChange(newStatus);
}
}, [onStatusChange]);
var doEnd = (0, _react.useCallback)(function () {
var duration = Date.now() - ts;
if (onEnd) {
onEnd({
duration: duration
});
}
}, [onEnd]);
var handleClose = (0, _react.useCallback)(function () {
updateStatus(VoiceInputStatus.INITED);
if (onClose) {
onClose();
}
}, [onClose, updateStatus]);
(0, _react.useImperativeHandle)(ref, function () {
return {
stop: function stop() {
updateStatus(VoiceInputStatus.INITED);
doEnd();
ts = 0;
}
};
});
(0, _react.useEffect)(function () {
var btn = btnRef.current;
if (!btn) return;
function handleTouchStart(e) {
if (e.cancelable) {
e.preventDefault();
}
var touch0 = e.touches[0];
startY = touch0.pageY;
ts = Date.now();
updateStatus(VoiceInputStatus.RECORDING);
if (onStart) {
onStart();
}
}
function handleTouchMove(e) {
if (!ts) return;
var nowY = e.touches[0].pageY;
var isCancel = startY - nowY > MOVE_INTERVAL;
updateStatus(isCancel ? VoiceInputStatus.WILL_CANCEL : VoiceInputStatus.RECORDING);
}
function handleTouchEnd(e) {
if (!ts) return;
var endY = e.changedTouches[0].pageY;
var isRecording = startY - endY < MOVE_INTERVAL;
updateStatus(VoiceInputStatus.INITED);
if (isRecording) {
doEnd();
} else if (onCancel) {
onCancel();
}
}
btn.addEventListener('touchstart', handleTouchStart, listenerOptsWithoutPassive);
btn.addEventListener('touchmove', handleTouchMove, listenerOpts);
btn.addEventListener('touchend', handleTouchEnd);
btn.addEventListener('touchcancel', handleTouchEnd);
return function () {
btn.removeEventListener('touchstart', handleTouchStart);
btn.removeEventListener('touchmove', handleTouchMove);
btn.removeEventListener('touchend', handleTouchEnd);
btn.removeEventListener('touchcancel', handleTouchEnd);
};
}, [doEnd, onCancel, onStart, updateStatus]);
var isRecording = status === VoiceInputStatus.RECORDING;
var isCancel = status === VoiceInputStatus.WILL_CANCEL;
return /*#__PURE__*/_react.default.createElement(_ClickOutside.ClickOutside, {
onClick: handleClose
}, /*#__PURE__*/_react.default.createElement("div", {
className: "VoiceInput",
"data-voice-status": status
}, /*#__PURE__*/_react.default.createElement("div", {
className: "VoiceInput-tip"
}, trans(statusTextMap[status])), /*#__PURE__*/_react.default.createElement("div", {
className: "VoiceInput-control"
}, isRecording && /*#__PURE__*/_react.default.createElement(_SoundWave.SoundWave, null), /*#__PURE__*/_react.default.createElement("div", {
className: "VoiceInput-btn",
role: "button",
"aria-label": trans(statusTextMap[status]),
ref: btnRef
}, /*#__PURE__*/_react.default.createElement(_Icon.Icon, {
className: "VoiceInput-btnIcon",
type: isCancel ? 'cancel' : 'mic'
})))));
});