stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
208 lines (207 loc) • 9.09 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WaveProgressBar = void 0;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _reactNativeGestureHandler = require("react-native-gesture-handler");
var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
var _ProgressThumb = require("./ProgressThumb");
var _ThemeContext = require("../../contexts/themeContext/ThemeContext");
var _theme = require("../../theme");
var _audioSampling = require("../MessageInput/utils/audioSampling");
var _jsxRuntime = require("react/jsx-runtime");
var _jsxFileName = "/home/runner/work/stream-chat-react-native/stream-chat-react-native/package/src/components/ProgressControl/WaveProgressBar.tsx";
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (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 WAVEFORM_WIDTH = 2;
var WAVEFORM_GAP = 2;
var WAVE_MAX_HEIGHT = 20;
var WAVE_MIN_HEIGHT = 2;
var DRAG_HIT_SLOP = {
bottom: 12,
left: 12,
right: 12,
top: 12
};
var clampProgress = progress => {
'worklet';
return Math.max(0, Math.min(progress, 1));
};
var WaveformBars = _react.default.memo(({
color,
heights,
waveformStyle
}) => (0, _jsxRuntime.jsx)(_reactNative.View, {
style: styles.waveformLayer,
children: heights.map((height, index) => (0, _jsxRuntime.jsx)(_reactNative.View, {
style: [styles.waveform, {
backgroundColor: color,
height
}, waveformStyle]
}, index))
}));
WaveformBars.displayName = 'WaveformBars';
var WaveProgressBar = exports.WaveProgressBar = _react.default.memo(props => {
var _useState = (0, _react.useState)(0),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
width = _useState2[0],
setWidth = _useState2[1];
var _props$amplitudesCoun = props.amplitudesCount,
amplitudesCount = _props$amplitudesCoun === void 0 ? Math.max(20, Math.floor(width / (WAVEFORM_WIDTH + WAVEFORM_GAP))) : _props$amplitudesCoun,
_props$isPlaying = props.isPlaying,
isPlaying = _props$isPlaying === void 0 ? false : _props$isPlaying,
onEndDrag = props.onEndDrag,
onProgressDrag = props.onProgressDrag,
onStartDrag = props.onStartDrag,
progress = props.progress,
waveformData = props.waveformData;
var _useState3 = (0, _react.useState)(() => progress > 0 || isPlaying),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
showInteractiveLayer = _useState4[0],
setShowInteractiveLayer = _useState4[1];
var isRTL = _reactNative.I18nManager.isRTL;
var thumbDirectionMultiplier = isRTL ? -1 : 1;
var eachWaveformWidth = WAVEFORM_WIDTH + WAVEFORM_GAP;
var fullWidth = (amplitudesCount - 1) * eachWaveformWidth;
var maxThumbTranslateX = Math.max(fullWidth - eachWaveformWidth, 0);
var maxProgressWidth = fullWidth + WAVEFORM_WIDTH;
var dragStartProgress = (0, _reactNativeReanimated.useSharedValue)(0);
var isDragging = (0, _reactNativeReanimated.useSharedValue)(false);
var visualProgress = (0, _reactNativeReanimated.useSharedValue)(progress);
var _useTheme = (0, _ThemeContext.useTheme)(),
_useTheme$theme = _useTheme.theme,
semantics = _useTheme$theme.semantics,
_useTheme$theme$waveP = _useTheme$theme.waveProgressBar,
container = _useTheme$theme$waveP.container,
thumb = _useTheme$theme$waveP.thumb,
waveformTheme = _useTheme$theme$waveP.waveform;
(0, _react.useEffect)(() => {
if (!isDragging.value) {
visualProgress.value = progress;
}
}, [isDragging, progress, visualProgress]);
(0, _react.useEffect)(() => {
setShowInteractiveLayer(progress > 0 || isPlaying);
}, [isPlaying, progress]);
var handleStartDrag = (0, _react.useCallback)(nextProgress => {
setShowInteractiveLayer(true);
onStartDrag?.(nextProgress);
}, [onStartDrag]);
var handleProgressDrag = (0, _react.useCallback)(nextProgress => {
onProgressDrag?.(nextProgress);
}, [onProgressDrag]);
var handleEndDrag = (0, _react.useCallback)(nextProgress => {
onEndDrag?.(nextProgress);
}, [onEndDrag]);
var pan = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Pan().hitSlop(DRAG_HIT_SLOP).maxPointers(1).onStart(() => {
var nextProgress = clampProgress(visualProgress.value);
dragStartProgress.value = nextProgress;
isDragging.value = true;
if (onStartDrag) {
(0, _reactNativeReanimated.runOnJS)(handleStartDrag)(nextProgress);
}
}).onUpdate(event => {
if (fullWidth <= 0) {
return;
}
var nextProgress = clampProgress(dragStartProgress.value + event.translationX * thumbDirectionMultiplier / fullWidth);
visualProgress.value = nextProgress;
if (onProgressDrag) {
(0, _reactNativeReanimated.runOnJS)(handleProgressDrag)(nextProgress);
}
}).onEnd(() => {
isDragging.value = false;
if (onEndDrag) {
(0, _reactNativeReanimated.runOnJS)(handleEndDrag)(visualProgress.value);
}
}), [dragStartProgress, fullWidth, handleEndDrag, handleProgressDrag, handleStartDrag, isDragging, onEndDrag, onProgressDrag, onStartDrag, thumbDirectionMultiplier, visualProgress]);
var stringifiedWaveformData = (0, _react.useMemo)(() => waveformData.toString(), [waveformData]);
var resampledWaveformData = (0, _react.useMemo)(() => (0, _audioSampling.resampleWaveformData)(waveformData, amplitudesCount), [amplitudesCount, stringifiedWaveformData]);
var waveformHeights = (0, _react.useMemo)(() => resampledWaveformData.map(waveform => waveform * WAVE_MAX_HEIGHT > WAVE_MIN_HEIGHT ? waveform * WAVE_MAX_HEIGHT : WAVE_MIN_HEIGHT), [resampledWaveformData]);
var progressOverlayStyles = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
width: clampProgress(visualProgress.value) * maxProgressWidth
}), [maxProgressWidth]);
var thumbStyles = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
position: 'absolute',
transform: [{
translateX: Math.min(clampProgress(visualProgress.value) * fullWidth, maxThumbTranslateX) * thumbDirectionMultiplier
}]
}), [fullWidth, maxThumbTranslateX, thumbDirectionMultiplier]);
return (0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, {
gesture: pan,
children: (0, _jsxRuntime.jsxs)(_reactNative.View, {
onLayout: ({
nativeEvent
}) => {
setWidth(nativeEvent.layout.width);
},
style: [styles.container, container],
children: [(0, _jsxRuntime.jsx)(WaveformBars, {
color: semantics.chatWaveformBar,
heights: waveformHeights,
waveformStyle: waveformTheme
}), showInteractiveLayer ? (0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
pointerEvents: "none",
style: [styles.progressOverlay, progressOverlayStyles],
children: (0, _jsxRuntime.jsx)(WaveformBars, {
color: semantics.chatWaveformBarPlaying,
heights: waveformHeights,
waveformStyle: waveformTheme
})
}) : null, (onEndDrag || onProgressDrag) && (showInteractiveLayer ? (0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
style: [thumbStyles, thumb],
children: (0, _jsxRuntime.jsx)(_ProgressThumb.ProgressControlThumb, {
isPlaying: isPlaying
})
}) : (0, _jsxRuntime.jsx)(_reactNative.View, {
style: [styles.idleThumb, thumb],
children: (0, _jsxRuntime.jsx)(_ProgressThumb.ProgressControlThumb, {
isPlaying: isPlaying
})
}))]
})
});
}, (prevProps, nextProps) => {
if (prevProps.amplitudesCount !== nextProps.amplitudesCount) {
return false;
}
if (prevProps.isPlaying !== nextProps.isPlaying) {
return false;
}
if (prevProps.progress !== nextProps.progress) {
return false;
} else {
return true;
}
});
var styles = _reactNative.StyleSheet.create({
container: {
alignItems: 'center',
flexDirection: 'row',
position: 'relative'
},
idleThumb: {
left: 0,
position: 'absolute'
},
progressOverlay: {
left: 0,
overflow: 'hidden',
position: 'absolute',
top: 0
},
waveformLayer: {
alignItems: 'center',
flexDirection: 'row',
gap: WAVEFORM_GAP
},
waveform: {
alignSelf: 'center',
borderRadius: _theme.primitives.radiusXxs,
width: WAVEFORM_WIDTH
}
});
WaveProgressBar.displayName = 'WaveProgressBar';
//# sourceMappingURL=WaveProgressBar.js.map