@ermis-network/ermis-chat-sdk 1.0.2 → 1.0.4
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/bin/init-call.js +52 -0
- package/dist/index.browser.cjs +284 -92
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.full-bundle.min.js +15 -15
- package/dist/index.browser.full-bundle.min.js.map +1 -1
- package/dist/index.browser.mjs +283 -92
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.cjs +284 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +199 -7
- package/dist/index.d.ts +199 -7
- package/dist/index.mjs +283 -92
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -2
- package/public/call_incoming.mp3 +0 -0
- package/public/call_outgoing.mp3 +0 -0
- package/public/ermis_call_node_wasm_bg.wasm +0 -0
- package/src/channel.ts +42 -0
- package/src/channel_state.ts +27 -0
- package/src/client.ts +104 -0
- package/src/ermis_call_node.ts +77 -47
- package/src/index.ts +2 -1
- package/src/signal_message.ts +121 -71
package/src/signal_message.ts
CHANGED
|
@@ -1,96 +1,146 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Call type constants for signal messages.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
export const CallType = {
|
|
5
|
+
AUDIO: 'audio',
|
|
6
|
+
VIDEO: 'video',
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export type CallTypeValue = (typeof CallType)[keyof typeof CallType];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Result of parsing a signal message.
|
|
13
|
+
*/
|
|
14
|
+
export interface SignalMessageResult {
|
|
15
|
+
text: string;
|
|
16
|
+
duration: string;
|
|
17
|
+
callType: CallTypeValue | '';
|
|
18
|
+
color: string;
|
|
10
19
|
}
|
|
11
20
|
|
|
12
21
|
/**
|
|
13
|
-
*
|
|
14
|
-
* Falls back to the raw userId if no entry is found.
|
|
22
|
+
* Format duration from milliseconds to "X min, Y sec" format.
|
|
15
23
|
*/
|
|
16
|
-
function
|
|
17
|
-
|
|
24
|
+
function formatDuration(durationMs: string): string {
|
|
25
|
+
if (!durationMs) return '';
|
|
26
|
+
const ms = parseInt(durationMs, 10);
|
|
27
|
+
if (isNaN(ms) || ms <= 0) return '';
|
|
28
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
29
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
30
|
+
const seconds = totalSeconds % 60;
|
|
31
|
+
return `${minutes} min, ${seconds} sec`;
|
|
18
32
|
}
|
|
19
33
|
|
|
20
34
|
/**
|
|
21
|
-
* Parse a raw signal message string into a
|
|
35
|
+
* Parse a raw signal message string into a structured object
|
|
36
|
+
* containing text, duration, call type, and color.
|
|
22
37
|
*
|
|
23
38
|
* Signal messages represent call events. The raw format is:
|
|
24
|
-
* `"<formatId> <
|
|
39
|
+
* `"<formatId> <callerId> [<enderId> <duration>]"`
|
|
25
40
|
*
|
|
26
|
-
* @param value
|
|
27
|
-
* @param
|
|
28
|
-
* @returns
|
|
41
|
+
* @param value - Raw signal message string from the server
|
|
42
|
+
* @param myUserId - The current user's ID (from client.userID)
|
|
43
|
+
* @returns Parsed signal message object, or null if input is empty
|
|
29
44
|
*/
|
|
30
45
|
export function parseSignalMessage(
|
|
31
46
|
value: string,
|
|
32
|
-
|
|
33
|
-
):
|
|
34
|
-
if (!value || typeof value !== 'string') return
|
|
47
|
+
myUserId: string,
|
|
48
|
+
): SignalMessageResult | null {
|
|
49
|
+
if (!value || typeof value !== 'string') return null;
|
|
35
50
|
|
|
36
51
|
const trimmed = value.trim();
|
|
37
|
-
if (!trimmed) return
|
|
52
|
+
if (!trimmed) return null;
|
|
38
53
|
|
|
39
54
|
const parts = trimmed.split(' ');
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
switch (formatId) {
|
|
45
|
-
// 1: Audio call started
|
|
46
|
-
case '1':
|
|
47
|
-
return `📞 ${userName} started an audio call.`;
|
|
48
|
-
|
|
49
|
-
// 2: Audio call missed
|
|
50
|
-
case '2':
|
|
51
|
-
return `📞 Missed audio call from ${userName}.`;
|
|
52
|
-
|
|
53
|
-
// 3: Audio call ended (caller_id ender_id duration)
|
|
54
|
-
case '3': {
|
|
55
|
-
const enderId = parts[2] ?? '';
|
|
56
|
-
const duration = parts[3] ?? '0';
|
|
57
|
-
const enderName = enderId ? resolveUser(enderId, userMap) : 'User';
|
|
58
|
-
return `📞 Audio call by ${userName}, ended by ${enderName}. Duration: ${formatDuration(duration)}.`;
|
|
59
|
-
}
|
|
55
|
+
const number = parseInt(parts[0], 10);
|
|
56
|
+
const callerId = parts[1] ?? '';
|
|
57
|
+
const isMe = myUserId === callerId;
|
|
60
58
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
let enderId = '';
|
|
60
|
+
let duration = '';
|
|
61
|
+
let callType: CallTypeValue | '' = '';
|
|
62
|
+
let color = '';
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// 6: Video call ended (caller_id ender_id duration)
|
|
70
|
-
case '6': {
|
|
71
|
-
const enderId = parts[2] ?? '';
|
|
72
|
-
const duration = parts[3] ?? '0';
|
|
73
|
-
const enderName = enderId ? resolveUser(enderId, userMap) : 'User';
|
|
74
|
-
return `📹 Video call by ${userName}, ended by ${enderName}. Duration: ${formatDuration(duration)}.`;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 7: Audio call rejected
|
|
78
|
-
case '7':
|
|
79
|
-
return `📞 Audio call from ${userName} was rejected.`;
|
|
80
|
-
|
|
81
|
-
// 8: Video call rejected
|
|
82
|
-
case '8':
|
|
83
|
-
return `📹 Video call from ${userName} was rejected.`;
|
|
84
|
-
|
|
85
|
-
// 9: Audio call busy
|
|
86
|
-
case '9':
|
|
87
|
-
return `📞 Audio call from ${userName} — recipient was busy.`;
|
|
88
|
-
|
|
89
|
-
// 10: Video call busy
|
|
90
|
-
case '10':
|
|
91
|
-
return `📹 Video call from ${userName} — recipient was busy.`;
|
|
64
|
+
if (number === 3 || number === 6) {
|
|
65
|
+
enderId = parts[2] ?? '';
|
|
66
|
+
duration = parts[3] === '0' ? '' : (parts[3] ?? '');
|
|
67
|
+
}
|
|
92
68
|
|
|
69
|
+
let text: string;
|
|
70
|
+
switch (number) {
|
|
71
|
+
case 1: // AudioCallStarted
|
|
72
|
+
text = isMe ? 'Calling...' : 'Incoming audio call...';
|
|
73
|
+
callType = CallType.AUDIO;
|
|
74
|
+
color = '#54D62C';
|
|
75
|
+
break;
|
|
76
|
+
case 2: // AudioCallMissed
|
|
77
|
+
text = isMe ? 'Outgoing audio call' : 'You missed audio call';
|
|
78
|
+
callType = CallType.AUDIO;
|
|
79
|
+
color = '#FF4842';
|
|
80
|
+
break;
|
|
81
|
+
case 3: // AudioCallEnded
|
|
82
|
+
if (duration) {
|
|
83
|
+
text = isMe ? 'Outgoing audio call' : 'Incoming audio call';
|
|
84
|
+
color = '#54D62C';
|
|
85
|
+
} else {
|
|
86
|
+
if (enderId === myUserId) {
|
|
87
|
+
text = 'You cancel audio call';
|
|
88
|
+
} else {
|
|
89
|
+
text = 'You missed audio call';
|
|
90
|
+
}
|
|
91
|
+
color = '#FF4842';
|
|
92
|
+
}
|
|
93
|
+
callType = CallType.AUDIO;
|
|
94
|
+
break;
|
|
95
|
+
case 4: // VideoCallStarted
|
|
96
|
+
text = isMe ? 'Calling...' : 'Incoming video call...';
|
|
97
|
+
callType = CallType.VIDEO;
|
|
98
|
+
color = '#54D62C';
|
|
99
|
+
break;
|
|
100
|
+
case 5: // VideoCallMissed
|
|
101
|
+
text = isMe ? 'Outgoing video call' : 'You missed video call';
|
|
102
|
+
callType = CallType.VIDEO;
|
|
103
|
+
color = '#FF4842';
|
|
104
|
+
break;
|
|
105
|
+
case 6: // VideoCallEnded
|
|
106
|
+
if (duration) {
|
|
107
|
+
text = isMe ? 'Outgoing video call' : 'Incoming video call';
|
|
108
|
+
color = '#54D62C';
|
|
109
|
+
} else {
|
|
110
|
+
if (enderId === myUserId) {
|
|
111
|
+
text = 'You cancel video call';
|
|
112
|
+
} else {
|
|
113
|
+
text = 'You missed video call';
|
|
114
|
+
}
|
|
115
|
+
color = '#FF4842';
|
|
116
|
+
}
|
|
117
|
+
callType = CallType.VIDEO;
|
|
118
|
+
break;
|
|
119
|
+
case 7: // AudioCallRejected
|
|
120
|
+
text = isMe ? 'Recipient rejected audio call' : 'You rejected audio call';
|
|
121
|
+
callType = CallType.AUDIO;
|
|
122
|
+
color = '#FF4842';
|
|
123
|
+
break;
|
|
124
|
+
case 8: // VideoCallRejected
|
|
125
|
+
text = isMe ? 'Recipient rejected video call' : 'You rejected video call';
|
|
126
|
+
callType = CallType.VIDEO;
|
|
127
|
+
color = '#FF4842';
|
|
128
|
+
break;
|
|
129
|
+
case 9: // AudioCallBusy
|
|
130
|
+
text = isMe ? 'Recipient was busy' : 'You missed audio call';
|
|
131
|
+
callType = CallType.AUDIO;
|
|
132
|
+
color = '#FF4842';
|
|
133
|
+
break;
|
|
134
|
+
case 10: // VideoCallBusy
|
|
135
|
+
text = isMe ? 'Recipient was busy' : 'You missed video call';
|
|
136
|
+
callType = CallType.VIDEO;
|
|
137
|
+
color = '#FF4842';
|
|
138
|
+
break;
|
|
93
139
|
default:
|
|
94
|
-
|
|
140
|
+
text = trimmed;
|
|
141
|
+
callType = '';
|
|
142
|
+
color = '';
|
|
95
143
|
}
|
|
144
|
+
|
|
145
|
+
return { text, duration: formatDuration(duration), callType, color };
|
|
96
146
|
}
|