@raishid/react-native-voice-message-player
Version:
An intuitive and customizable React Native module for playing voice messages seamlessly in chat interfaces. This package offers out-of-the-box components and easy-to-use configurations to integrate voice message playback functionality in your application.
1,038 lines (1,014 loc) • 30.5 kB
JavaScript
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
// src/assets/imgs/playing.png
var require_playing = __commonJS({
"src/assets/imgs/playing.png"(exports, module) {
module.exports = "./assets/playing-7JJDQBGU.png";
}
});
// src/assets/imgs/pause.png
var require_pause = __commonJS({
"src/assets/imgs/pause.png"(exports, module) {
module.exports = "./assets/pause-5TL2VU7X.png";
}
});
// src/assets/imgs/download.png
var require_download = __commonJS({
"src/assets/imgs/download.png"(exports, module) {
module.exports = "./assets/download-R6LJVGQS.png";
}
});
// src/assets/imgs/loading.png
var require_loading = __commonJS({
"src/assets/imgs/loading.png"(exports, module) {
module.exports = "./assets/loading-OKBI45CP.png";
}
});
// src/assets/imgs/error.png
var require_error = __commonJS({
"src/assets/imgs/error.png"(exports, module) {
module.exports = "./assets/error-7AKRDX7S.png";
}
});
// src/assets/imgs/clock-loader.png
var require_clock_loader = __commonJS({
"src/assets/imgs/clock-loader.png"(exports, module) {
module.exports = "./assets/clock-loader-NVOFPLNM.png";
}
});
// src/assets/imgs/single-check.png
var require_single_check = __commonJS({
"src/assets/imgs/single-check.png"(exports, module) {
module.exports = "./assets/single-check-QI6G3XSJ.png";
}
});
// src/assets/imgs/double-check.png
var require_double_check = __commonJS({
"src/assets/imgs/double-check.png"(exports, module) {
module.exports = "./assets/double-check-5OEVGBYY.png";
}
});
// src/assets/imgs/avatar.png
var require_avatar = __commonJS({
"src/assets/imgs/avatar.png"(exports, module) {
module.exports = "./assets/avatar-QBEUALAS.png";
}
});
// src/assets/imgs/mic.png
var require_mic = __commonJS({
"src/assets/imgs/mic.png"(exports, module) {
module.exports = "./assets/mic-Y5FYMMZZ.png";
}
});
// src/RNVoiceMessagePlayer.tsx
import React6, {
useState as useState3,
useRef,
useEffect as useEffect3,
useImperativeHandle
} from "react";
import { View as View5, Text as Text3, StyleSheet as StyleSheet6 } from "react-native";
import { Audio } from "expo-av";
import * as FileSystem from "expo-file-system";
// src/helpers/theme.ts
var theme_default = {
colors: {
primary: "#FF3B30",
secondary: "#F1F1F1",
tertiary: "#FFFFFF",
primaryBackground: "#FFFFFF",
secondaryBackground: "rgba(249,249,249,0.94)",
disabled: "#D1D1D6",
accent: "#000",
label: "rgba(60,60,67,0.3)",
secondaryLabel: "rgb(150,150,150)"
},
typography: {
family: void 0
},
roundness: 12
};
// src/components/PlayPauseButton.tsx
import React, { useEffect, useState } from "react";
import { Image, StyleSheet, TouchableOpacity } from "react-native";
import { jsx } from "react/jsx-runtime";
var defaultSources = {
playing: require_playing(),
pause: require_pause(),
download: require_download(),
loading: require_loading(),
error: require_error()
};
var PlayPauseButton = ({
isPlaying = false,
isDownloadable = false,
onPress,
onDownload,
disabled = false,
isLoading = true,
isError = false,
theme = theme_default,
style,
configSources = {},
leftActionImgStyle
}) => {
disabled = disabled || isLoading;
const buttonAction = isDownloadable || isError ? onDownload : onPress;
const sources = { ...defaultSources, ...configSources };
const selectedTheme = { ...theme_default, ...theme };
const [icon, setIcon] = useState(sources.pause);
useEffect(() => {
setIcon(sources.pause);
if (isLoading) setIcon(sources.loading);
if (isError) setIcon(sources.error);
if (isDownloadable) setIcon(sources.download);
if (isPlaying) setIcon(sources.playing);
}, [isPlaying, isDownloadable, isError, isLoading, isPlaying]);
return /* @__PURE__ */ jsx(
TouchableOpacity,
{
disabled,
activeOpacity: 0.5,
onPress: buttonAction,
style: [styles.container, style],
children: /* @__PURE__ */ jsx(
Image,
{
source: icon,
style: [
styles.image,
{
tintColor: disabled ? selectedTheme?.colors?.disabled : selectedTheme?.colors?.accent
},
leftActionImgStyle
]
}
)
}
);
};
var styles = StyleSheet.create({
container: {
justifyContent: "center",
alignItems: "center"
},
image: {
height: 18,
tintColor: "black",
width: 18,
marginRight: 16,
marginLeft: 8,
marginVertical: 8,
resizeMode: "contain"
}
});
var PlayPauseButton_default = React.memo(PlayPauseButton);
// src/components/DownloadProgressBar.tsx
import React2 from "react";
import { StyleSheet as StyleSheet2, View, Text } from "react-native";
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
var DownloadProgressBar = ({
percentage = 0,
theme = theme_default,
renderComponent
}) => {
const selectedTheme = { ...theme_default, ...theme };
const displayPercentage = Math.min(100, Math.max(0, Math.floor(percentage)));
if (renderComponent) {
return renderComponent({
percentage: displayPercentage.toFixed(1),
theme: selectedTheme
});
}
return /* @__PURE__ */ jsxs(
View,
{
style: [
styles2.triangle,
{ backgroundColor: selectedTheme.colors?.secondaryBackground }
],
children: [
/* @__PURE__ */ jsx2(
View,
{
style: [
styles2.loader,
{
width: `${displayPercentage}%`,
backgroundColor: selectedTheme.colors?.label
}
]
}
),
/* @__PURE__ */ jsxs(Text, { style: [styles2.text, { color: selectedTheme?.colors?.accent }], children: [
"Downloading: ",
displayPercentage,
"%"
] })
]
}
);
};
var styles2 = StyleSheet2.create({
triangle: {
height: 11,
flex: 1,
borderRadius: 11,
overflow: "hidden",
position: "relative",
justifyContent: "center"
},
loader: {
height: "100%",
borderRadius: 11,
opacity: 0.6
},
text: {
fontSize: 7,
position: "absolute",
fontWeight: "bold",
textAlign: "center",
alignSelf: "center",
textTransform: "capitalize",
textDecorationLine: "none",
fontStyle: "italic",
opacity: 0.6
}
});
var DownloadProgressBar_default = React2.memo(DownloadProgressBar);
// src/components/TrackerTimers.tsx
import { StyleSheet as StyleSheet3, View as View2, Text as Text2, Image as Image2 } from "react-native";
// src/helpers/secondsToTime.ts
var secondsToTime = (seconds) => {
const minutes = String(Math.floor(seconds / 60)).padStart(2, "0");
const remainingSeconds = String(seconds % 60).padStart(2, "0");
return `${minutes}:${remainingSeconds}`;
};
var secondsToTime_default = secondsToTime;
// src/components/TrackerTimers.tsx
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
var defaultStatusSources = {
loading: require_clock_loader(),
"single-check": require_single_check(),
"double-check": require_double_check(),
"double-check-viewed": require_double_check()
};
var TrackerTimers = ({
theme = theme_default,
timer,
timestamp,
renderTimer,
renderTimestamp,
status,
statusSources
}) => {
const selectedTheme = { ...theme_default, ...theme };
statusSources = { ...defaultStatusSources, ...statusSources };
return /* @__PURE__ */ jsxs2(View2, { style: styles3.container, children: [
renderTimer ? renderTimer({ timer }) : /* @__PURE__ */ jsx3(
Text2,
{
style: [
styles3.timerText,
{
color: selectedTheme?.colors?.accent,
fontFamily: selectedTheme?.typography?.family
}
],
children: secondsToTime_default(Math.floor(timer))
}
),
/* @__PURE__ */ jsxs2(View2, { style: styles3.rightContainer, children: [
renderTimestamp ? renderTimestamp({ timestamp }) : /* @__PURE__ */ jsx3(
Text2,
{
style: [
styles3.timestampText,
{
color: selectedTheme?.colors?.accent,
fontFamily: selectedTheme?.typography?.family
}
],
children: timestamp
}
),
status && statusSources?.[status] && /* @__PURE__ */ jsx3(
Image2,
{
source: statusSources?.[status],
style: [
styles3.statusIcon,
{
tintColor: status === "double-check-viewed" ? selectedTheme?.colors?.primary : selectedTheme?.colors?.secondaryLabel
}
]
}
)
] })
] });
};
var styles3 = StyleSheet3.create({
container: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
flex: 1
},
timerText: {
fontSize: 8
},
timestampText: {
fontSize: 8
},
rightContainer: {
flexDirection: "row",
alignItems: "center"
},
statusIcon: {
height: 8,
width: 10,
marginLeft: 4,
resizeMode: "contain"
}
});
var TrackerTimers_default = TrackerTimers;
// src/components/TrackerLine.tsx
import { useEffect as useEffect2, useState as useState2 } from "react";
import { StyleSheet as StyleSheet4, View as View3 } from "react-native";
import MultiSlider from "@ptomasroos/react-native-multi-slider";
import { jsx as jsx4 } from "react/jsx-runtime";
var TrackerLine = ({
theme = theme_default,
thumbSize = 16,
disabled = false,
totalValue = 0,
currentValue = 0,
onValuesChange,
onValuesChangeStart,
onValuesChangeFinish,
renderComponent,
thumbColor
}) => {
if (!totalValue) return null;
const selectedTheme = { ...theme_default, ...theme };
const [containerWidth, setContainerWidth] = useState2(0);
const [sliderLength, setSliderSlength] = useState2(0);
useEffect2(() => {
setSliderSlength(containerWidth);
}, [containerWidth]);
if (renderComponent) {
return renderComponent();
}
return /* @__PURE__ */ jsx4(
View3,
{
style: styles4.container,
onLayout: (e) => {
const width = e.nativeEvent.layout.width;
const calculatedWidth = width - width / 100 * 10;
setContainerWidth(calculatedWidth);
},
children: /* @__PURE__ */ jsx4(
MultiSlider,
{
min: 0,
max: totalValue,
values: [currentValue],
sliderLength,
onValuesChange: (val) => onValuesChange(disabled ? currentValue : val[0]),
onValuesChangeStart,
onValuesChangeFinish: (val) => onValuesChangeFinish(disabled ? currentValue : val[0]),
selectedStyle: {
borderColor: disabled ? selectedTheme?.colors?.disabled : selectedTheme?.colors?.label,
height: 0,
borderTopWidth: 1.5
},
step: 1,
snapped: true,
unselectedStyle: {
borderColor: selectedTheme?.colors?.secondary,
height: 0,
borderTopWidth: 1.5
},
markerStyle: {
...styles4.marker,
backgroundColor: disabled ? selectedTheme?.colors?.disabled : thumbColor || selectedTheme?.colors?.secondaryLabel,
height: thumbSize,
width: thumbSize,
borderColor: selectedTheme?.colors?.primaryBackground
}
}
)
}
);
};
var styles4 = StyleSheet4.create({
container: {
flex: 1,
flexDirection: "row"
},
marker: {
shadowOpacity: 0,
elevation: 0,
borderWidth: 2
}
});
var TrackerLine_default = TrackerLine;
// src/components/extraction/Profiling.tsx
import React5 from "react";
// src/components/Avatar.tsx
import React4 from "react";
import { View as View4, Image as Image3, StyleSheet as StyleSheet5, TouchableOpacity as TouchableOpacity2 } from "react-native";
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var AvatarIcon = require_avatar();
var MicIcon = require_mic();
var Avatar = ({
renderMic,
renderImage,
theme = theme_default,
disabled,
micPosition = "left",
onImagePress,
imageSource,
micSource,
micColor
}) => {
const selectedTheme = { ...theme_default, ...theme };
return /* @__PURE__ */ jsxs3(View4, { style: styles5.container, children: [
renderImage ? imageSource && renderImage({ imageSource }) : /* @__PURE__ */ jsx5(
TouchableOpacity2,
{
disabled: disabled || !onImagePress,
activeOpacity: 0.5,
onPress: onImagePress,
style: [
styles5.avatarContainer,
{ borderColor: selectedTheme?.colors?.secondary }
],
children: /* @__PURE__ */ jsx5(
Image3,
{
source: imageSource || AvatarIcon,
style: [
styles5.avatar,
!imageSource && {
tintColor: selectedTheme?.colors?.secondary
}
]
}
)
}
),
renderMic ? micSource && renderMic({ micSource }) : /* @__PURE__ */ jsx5(
Image3,
{
source: micSource || MicIcon,
style: [
styles5.mic,
{
tintColor: micColor || selectedTheme?.colors?.secondaryLabel,
[micPosition]: -6
}
]
}
)
] });
};
var styles5 = StyleSheet5.create({
container: {
flexDirection: "row",
alignItems: "center"
},
avatarContainer: {
height: 40,
width: 40,
borderRadius: 20,
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent",
borderWidth: 0.5,
overflow: "hidden"
},
avatar: {
height: "100%",
width: "100%",
resizeMode: "cover",
borderRadius: 20
},
mic: {
height: 15,
width: 15,
resizeMode: "contain",
position: "absolute",
bottom: 3
}
});
var Avatar_default = React4.memo(Avatar);
// src/components/extraction/Profiling.tsx
import { jsx as jsx6 } from "react/jsx-runtime";
var Profiling = React5.memo((props) => {
const {
micSource,
imageSource,
theme,
isPlayed,
onImagePress,
ProfileImagePressDisabled,
renderProfileImage,
renderProfileMic,
profilePosition
} = props;
if (props.renderProfile && typeof props.renderProfile === "function") {
if (micSource && imageSource) {
return props.renderProfile({
micSource,
imageSource
});
}
}
return /* @__PURE__ */ jsx6(
Avatar_default,
{
micColor: isPlayed ? theme?.colors?.primary : theme?.colors?.secondaryLabel,
micPosition: profilePosition === "right" ? "left" : "right",
renderImage: renderProfileImage,
renderMic: renderProfileMic,
imageSource,
micSource,
onImagePress,
disabled: ProfileImagePressDisabled
}
);
});
var Profiling_default = React5.memo(Profiling);
// src/RNVoiceMessagePlayer.tsx
import { format } from "date-fns";
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
var VoicePlayerComponent = (props, ref) => {
const {
bottomProps: {
bottomContainerStyle = {},
bottomStatusSources = {},
renderBottom,
renderBottomTimer,
renderBottomTimestamp
} = {},
leftActionProps: {
leftActionContainerStyle = {},
leftActionSources = {},
leftActionImgStyle,
renderLeftAction
} = {},
profileProps: {
profileImageSource = {},
profileMicSource = {},
ProfileImagePressDisabled = false,
onProfileImagePress,
profileContainerStyle = {},
profilePosition = "right",
renderProfile,
renderProfileImage,
renderProfileMic
} = {},
trackProps: {
onTrackChange,
onTrackChangeComplete,
onTrackChangeStart,
renderTrack
} = {},
chatStatusProps: {
isNew = false,
isPlayed = false,
status = "single-check"
} = {},
timestamp,
autoDownload,
containerStyle,
customTheme,
onDownload,
onDownloadFailed,
onDownloadSaved,
onDownloadSuccess,
onError,
onLoadFailed,
onLoadStart,
onLoadSuccess,
onLoading,
onPause,
onPlay,
renderDownloadProgress,
renderText,
textError = "Audio is not playable",
textLoading = "Loading...",
textNotDownloaded = "Download voice message",
source,
showProfileAvatar = false,
trackContainerStyle
} = props || {};
const audioSrc = typeof source === "object" ? source.uri : source;
const [isPlaying, setIsPlaying] = useState3(false);
const [tempPause, setTempPause] = useState3(false);
const [duration, setDuration] = useState3(0);
const [currentTime, setCurrentTime] = useState3(0);
const [isDownloading, setIsDownloading] = useState3(false);
const [downloadProgress, setDownloadProgress] = useState3(0);
const [isDownloaded, setIsDownloaded] = useState3(false);
const [initializing, setInitializing] = useState3(false);
const [error, setError] = useState3(false);
const soundRef = useRef(null);
const [time] = useState3(timestamp ? timestamp : format(/* @__PURE__ */ new Date(), "hh:mm"));
const selectedTheme = { ...theme_default, ...customTheme };
const isURL = typeof audioSrc === "string" && audioSrc?.startsWith("http");
const timerValue = duration - currentTime >= 0 ? duration - currentTime : duration;
const playSound = () => {
if (soundRef.current === null) return;
setIsPlaying(true);
soundRef.current.playAsync().then((res) => {
if (res.isLoaded && res.isPlaying) {
typeof onPlay === "function" && onPlay();
} else {
const errorMsg = "Playback failed due to audio decoding error";
typeof onError === "function" && onError(new Error(errorMsg));
console.error(errorMsg);
return;
}
});
};
const pauseSound = () => {
if (soundRef.current === null) return;
soundRef.current.pauseAsync().then(() => {
setIsPlaying(false);
typeof onPause === "function" && onPause();
});
};
const downloadAndPlayAudio = async () => {
if (isURL) {
setIsDownloaded(false);
console.log("Received URL based sound.");
setIsDownloading(true);
console.log("Downloading started...");
typeof onDownload === "function" && onDownload();
const timestamp2 = (/* @__PURE__ */ new Date()).getTime();
const randomNum = Math.floor(Math.random() * 1e3);
const uniqueFileName = `audio_${timestamp2}_${randomNum}.mp3`;
const localPath = `${FileSystem.cacheDirectory}/${uniqueFileName}`;
console.log("Saving to: ", localPath);
const resumableD = FileSystem.createDownloadResumable(
audioSrc,
localPath,
{},
(downloadProgress2) => {
const progress = downloadProgress2.totalBytesWritten / downloadProgress2.totalBytesExpectedToWrite;
setDownloadProgress(progress);
}
);
resumableD.downloadAsync().then((_uri) => {
setIsDownloading(false);
console.info("Received URL downloaded successfully!");
typeof onDownloadSuccess === "function" && onDownloadSuccess(localPath);
FileSystem.getInfoAsync(localPath).then(({ exists }) => {
if (exists) {
typeof onDownloadSaved === "function" && onDownloadSaved(localPath);
console.info("Downloaded sound saved successfully!");
loadSound(localPath);
}
});
}).catch((err) => {
const errorMsg = "Received URL threw error while downloading: " + err;
console.error(errorMsg);
setError(true);
setIsDownloading(false);
typeof onDownloadFailed === "function" && onDownloadFailed(new Error(errorMsg));
});
} else {
setIsDownloaded(true);
console.log("Received Local URL based sound.");
loadSound(audioSrc);
}
};
const togglePlayPause = () => {
if (isPlaying) {
pauseSound();
} else {
playSound();
}
};
const playBackOnStatus = async (res) => {
if (res.isLoaded && res.isPlaying) {
const seg = res.positionMillis / 1e3;
setCurrentTime(seg);
}
if (res.isLoaded && !res.isPlaying) {
if (res.durationMillis && res.durationMillis <= res.positionMillis) {
setCurrentTime(0);
setIsPlaying(false);
await soundRef.current?.pauseAsync();
await soundRef.current?.setPositionAsync(0);
}
}
};
const loadSound = async (filePath) => {
setInitializing(true);
setIsDownloaded(true);
typeof onLoadStart === "function" && onLoadStart();
console.log("Initializing Sound...");
let soudSource;
if (typeof filePath === "string") {
soudSource = { uri: filePath };
} else {
soudSource = filePath;
}
try {
const _sound = await Audio.Sound.createAsync(
soudSource,
{
positionMillis: 0
},
playBackOnStatus
);
soundRef.current = _sound.sound;
const soundstatus = await _sound.sound.getStatusAsync();
if (soundstatus.isLoaded && soundstatus.durationMillis) {
setDuration(soundstatus.durationMillis / 1e3);
}
typeof onLoadSuccess === "function" && onLoadSuccess(soundRef.current);
console.info("Sound Initialized Successfully!");
setInitializing(false);
} catch (err) {
setInitializing(false);
const errorMsg = "Sound Initialized Failed: " + err;
typeof onLoadFailed === "function" && onLoadFailed(new Error(errorMsg));
typeof onError === "function" && onError(new Error(errorMsg));
console.error(errorMsg);
setError(error);
return;
}
};
const unMount = async () => {
if (soundRef.current) {
await soundRef.current.unloadAsync();
soundRef.current = null;
}
};
useEffect3(() => {
if (typeof onLoading === "function") {
if (initializing || isDownloading) {
onLoading();
}
}
}, [initializing, isDownloading, onLoading]);
useEffect3(() => {
downloadAndPlayAudio();
return () => {
unMount();
};
}, [audioSrc, autoDownload]);
useImperativeHandle(ref, () => ({
play: playSound,
pause: pauseSound,
load: loadSound,
loadWithDownload: downloadAndPlayAudio,
getSoundRef: () => soundRef.current,
getDuration: () => duration,
getIsDownloading: () => isDownloading,
getIsDownloaded: () => isDownloaded,
getDownloadProgress: () => downloadProgress,
getPlayingStatus: () => isPlaying,
getTimerInSeconds: () => timerValue,
togglePlayingStatus: () => togglePlayPause
}));
return /* @__PURE__ */ jsxs4(
View5,
{
style: [
styles6.container,
{
backgroundColor: selectedTheme?.colors?.primaryBackground,
borderRadius: selectedTheme?.roundness
},
containerStyle
],
children: [
showProfileAvatar && profilePosition === "left" && /* @__PURE__ */ jsx7(View5, { style: [styles6.profileContainerStyle, profileContainerStyle], children: /* @__PURE__ */ jsx7(
Profiling_default,
{
micSource: profileMicSource,
imageSource: profileImageSource,
theme: selectedTheme,
isPlayed,
onImagePress: onProfileImagePress,
ProfileImagePressDisabled,
renderProfileImage,
renderProfileMic,
profilePosition,
renderProfile
}
) }),
typeof renderLeftAction === "function" ? renderLeftAction({
isLoading: initializing || isDownloading,
isError: error,
isDownloaded,
isDownloading,
isPlaying
}) : /* @__PURE__ */ jsx7(
PlayPauseButton_default,
{
style: leftActionContainerStyle,
theme: selectedTheme,
configSources: leftActionSources,
disabled: isDownloading,
onDownload: downloadAndPlayAudio,
isPlaying,
onPress: togglePlayPause,
isDownloadable: !isDownloaded,
isLoading: initializing || isDownloading,
isError: error,
leftActionImgStyle
}
),
/* @__PURE__ */ jsxs4(View5, { style: [styles6.centerView, trackContainerStyle], children: [
typeof renderText === "function" ? renderText({
theme: selectedTheme,
initializing,
error,
isDownloading,
isURL,
isDownloaded,
autoDownload,
text: textNotDownloaded
}) : /* @__PURE__ */ jsx7(React6.Fragment, { children: !autoDownload && isURL && !isDownloaded && !isDownloading && textNotDownloaded && /* @__PURE__ */ jsx7(
Text3,
{
style: [
styles6.text,
{
color: selectedTheme?.colors?.label,
fontFamily: selectedTheme?.typography?.family
}
],
children: textNotDownloaded
}
) }),
(initializing || error) && !isDownloading ? typeof renderText === "function" ? renderText({
theme: selectedTheme,
initializing,
error,
isDownloading,
isURL,
isDownloaded,
autoDownload,
text: textNotDownloaded
}) : /* @__PURE__ */ jsx7(
Text3,
{
style: [
styles6.text,
{
color: selectedTheme?.colors?.label,
fontFamily: selectedTheme?.typography?.family
}
],
children: initializing ? textLoading : error ? textError : null
}
) : /* @__PURE__ */ jsxs4(React6.Fragment, { children: [
isDownloading && (typeof renderDownloadProgress === "function" ? renderDownloadProgress({
progress: downloadProgress,
theme: selectedTheme
}) : /* @__PURE__ */ jsx7(
DownloadProgressBar_default,
{
theme: selectedTheme,
percentage: downloadProgress
}
)),
!isDownloading && (typeof renderTrack === "function" ? renderTrack({
error,
theme: selectedTheme,
duration,
currentTime,
setCurrentTime,
soundRef: soundRef.current
}) : /* @__PURE__ */ jsx7(
TrackerLine_default,
{
disabled: error,
theme: selectedTheme,
totalValue: duration,
currentValue: currentTime,
thumbColor: isNew ? selectedTheme?.colors?.primary : selectedTheme?.colors?.secondaryLabel,
onValuesChange: async (value) => {
await soundRef.current?.setPositionAsync(value * 1e3);
setCurrentTime(value);
typeof onTrackChange === "function" && onTrackChange(value);
},
onValuesChangeStart: () => {
pauseSound();
if (isPlaying) {
setTempPause(true);
}
typeof onTrackChangeStart === "function" && onTrackChangeStart();
},
onValuesChangeFinish: (value) => {
if (soundRef.current) {
if (value) {
setCurrentTime(value);
}
if (tempPause) {
playSound();
setTempPause(false);
}
if (typeof onTrackChangeComplete === "function" && value) {
onTrackChangeComplete(value);
}
}
}
}
))
] }),
/* @__PURE__ */ jsx7(View5, { style: [styles6.timeContainer, bottomContainerStyle], children: typeof renderBottom === "function" ? renderBottom({
theme: selectedTheme,
timer: timerValue,
timestamp: time
}) : /* @__PURE__ */ jsx7(
TrackerTimers_default,
{
status,
statusSources: bottomStatusSources,
theme: selectedTheme,
timer: timerValue,
timestamp: time,
renderTimer: renderBottomTimer,
renderTimestamp: renderBottomTimestamp
}
) })
] }),
showProfileAvatar && profilePosition === "right" && /* @__PURE__ */ jsx7(
Profiling_default,
{
micSource: profileMicSource,
imageSource: profileImageSource,
theme: selectedTheme,
isPlayed,
onImagePress: onProfileImagePress,
ProfileImagePressDisabled,
renderProfileImage,
renderProfileMic,
profilePosition,
renderProfile
}
)
]
}
);
};
var styles6 = StyleSheet6.create({
container: {
paddingVertical: 8,
paddingHorizontal: 8,
minHeight: 60,
backgroundColor: "#FFF",
marginHorizontal: 16,
justifyContent: "center",
alignItems: "center",
flexDirection: "row"
},
profileContainerStyle: {
position: "relative",
marginHorizontal: 8
},
centerView: {
flex: 1,
flexDirection: "row",
position: "relative",
alignItems: "center",
height: 20,
marginRight: 16
},
sliderContainer: {
flex: 1
},
timeContainer: {
position: "absolute",
left: 0,
right: 0,
bottom: -10
},
text: {
fontSize: 12
}
});
var RNVoiceMessagePlayer = React6.forwardRef(VoicePlayerComponent);
var RNVoiceMessagePlayer_default = RNVoiceMessagePlayer;
// src/index.ts
var index_default = RNVoiceMessagePlayer_default;
export {
TrackerTimers_default as BottomTimesComponent,
DownloadProgressBar_default as DownloadProgressBarComponent,
PlayPauseButton_default as LeftActionComponent,
Avatar_default as ProfileComponent,
TrackerLine_default as TrackerLineComponent,
index_default as default,
theme_default as theme
};