softchatjs-react-native
Version:
React native UI SDK for softchatjs-core. Create a free account at: https://www.softchatjs.com
377 lines (366 loc) • 11.3 kB
JavaScript
// src/components/Chat/ChatItem/Media/VoiceMessage.tsx
import { View as View3, Text as Text2, TouchableOpacity, ActivityIndicator } from "react-native";
import React5, { useCallback, useMemo } from "react";
// src/assets/icons.tsx
import React from "react";
import { View } from "react-native";
import { Svg, Path, G, Defs, ClipPath, Rect } from "react-native-svg";
var PauseIcon = (props) => {
const { size = 25, color = "black" } = props;
return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React.createElement(
Path,
{
"fill-rule": "evenodd",
"clip-rule": "evenodd",
d: "M8 5C7.46957 5 6.96086 5.21071 6.58579 5.58579C6.21071 5.96086 6 6.46957 6 7V17C6 17.5304 6.21071 18.0391 6.58579 18.4142C6.96086 18.7893 7.46957 19 8 19H9C9.53043 19 10.0391 18.7893 10.4142 18.4142C10.7893 18.0391 11 17.5304 11 17V7C11 6.46957 10.7893 5.96086 10.4142 5.58579C10.0391 5.21071 9.53043 5 9 5H8ZM15 5C14.4696 5 13.9609 5.21071 13.5858 5.58579C13.2107 5.96086 13 6.46957 13 7V17C13 17.5304 13.2107 18.0391 13.5858 18.4142C13.9609 18.7893 14.4696 19 15 19H16C16.5304 19 17.0391 18.7893 17.4142 18.4142C17.7893 18.0391 18 17.5304 18 17V7C18 6.46957 17.7893 5.96086 17.4142 5.58579C17.0391 5.21071 16.5304 5 16 5H15Z",
fill: color
}
));
};
var PlayIcon = (props) => {
const { size = 25, color = "black" } = props;
return /* @__PURE__ */ React.createElement(Svg, { width: size, height: size, viewBox: "0 0 256 256", fill: "none" }, /* @__PURE__ */ React.createElement(
Path,
{
d: "M240 128C240.007 130.716 239.31 133.388 237.978 135.756C236.647 138.123 234.725 140.105 232.4 141.51L88.32 229.65C85.8909 231.138 83.1087 231.95 80.2608 232.002C77.4129 232.055 74.6025 231.347 72.12 229.95C69.6611 228.575 67.6128 226.57 66.1856 224.141C64.7585 221.712 64.0041 218.947 64 216.13V39.8701C64.0041 37.053 64.7585 34.2877 66.1856 31.8588C67.6128 29.4299 69.6611 27.4249 72.12 26.0501C74.6025 24.6536 77.4129 23.9451 80.2608 23.9979C83.1087 24.0506 85.8909 24.8626 88.32 26.3501L232.4 114.49C234.725 115.895 236.647 117.877 237.978 120.245C239.31 122.612 240.007 125.284 240 128Z",
fill: color
}
));
};
// src/utils/index.ts
import moment from "moment";
import { MessageStates } from "softchatjs-core";
function convertToMinutes(seconds) {
var _seconds = Number(seconds.toFixed(0));
const minutes = Math.floor(_seconds / 60);
const remainingSeconds = _seconds % 60;
const paddedMinutes = String(minutes).padStart(2, "0");
const paddedSeconds = String(remainingSeconds).padStart(2, "0");
return `${paddedMinutes}:${paddedSeconds}`;
}
// src/contexts/ChatProvider.tsx
import React4, { createContext as createContext3, useContext as useContext3 } from "react";
// src/contexts/ModalProvider.tsx
import React2, { createContext, useContext, useState } from "react";
import {
Modal,
View as View2
} from "react-native";
var initial = {
displayModal: () => {
},
resetModal: () => {
},
modalProps: {
dismissable: true,
justifyContent: "center",
children: null,
animation: "slide",
containerWidth: "100%"
}
};
var ModalProviderContext = createContext(initial);
// src/theme/colors.ts
var teal = {
50: "#DCF2F0",
100: "#A9DFD8",
200: "#73CABE",
300: "#3AB4A4",
400: "#00A391",
500: "#00927E",
600: "#008572",
700: "#007662",
800: "#006654",
900: "#004A38"
};
var green = {
50: "#E6F5E4",
100: "#C2E6BD",
200: "#9AD693",
300: "#6FC666",
400: "#4ABA42",
500: "#17AE13",
600: "#029F04",
700: "#008D00",
800: "#007C00",
900: "#005E00"
};
var grey = {
50: "#F6F6FF",
100: "#F2F1FF",
200: "#EBEBF9",
300: "#CAC9D7",
400: "#ACACB9",
500: "#82818F",
600: "#6D6D7A",
700: "#4D4D59",
800: "#2B2B36",
900: "#21222D",
A100: "#1D1E26"
};
var stone = {
50: "#F8F8F8",
100: "#EFEFEF",
200: "#E8E8E8",
300: "#D9D9D9",
400: "#D2D2D2",
500: "#A0A0A0",
600: "#87888C",
700: "#2C2D33",
800: "#1D1E26",
900: "#171821"
};
// src/theme/index.ts
var theme = {
background: {
primary: stone[900],
secondary: grey[900],
disabled: grey[800]
},
text: {
primary: "black",
secondary: stone[200],
disabled: stone[500]
},
action: {
primary: teal[50],
secondary: stone[300]
},
chatBubble: {
left: {
bgColor: grey[900],
messageColor: stone[200],
messageTimeColor: "grey",
replyBorderColor: stone[200]
},
right: {
bgColor: "#474952",
messageColor: "white",
messageTimeColor: "grey",
replyBorderColor: green[900]
}
},
icon: "white",
divider: stone[700]
};
var theme_default = theme;
// src/contexts/MessageStateContext.tsx
import React3, {
createContext as createContext2,
useState as useState2,
useContext as useContext2
} from "react";
import { Audio } from "expo-av";
// src/constants/defaultUser.ts
var defaultUser_default = {
id: "",
uid: "",
username: "",
firstname: "",
lastname: "",
profileUrl: "",
color: "",
custom: {}
};
// src/contexts/MessageStateContext.tsx
var initialMessageStateContext = {
globalTextMessage: "",
setGlobalTextMessage: () => {
},
stickers: [],
setStickers: () => {
},
pendingMessages: [],
addNewPendingMessages: (message) => {
},
removePendingMessage: (messageId) => {
},
updatePendingMessage: (messageId, message) => {
},
playVoiceMessage: (media) => {
},
pauseVoiceMessage: () => {
},
resumeVoiceMessage: () => {
},
audioState: null,
unload: () => {
},
sound: null,
activeVoiceMessage: null,
avPlayBackStatus: null,
userMeta: defaultUser_default,
setUserMeta: () => {
},
conversationList: [],
setConversationList: () => {
}
};
var MessageStateContext = createContext2(
initialMessageStateContext
);
var useMessageState = () => useContext2(MessageStateContext);
// src/contexts/ChatProvider.tsx
var ConfigContext = createContext3({
theme: theme_default,
client: null,
fontFamily: void 0,
fontScale: 1
});
function useConfig() {
return useContext3(ConfigContext);
}
// src/components/Chat/ChatItem/Media/VoiceMessage.tsx
var AudioWaves = ({
type = "record",
audioTime,
audioWaves
}) => {
const { theme: theme2, fontFamily } = useConfig();
const waves = Object.values(audioWaves).flat();
return /* @__PURE__ */ React5.createElement(
View3,
{
style: {
flex: 1,
marginHorizontal: 5,
borderWidth: type === "record" ? 1 : 0,
overflow: "hidden",
borderColor: theme2?.divider,
borderRadius: 100,
paddingHorizontal: 10,
height: 35,
flexDirection: "row",
alignItems: "center"
}
},
/* @__PURE__ */ React5.createElement(
Text2,
{
style: {
color: type === "play" ? theme2?.text.primary : "white",
fontSize: 12,
fontFamily,
marginEnd: 5
}
},
convertToMinutes(Number(audioTime.toFixed(0)))
),
/* @__PURE__ */ React5.createElement(
View3,
{
style: {
flex: 1,
flexDirection: "row",
alignItems: "center",
height: "100%",
justifyContent: type === "play" ? "flex-start" : "flex-end",
overflow: "hidden",
paddingHorizontal: 0
}
},
waves.map((wave, i) => /* @__PURE__ */ React5.createElement(
View3,
{
key: i,
style: {
width: 2,
backgroundColor: theme2?.icon,
height: `${wave.height}%`,
marginEnd: 2,
borderRadius: 1
}
}
))
)
);
};
function VoiceMessage(props) {
const { media, textColor = theme_default.text.primary } = props;
const { fontFamily } = useConfig();
const {
audioState,
playVoiceMessage,
pauseVoiceMessage,
resumeVoiceMessage,
activeVoiceMessage,
avPlayBackStatus
} = useMessageState();
const renderVoiceMessageControls = useCallback(() => {
var isActiveVoiceMessage = media.mediaId === activeVoiceMessage?.mediaId;
if (isActiveVoiceMessage && audioState === "loading") {
return /* @__PURE__ */ React5.createElement(ActivityIndicator, { size: 25 });
} else if (isActiveVoiceMessage && audioState === null) {
return /* @__PURE__ */ React5.createElement(TouchableOpacity, { onPress: () => playVoiceMessage(media) }, /* @__PURE__ */ React5.createElement(PlayIcon, { color: theme_default?.icon }));
} else if (isActiveVoiceMessage && audioState === "playing") {
return /* @__PURE__ */ React5.createElement(TouchableOpacity, { onPress: pauseVoiceMessage }, /* @__PURE__ */ React5.createElement(PauseIcon, { color: theme_default?.icon }));
} else if (isActiveVoiceMessage && audioState === "paused") {
return /* @__PURE__ */ React5.createElement(TouchableOpacity, { onPress: resumeVoiceMessage }, /* @__PURE__ */ React5.createElement(PlayIcon, { color: theme_default?.icon }));
} else {
return /* @__PURE__ */ React5.createElement(TouchableOpacity, { onPress: () => playVoiceMessage(media) }, /* @__PURE__ */ React5.createElement(PlayIcon, { color: theme_default?.icon }));
}
}, [media, activeVoiceMessage, audioState]);
var progress = useMemo(() => {
try {
var isActiveVoiceMessage = media.mediaId === activeVoiceMessage?.mediaId;
if (isActiveVoiceMessage) {
if (audioState === null || audioState === "loading") {
return {
percentage: 0,
timePlayed: media?.meta?.audioDurationSec ?? 0 / 1e3
};
}
var curr = avPlayBackStatus?.positionMillis / 1e3;
var duration = media?.meta?.audioDurationSec ?? 0 / 1e3;
var percentage = curr / duration * 100;
return { percentage, timePlayed: curr };
}
return { percentage: 0, timePlayed: media.meta?.audioDurationSec ?? 0 };
} catch (error) {
return { percentage: 0, timePlayed: media.meta?.audioDurationSec ?? 0 };
}
}, [media, avPlayBackStatus, audioState]);
return /* @__PURE__ */ React5.createElement(
View3,
{
style: {
flexDirection: "row",
alignItems: "center",
width: "100%",
minWidth: 50,
backgroundColor: theme_default.background.disabled,
padding: 10,
borderRadius: 25
// backgroundColor: 'red'
}
},
/* @__PURE__ */ React5.createElement(React5.Fragment, null, renderVoiceMessageControls()),
/* @__PURE__ */ React5.createElement(
View3,
{
style: {
flex: 1,
backgroundColor: theme_default?.divider,
marginHorizontal: 10
}
},
/* @__PURE__ */ React5.createElement(
View3,
{
style: {
width: `${progress.percentage}%`,
maxWidth: "100%",
height: 3,
backgroundColor: theme_default?.icon
}
}
)
),
/* @__PURE__ */ React5.createElement(Text2, { style: { marginStart: 5, color: textColor, fontFamily } }, convertToMinutes(progress.timePlayed))
);
}
export {
AudioWaves,
VoiceMessage as default
};
//# sourceMappingURL=VoiceMessage.mjs.map