Skip to content

Commit 663d869

Browse files
committed
code improvements
1 parent fd3777c commit 663d869

3 files changed

Lines changed: 56 additions & 70 deletions

File tree

‎App.tsx‎

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import {
1212
import { fetchCallCredentials, joinCall } from "./src/join";
1313
import { GestureHandlerRootView } from "react-native-gesture-handler";
1414
import { AudioVisualizer } from "./src/AudioVisualizer";
15+
import inCallManager from "react-native-incall-manager";
1516

1617
const credentialsPromise = fetchCallCredentials();
1718

18-
function App(): React.JSX.Element {
19+
function App() {
1920
const [client, setClient] = useState<StreamVideoClient | null>(null);
2021
const [call, setCall] = useState<Call | null>(null);
2122
const [status, setStatus] = useState<
@@ -30,6 +31,7 @@ function App(): React.JSX.Element {
3031
setClient(client);
3132
setCall(call);
3233
setStatus("joined-with-agent");
34+
inCallManager.setSpeakerphoneOn(true);
3335
})
3436
.catch((err: any) => {
3537
console.error("Could not join call", err);
@@ -80,24 +82,14 @@ function CallLayout(props: {
8082
onLeave?: () => void;
8183
}) {
8284
const call = useCall();
83-
const { useParticipants } = useCallStateHooks();
84-
const participants = useParticipants();
85-
const agentParticipant =
86-
participants.find((p) => p.userId === "lucy") ?? null;
87-
const humanParticipant =
88-
participants.find((p) => p.userId !== "lucy") ?? null;
89-
const audioLevel = agentParticipant?.isDominantSpeaker
90-
? agentParticipant?.audioLevel
91-
: humanParticipant?.audioLevel;
92-
85+
const { useDominantSpeaker } = useCallStateHooks();
86+
const dominantSpeaker = useDominantSpeaker();
9387
return (
9488
<>
95-
{agentParticipant && (
96-
<AudioVisualizer
97-
colorScheme={agentParticipant.isDominantSpeaker ? "blue" : "red"}
98-
audioLevel={audioLevel || 0}
99-
/>
100-
)}
89+
<AudioVisualizer
90+
colorScheme={dominantSpeaker?.isLocalParticipant ? "red" : "blue"}
91+
audioLevel={dominantSpeaker?.audioLevel || 0}
92+
/>
10193
<View style={styles.callControls}>
10294
<HangUpCallButton
10395
onPressHandler={() => {

‎src/AudioVisualizer.tsx‎

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import React, {useEffect, useRef} from 'react';
2-
import {StyleSheet, View, Animated, Easing} from 'react-native';
3-
import Svg, {Path, Defs, RadialGradient, Stop} from 'react-native-svg';
4-
import {PathProps} from 'react-native-svg';
1+
import React, { useEffect, useRef } from "react";
2+
import { StyleSheet, View, Animated, Easing } from "react-native";
3+
import Svg, {
4+
Path,
5+
PathProps,
6+
Defs,
7+
RadialGradient,
8+
Stop,
9+
} from "react-native-svg";
510

611
interface AudioVisualizerProps {
7-
colorScheme?: 'blue' | 'red';
12+
colorScheme?: "blue" | "red";
813
audioLevel: number;
914
}
1015

@@ -14,7 +19,7 @@ const normalizeAudioLevel = (
1419
level: number,
1520
minInput = 0,
1621
maxInput = 1.5,
17-
randomFactor = 15,
22+
randomFactor = 15
1823
): number => {
1924
const clampedLevel = Math.max(minInput, Math.min(maxInput, level));
2025
const factor = 150;
@@ -37,7 +42,7 @@ const normalizeAudioLevel = (
3742
};
3843

3944
export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
40-
colorScheme = 'blue',
45+
colorScheme = "blue",
4146
audioLevel = 0,
4247
}) => {
4348
const normalizedAudioLevel = normalizeAudioLevel(audioLevel);
@@ -55,7 +60,7 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
5560
const generateIntermediateValues = (
5661
start: number,
5762
end: number,
58-
steps: number,
63+
steps: number
5964
) => {
6065
const result = [];
6166
for (let i = 1; i <= steps; i++) {
@@ -79,7 +84,7 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
7984
duration: 1000,
8085
useNativeDriver: false,
8186
}),
82-
]),
87+
])
8388
).start();
8489
};
8590

@@ -98,17 +103,17 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
98103
const intermediateValues = generateIntermediateValues(
99104
prevAudioLevelRef.current,
100105
normalizedAudioLevel,
101-
steps,
106+
steps
102107
);
103108

104109
// Create a sequence of animations through intermediate values
105-
const animations = intermediateValues.map(value =>
110+
const animations = intermediateValues.map((value) =>
106111
Animated.timing(audioLevelAnim, {
107112
toValue: value,
108113
duration: 30, // Short duration for each step
109114
useNativeDriver: false,
110115
easing: Easing.bezier(0.25, 0.1, 0.25, 1), // Smooth cubic bezier curve
111-
}),
116+
})
112117
);
113118

114119
// Run the sequence
@@ -134,36 +139,36 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
134139
const animation = combinedAnimation.interpolate({
135140
inputRange: [0, 25, 50, 75, 100], // More interpolation points
136141
outputRange: [0.3, 0.5, 0.7, 0.85, 1], // More gradual scaling
137-
extrapolate: 'clamp',
142+
extrapolate: "clamp",
138143
});
139144

140145
const blueGradient = {
141-
center: '#ffffff',
142-
middle: '#40ffff',
143-
outer: '#0099ff',
144-
edge: '#0066cc',
146+
center: "#ffffff",
147+
middle: "#40ffff",
148+
outer: "#0099ff",
149+
edge: "#0066cc",
145150
};
146151

147152
const redGradient = {
148-
center: '#ffffff',
149-
middle: '#ff4040',
150-
outer: '#ff0000',
151-
edge: '#cc0000',
153+
center: "#ffffff",
154+
middle: "#ff4040",
155+
outer: "#ff0000",
156+
edge: "#cc0000",
152157
};
153158

154-
const colors = colorScheme === 'blue' ? blueGradient : redGradient;
159+
const colors = colorScheme === "blue" ? blueGradient : redGradient;
155160

156161
const AnimatedPath = Animated.createAnimatedComponent(Path);
157162

158163
const animatedProps: AnimatedPathProps = {
159-
fill: 'url(#grad)',
164+
fill: "url(#grad)",
160165
d: animation.interpolate({
161166
inputRange: [0, 1],
162167
outputRange: [
163168
// Base state - larger starting size
164-
'M 200 140 C 250 140, 260 140, 260 200 C 260 260, 250 260, 200 260 C 150 260, 140 260, 140 200 C 140 140, 150 140, 200 140',
169+
"M 200 140 C 250 140, 260 140, 260 200 C 260 260, 250 260, 200 260 C 150 260, 140 260, 140 200 C 140 140, 150 140, 200 140",
165170
// Expanded state - even larger maximum size
166-
'M 200 80 C 290 80, 320 80, 320 200 C 320 320, 290 320, 200 320 C 110 320, 80 320, 80 200 C 80 80, 110 80, 200 80',
171+
"M 200 80 C 290 80, 320 80, 320 200 C 320 320, 290 320, 200 320 C 110 320, 80 320, 80 200 C 80 80, 110 80, 200 80",
167172
],
168173
}),
169174
};
@@ -180,7 +185,8 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
180185
rx="50%"
181186
ry="50%"
182187
fx="50%"
183-
fy="50%">
188+
fy="50%"
189+
>
184190
<Stop offset="0%" stopColor={colors.center} stopOpacity="1" />
185191
<Stop offset="20%" stopColor={colors.middle} stopOpacity="0.9" />
186192
<Stop offset="50%" stopColor={colors.outer} stopOpacity="0.7" />
@@ -197,14 +203,14 @@ export const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
197203
const styles = StyleSheet.create({
198204
container: {
199205
flex: 1,
200-
backgroundColor: 'black',
201-
justifyContent: 'center',
202-
alignItems: 'center',
206+
backgroundColor: "black",
207+
justifyContent: "center",
208+
alignItems: "center",
203209
},
204210
blobContainer: {
205211
width: 500,
206212
height: 500,
207-
justifyContent: 'center',
208-
alignItems: 'center',
213+
justifyContent: "center",
214+
alignItems: "center",
209215
},
210216
});

‎src/join.ts‎

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,35 @@ import { Call, StreamVideoClient } from "@stream-io/video-react-native-sdk";
33
interface CallCredentials {
44
apiKey: string;
55
token: string;
6+
callType: string;
7+
callId: string;
68
userId: string;
7-
cid: string;
89
}
910

10-
const baseUrl = "your localhost url here";
11+
const baseUrl = "http://localhost:3000";
1112

12-
export async function fetchCallCredentials() {
13+
export async function fetchCallCredentials(): Promise<CallCredentials> {
1314
const res = await fetch(`${baseUrl}/credentials`);
1415

1516
if (res.status !== 200) {
1617
throw new Error("Could not fetch call credentials");
1718
}
1819

19-
const credentials = await res.json();
20-
21-
return {
22-
apiKey: credentials.apiKey,
23-
token: credentials.token,
24-
userId: parseUserIdFromToken(credentials.token),
25-
cid: credentials.cid,
26-
};
20+
return (await res.json()) as CallCredentials;
2721
}
2822

2923
export async function joinCall(
3024
credentials: CallCredentials
3125
): Promise<[client: StreamVideoClient, call: Call]> {
26+
console.log("🚀 ~ credentials:", credentials);
3227
const client = new StreamVideoClient({
3328
apiKey: credentials.apiKey,
3429
user: { id: credentials.userId },
3530
token: credentials.token,
3631
});
37-
const [callType, callId] = credentials.cid.split(":");
38-
const call = client.call(callType, callId);
32+
33+
const call = client.call(credentials.callType, credentials.callId);
34+
await call.camera.disable();
3935

4036
try {
4137
await Promise.all([connectAgent(call), call.join({ create: true })]);
@@ -49,19 +45,11 @@ export async function joinCall(
4945
}
5046

5147
async function connectAgent(call: Call) {
52-
const res = await fetch(`${baseUrl}/${call.cid}/connect`, {
48+
const res = await fetch(`${baseUrl}/${call.type}/${call.id}/connect`, {
5349
method: "POST",
5450
});
5551

5652
if (res.status !== 200) {
5753
throw new Error("Could not connect agent");
5854
}
5955
}
60-
61-
function parseUserIdFromToken(token: string) {
62-
const payload = token.split(".")[1];
63-
if (!payload) {
64-
return "";
65-
}
66-
return JSON.parse(atob(payload)).user_id ?? "";
67-
}

0 commit comments

Comments
 (0)