@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.
@@ -1,96 +1,146 @@
1
1
  /**
2
- * Convert duration in seconds to mm:ss format.
2
+ * Call type constants for signal messages.
3
3
  */
4
- function formatDuration(durationSec: string): string {
5
- const sec = parseInt(durationSec, 10);
6
- if (isNaN(sec) || sec < 0) return durationSec;
7
- const minutes = Math.floor(sec / 60);
8
- const seconds = sec % 60;
9
- return `${minutes}:${seconds.toString().padStart(2, '0')}`;
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
- * Resolve a user ID to a display name using the provided map.
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 resolveUser(userId: string, userMap: Record<string, string>): string {
17
- return userMap[userId] ?? userId;
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 human-readable English sentence.
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> <userID> [<param1> <param2> ...]"`
39
+ * `"<formatId> <callerId> [<enderId> <duration>]"`
25
40
  *
26
- * @param value - Raw signal message string from the server
27
- * @param userMap - Mapping of user IDs display names
28
- * @returns Parsed English text, or the original string if unknown
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
- userMap: Record<string, string>,
33
- ): string {
34
- if (!value || typeof value !== 'string') return value ?? '';
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 formatId = parts[0];
41
- const userId = parts[1] ?? '';
42
- const userName = userId ? resolveUser(userId, userMap) : 'User';
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
- // 4: Video call started
62
- case '4':
63
- return `📹 ${userName} started a video call.`;
59
+ let enderId = '';
60
+ let duration = '';
61
+ let callType: CallTypeValue | '' = '';
62
+ let color = '';
64
63
 
65
- // 5: Video call missed
66
- case '5':
67
- return `📹 Missed video call from ${userName}.`;
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
- return trimmed;
140
+ text = trimmed;
141
+ callType = '';
142
+ color = '';
95
143
  }
144
+
145
+ return { text, duration: formatDuration(duration), callType, color };
96
146
  }