react-peer-chat 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{chunk-6JONVNJK.js → chunk-B2RQAOIC.js} +3 -3
- package/dist/chunks/{chunk-FBLX5IM6.js → chunk-CIIM7EHX.js} +80 -65
- package/dist/chunks/{chunk-LNEKYYG7.js → chunk-FZ4QVG4I.js} +21 -1
- package/dist/chunks/{chunk-JJPIWKLG.js → chunk-QIPTWGEX.js} +1 -1
- package/dist/components.js +4 -4
- package/dist/hooks.js +2 -2
- package/dist/icons.js +2 -2
- package/dist/index.js +4 -4
- package/dist/lib/storage.js +1 -1
- package/dist/types.d.ts +2 -1
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useChat } from './chunk-
|
|
2
|
-
import { BiSolidMessageX, BiSolidMessageDetail, GrSend, BsFillMicFill, BsFillMicMuteFill } from './chunk-
|
|
3
|
-
import { __objRest, __spreadValues } from './chunk-
|
|
1
|
+
import { useChat } from './chunk-CIIM7EHX.js';
|
|
2
|
+
import { BiSolidMessageX, BiSolidMessageDetail, GrSend, BsFillMicFill, BsFillMicMuteFill } from './chunk-QIPTWGEX.js';
|
|
3
|
+
import { __objRest, __spreadValues } from './chunk-FZ4QVG4I.js';
|
|
4
4
|
import React, { useRef, useState, useEffect } from 'react';
|
|
5
5
|
|
|
6
6
|
// src/styles.css
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getStorage, setStorage } from './chunk-ZYFPSCFE.js';
|
|
2
|
-
import { __spreadValues, __spreadProps } from './chunk-
|
|
2
|
+
import { __spreadValues, __async, __spreadProps } from './chunk-FZ4QVG4I.js';
|
|
3
3
|
import { useState, useRef, useMemo, useEffect } from 'react';
|
|
4
4
|
|
|
5
5
|
// src/constants.ts
|
|
@@ -66,6 +66,7 @@ function useChat({
|
|
|
66
66
|
const [audio, setAudio] = useAudio(allowed);
|
|
67
67
|
const connRef = useRef({});
|
|
68
68
|
const callsRef = useRef({});
|
|
69
|
+
const localStreamRef = useRef(null);
|
|
69
70
|
const audioContextRef = useRef(null);
|
|
70
71
|
const mixerRef = useRef(null);
|
|
71
72
|
const sourceNodesRef = useRef({});
|
|
@@ -75,8 +76,53 @@ function useChat({
|
|
|
75
76
|
const remotePeerIds = Array.isArray(remotePeerId) ? remotePeerId : [remotePeerId];
|
|
76
77
|
return { completePeerId: addPrefix(peerId), completeRemotePeerIds: remotePeerIds.map(addPrefix) };
|
|
77
78
|
}, [peerId]);
|
|
79
|
+
function resetConnections(type = "all") {
|
|
80
|
+
switch (type) {
|
|
81
|
+
case "all":
|
|
82
|
+
resetConnections("data");
|
|
83
|
+
resetConnections("call");
|
|
84
|
+
break;
|
|
85
|
+
case "data":
|
|
86
|
+
Object.values(connRef.current).forEach(closeConnection);
|
|
87
|
+
connRef.current = {};
|
|
88
|
+
break;
|
|
89
|
+
case "call":
|
|
90
|
+
Object.values(callsRef.current).forEach(closeConnection);
|
|
91
|
+
Object.keys(sourceNodesRef.current).forEach(removePeerAudio);
|
|
92
|
+
callsRef.current = {};
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function handleConnection(conn) {
|
|
97
|
+
const peerId2 = conn.peer;
|
|
98
|
+
if (connRef.current[peerId2]) return conn.close();
|
|
99
|
+
conn.on("open", () => {
|
|
100
|
+
connRef.current[peerId2] = conn;
|
|
101
|
+
conn.on("data", ({ type, message, messages: messages2, remotePeerName }) => {
|
|
102
|
+
switch (type) {
|
|
103
|
+
case "init":
|
|
104
|
+
setRemotePeers((prev) => __spreadProps(__spreadValues({}, prev), { [peerId2]: remotePeerName }));
|
|
105
|
+
if (recoverChat) setMessages((old) => messages2.length > old.length ? messages2 : old);
|
|
106
|
+
break;
|
|
107
|
+
case "message":
|
|
108
|
+
receiveMessage(message);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
conn.send({ type: "init", remotePeerName: name, messages });
|
|
113
|
+
});
|
|
114
|
+
conn.on("close", () => {
|
|
115
|
+
conn.removeAllListeners();
|
|
116
|
+
delete connRef.current[peerId2];
|
|
117
|
+
});
|
|
118
|
+
}
|
|
78
119
|
function handleCall(call) {
|
|
79
120
|
const peerId2 = call.peer;
|
|
121
|
+
if (callsRef.current[peerId2]) return call.close();
|
|
122
|
+
if (!call.localStream) {
|
|
123
|
+
if (!localStreamRef.current) return call.close();
|
|
124
|
+
call.answer(localStreamRef.current);
|
|
125
|
+
}
|
|
80
126
|
call.on("stream", () => {
|
|
81
127
|
callsRef.current[peerId2] = call;
|
|
82
128
|
if (!audioContextRef.current) audioContextRef.current = new AudioContext();
|
|
@@ -100,31 +146,14 @@ function useChat({
|
|
|
100
146
|
delete callsRef.current[peerId2];
|
|
101
147
|
});
|
|
102
148
|
}
|
|
103
|
-
function handleConnection(conn) {
|
|
104
|
-
connRef.current[conn.peer] = conn;
|
|
105
|
-
conn.on("open", () => {
|
|
106
|
-
conn.on("data", ({ message, messages: messages2, remotePeerName, type }) => {
|
|
107
|
-
if (type === "message") receiveMessage(message);
|
|
108
|
-
else if (type === "init") {
|
|
109
|
-
setRemotePeers((prev) => __spreadProps(__spreadValues({}, prev), { [conn.peer]: remotePeerName }));
|
|
110
|
-
if (recoverChat) setMessages((old) => messages2.length > old.length ? messages2 : old);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
conn.send({ type: "init", remotePeerName: name, messages });
|
|
114
|
-
});
|
|
115
|
-
conn.on("close", conn.removeAllListeners);
|
|
116
|
-
}
|
|
117
|
-
function handleMediaError() {
|
|
118
|
-
setAudio(false);
|
|
119
|
-
onError(new Error("Microphone not accessible!"));
|
|
120
|
-
}
|
|
121
149
|
function receiveMessage(message) {
|
|
122
150
|
addMessage(message);
|
|
123
151
|
onMessageReceived == null ? void 0 : onMessageReceived(message);
|
|
124
152
|
}
|
|
125
153
|
function removePeerAudio(peerId2) {
|
|
126
|
-
|
|
127
|
-
|
|
154
|
+
const source = sourceNodesRef.current[peerId2];
|
|
155
|
+
if (!source) return;
|
|
156
|
+
source.disconnect();
|
|
128
157
|
delete sourceNodesRef.current[peerId2];
|
|
129
158
|
}
|
|
130
159
|
function sendMessage(message) {
|
|
@@ -135,6 +164,7 @@ function useChat({
|
|
|
135
164
|
}
|
|
136
165
|
useEffect(() => {
|
|
137
166
|
if (!text && !audio) return;
|
|
167
|
+
let destroyed = false;
|
|
138
168
|
import('peerjs').then(
|
|
139
169
|
({
|
|
140
170
|
Peer,
|
|
@@ -145,20 +175,26 @@ function useChat({
|
|
|
145
175
|
if (!data || !audioVideo) return onError(new Error("Browser not supported! Try some other browser."));
|
|
146
176
|
const peer2 = new Peer(completePeerId, __spreadValues({ config: defaultConfig }, peerOptions));
|
|
147
177
|
peer2.on("connection", handleConnection);
|
|
148
|
-
peer2.on("
|
|
178
|
+
peer2.on("call", handleCall);
|
|
179
|
+
peer2.on("disconnected", () => {
|
|
180
|
+
resetConnections();
|
|
181
|
+
peer2.reconnect();
|
|
182
|
+
});
|
|
149
183
|
peer2.on("error", (error) => {
|
|
150
184
|
if (error.type === "network" || error.type === "server-error") {
|
|
185
|
+
resetConnections();
|
|
151
186
|
setTimeout(() => peer2.reconnect(), 1e3);
|
|
152
187
|
onNetworkError == null ? void 0 : onNetworkError(error);
|
|
153
188
|
}
|
|
154
189
|
onPeerError(error);
|
|
155
190
|
});
|
|
156
|
-
|
|
191
|
+
if (destroyed) peer2.destroy();
|
|
192
|
+
else setPeer(peer2);
|
|
157
193
|
}
|
|
158
194
|
);
|
|
159
195
|
return () => {
|
|
196
|
+
destroyed = true;
|
|
160
197
|
setPeer((prev) => {
|
|
161
|
-
prev == null ? void 0 : prev.removeAllListeners();
|
|
162
198
|
prev == null ? void 0 : prev.destroy();
|
|
163
199
|
return void 0;
|
|
164
200
|
});
|
|
@@ -166,52 +202,34 @@ function useChat({
|
|
|
166
202
|
}, [completePeerId]);
|
|
167
203
|
useEffect(() => {
|
|
168
204
|
if (!text || !peer) return;
|
|
169
|
-
const
|
|
170
|
-
if (peer.open)
|
|
171
|
-
peer.on("open",
|
|
205
|
+
const connectData = () => completeRemotePeerIds.forEach((id) => handleConnection(peer.connect(id)));
|
|
206
|
+
if (peer.open) connectData();
|
|
207
|
+
peer.on("open", connectData);
|
|
172
208
|
return () => {
|
|
173
|
-
peer.off("open",
|
|
174
|
-
|
|
175
|
-
connRef.current = {};
|
|
209
|
+
peer.off("open", connectData);
|
|
210
|
+
resetConnections("data");
|
|
176
211
|
};
|
|
177
212
|
}, [text, peer]);
|
|
178
213
|
useEffect(() => {
|
|
179
214
|
if (!audio || !peer) return;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
}).then((stream) => {
|
|
191
|
-
localStream = stream;
|
|
192
|
-
completeRemotePeerIds.forEach((id) => {
|
|
193
|
-
if (callsRef.current[id]) return;
|
|
194
|
-
const call = peer.call(id, stream);
|
|
195
|
-
handleCall(call);
|
|
196
|
-
});
|
|
197
|
-
peer.on("call", (call) => {
|
|
198
|
-
if (callsRef.current[call.peer]) return call.close();
|
|
199
|
-
call.answer(stream);
|
|
200
|
-
handleCall(call);
|
|
201
|
-
});
|
|
202
|
-
}).catch(handleMediaError);
|
|
203
|
-
};
|
|
215
|
+
const setupAudio = () => __async(null, null, function* () {
|
|
216
|
+
try {
|
|
217
|
+
localStreamRef.current = yield navigator.mediaDevices.getUserMedia({ video: false, audio: { autoGainControl: true, noiseSuppression: true, echoCancellation: true } });
|
|
218
|
+
completeRemotePeerIds.forEach((id) => localStreamRef.current && handleCall(peer.call(id, localStreamRef.current)));
|
|
219
|
+
} catch (e) {
|
|
220
|
+
setAudio(false);
|
|
221
|
+
onError(new Error("Microphone not accessible"));
|
|
222
|
+
}
|
|
223
|
+
});
|
|
204
224
|
if (peer.open) setupAudio();
|
|
205
225
|
peer.on("open", setupAudio);
|
|
206
226
|
return () => {
|
|
207
|
-
var _a;
|
|
227
|
+
var _a, _b;
|
|
208
228
|
peer.off("open", setupAudio);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
Object.keys(sourceNodesRef.current).forEach(removePeerAudio);
|
|
214
|
-
(_a = audioContextRef.current) == null ? void 0 : _a.close();
|
|
229
|
+
(_a = localStreamRef.current) == null ? void 0 : _a.getTracks().forEach((track) => track.stop());
|
|
230
|
+
resetConnections("call");
|
|
231
|
+
(_b = audioContextRef.current) == null ? void 0 : _b.close();
|
|
232
|
+
localStreamRef.current = null;
|
|
215
233
|
audioContextRef.current = null;
|
|
216
234
|
mixerRef.current = null;
|
|
217
235
|
};
|
|
@@ -224,10 +242,7 @@ function useMessages() {
|
|
|
224
242
|
return [messages, setMessages, addMessage];
|
|
225
243
|
}
|
|
226
244
|
function useStorage(key, initialValue, local = false) {
|
|
227
|
-
const [storedValue, setStoredValue] = useState(() =>
|
|
228
|
-
if (typeof window === "undefined") return initialValue;
|
|
229
|
-
return getStorage(key, initialValue, local);
|
|
230
|
-
});
|
|
245
|
+
const [storedValue, setStoredValue] = useState(() => typeof window === "undefined" ? initialValue : getStorage(key, initialValue, local));
|
|
231
246
|
const setValue = (value) => {
|
|
232
247
|
setStoredValue((prev) => {
|
|
233
248
|
const next = isSetStateFunction(value) ? value(prev) : value;
|
|
@@ -29,5 +29,25 @@ var __objRest = (source, exclude) => {
|
|
|
29
29
|
}
|
|
30
30
|
return target;
|
|
31
31
|
};
|
|
32
|
+
var __async = (__this, __arguments, generator) => {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
var fulfilled = (value) => {
|
|
35
|
+
try {
|
|
36
|
+
step(generator.next(value));
|
|
37
|
+
} catch (e) {
|
|
38
|
+
reject(e);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
var rejected = (value) => {
|
|
42
|
+
try {
|
|
43
|
+
step(generator.throw(value));
|
|
44
|
+
} catch (e) {
|
|
45
|
+
reject(e);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
49
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
50
|
+
});
|
|
51
|
+
};
|
|
32
52
|
|
|
33
|
-
export { __objRest, __spreadProps, __spreadValues };
|
|
53
|
+
export { __async, __objRest, __spreadProps, __spreadValues };
|
package/dist/components.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Chat as default } from './chunks/chunk-
|
|
2
|
-
import './chunks/chunk-
|
|
3
|
-
import './chunks/chunk-
|
|
1
|
+
export { Chat as default } from './chunks/chunk-B2RQAOIC.js';
|
|
2
|
+
import './chunks/chunk-CIIM7EHX.js';
|
|
3
|
+
import './chunks/chunk-QIPTWGEX.js';
|
|
4
4
|
import './chunks/chunk-ZYFPSCFE.js';
|
|
5
|
-
import './chunks/chunk-
|
|
5
|
+
import './chunks/chunk-FZ4QVG4I.js';
|
package/dist/hooks.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { useAudio, useChat, useMessages, useStorage } from './chunks/chunk-
|
|
1
|
+
export { useAudio, useChat, useMessages, useStorage } from './chunks/chunk-CIIM7EHX.js';
|
|
2
2
|
import './chunks/chunk-ZYFPSCFE.js';
|
|
3
|
-
import './chunks/chunk-
|
|
3
|
+
import './chunks/chunk-FZ4QVG4I.js';
|
package/dist/icons.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { BiSolidMessageDetail, BiSolidMessageX, BsFillMicFill, BsFillMicMuteFill, GrSend } from './chunks/chunk-
|
|
2
|
-
import './chunks/chunk-
|
|
1
|
+
export { BiSolidMessageDetail, BiSolidMessageX, BsFillMicFill, BsFillMicMuteFill, GrSend } from './chunks/chunk-QIPTWGEX.js';
|
|
2
|
+
import './chunks/chunk-FZ4QVG4I.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Chat as default } from './chunks/chunk-
|
|
2
|
-
export { useChat } from './chunks/chunk-
|
|
3
|
-
import './chunks/chunk-
|
|
1
|
+
export { Chat as default } from './chunks/chunk-B2RQAOIC.js';
|
|
2
|
+
export { useChat } from './chunks/chunk-CIIM7EHX.js';
|
|
3
|
+
import './chunks/chunk-QIPTWGEX.js';
|
|
4
4
|
export { clearChat } from './chunks/chunk-ZYFPSCFE.js';
|
|
5
|
-
import './chunks/chunk-
|
|
5
|
+
import './chunks/chunk-FZ4QVG4I.js';
|
package/dist/lib/storage.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { clearChat, getStorage, removeStorage, setStorage } from '../chunks/chunk-ZYFPSCFE.js';
|
|
2
|
-
import '../chunks/chunk-
|
|
2
|
+
import '../chunks/chunk-FZ4QVG4I.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ type MessageEventHandler = (message: Message) => void;
|
|
|
15
15
|
type PeerErrorHandler = ErrorHandler<PeerError<`${PeerErrorType}`>>;
|
|
16
16
|
|
|
17
17
|
type RemotePeerId = string | string[];
|
|
18
|
+
type ResetConnectionType = "all" | "data" | "call";
|
|
18
19
|
type UseChatProps = {
|
|
19
20
|
peerId: string;
|
|
20
21
|
name?: string;
|
|
@@ -54,4 +55,4 @@ type DialogPosition = "left" | "center" | "right";
|
|
|
54
55
|
type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
|
|
55
56
|
type RemotePeers = Record<string, string>;
|
|
56
57
|
|
|
57
|
-
export type { ChatProps, Children, ChildrenOptions, Connection, DialogOptions, DialogPosition, DivProps, ErrorHandler, IconProps, InputMessage, Message, MessageEventHandler, PeerErrorHandler, RemotePeerId, RemotePeers, UseChatProps, UseChatReturn };
|
|
58
|
+
export type { ChatProps, Children, ChildrenOptions, Connection, DialogOptions, DialogPosition, DivProps, ErrorHandler, IconProps, InputMessage, Message, MessageEventHandler, PeerErrorHandler, RemotePeerId, RemotePeers, ResetConnectionType, UseChatProps, UseChatReturn };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-peer-chat",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "An easy to use react component for impleting peer-to-peer chatting.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sahil Aggarwal <aggarwalsahil2004@gmail.com>",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@release-it/conventional-changelog": "^10.0.4",
|
|
39
|
-
"@types/react": "^19.2.
|
|
39
|
+
"@types/react": "^19.2.8",
|
|
40
40
|
"prettier-package-json": "^2.8.0",
|
|
41
|
-
"release-it": "^19.2.
|
|
41
|
+
"release-it": "^19.2.3",
|
|
42
42
|
"tsup": "^8.5.1",
|
|
43
43
|
"typescript": "^5.9.3"
|
|
44
44
|
},
|