@samparkchat/sampark-web-chat 0.1.1 → 0.1.3

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.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/sampark/sampark-chat/components/AttachmentFileSharing.js +5 -5
  3. package/sampark/sampark-chat/components/AttachmentGroupFileSharing.js +23 -13
  4. package/sampark/sampark-chat/components/AudioPlayerInline.js +5 -4
  5. package/sampark/sampark-chat/components/GroupVideoCall.d.ts +10 -0
  6. package/sampark/sampark-chat/components/GroupVideoCall.js +155 -60
  7. package/sampark/sampark-chat/components/Headers/ChatHeader.js +3 -62
  8. package/sampark/sampark-chat/components/Headers/HeaderPanel/CallHistory.d.ts +2 -0
  9. package/sampark/sampark-chat/components/Headers/HeaderPanel/CallHistory.js +12 -41
  10. package/sampark/sampark-chat/components/Headers/HeaderPanel/GroupList.js +15 -14
  11. package/sampark/sampark-chat/components/Headers/HeaderPanel/UserList.d.ts +1 -0
  12. package/sampark/sampark-chat/components/Headers/HeaderPanel/UserList.js +7 -14
  13. package/sampark/sampark-chat/components/Headers/SamparkHeader.d.ts +17 -0
  14. package/sampark/sampark-chat/components/Headers/SamparkHeader.js +20 -17
  15. package/sampark/sampark-chat/components/InputModal.d.ts +17 -0
  16. package/sampark/sampark-chat/components/InputModal.js +110 -0
  17. package/sampark/sampark-chat/components/MentionList.js +10 -14
  18. package/sampark/sampark-chat/components/OnlineIndicator.d.ts +14 -0
  19. package/sampark/sampark-chat/components/OnlineIndicator.js +54 -0
  20. package/sampark/sampark-chat/components/ProfileModal.d.ts +3 -0
  21. package/sampark/sampark-chat/components/ProfileModal.js +74 -67
  22. package/sampark/sampark-chat/components/ThreadConversation.d.ts +13 -0
  23. package/sampark/sampark-chat/components/ThreadConversation.js +198 -18
  24. package/sampark/sampark-chat/components/bottomsheets/GroupBottomSheet.d.ts +3 -0
  25. package/sampark/sampark-chat/components/bottomsheets/GroupBottomSheet.js +83 -33
  26. package/sampark/sampark-chat/components/bottomsheets/GroupOptionBottomSheet.d.ts +13 -0
  27. package/sampark/sampark-chat/components/bottomsheets/GroupOptionBottomSheet.js +39 -9
  28. package/sampark/sampark-chat/components/lists/CommonList.d.ts +3 -1
  29. package/sampark/sampark-chat/components/lists/CommonList.js +51 -35
  30. package/sampark/sampark-chat/components/lists/ParticipantList.d.ts +2 -0
  31. package/sampark/sampark-chat/components/lists/ParticipantList.js +8 -5
  32. package/sampark/sampark-chat/components/lists/UserInfo.d.ts +2 -0
  33. package/sampark/sampark-chat/components/lists/UserInfo.js +7 -25
  34. package/sampark/sampark-chat/components/lists/ViewParticipents.d.ts +5 -0
  35. package/sampark/sampark-chat/components/lists/ViewParticipents.js +208 -73
  36. package/sampark/sampark-chat/components/modals/MeetingAdminTransferModal.d.ts +18 -0
  37. package/sampark/sampark-chat/components/modals/MeetingAdminTransferModal.js +264 -0
  38. package/sampark/sampark-chat/components/modals/ProfileAvatar.d.ts +27 -0
  39. package/sampark/sampark-chat/components/modals/ProfileAvatar.js +80 -0
  40. package/sampark/sampark-chat/models/OwnershipTransferModal.d.ts +18 -0
  41. package/sampark/sampark-chat/models/OwnershipTransferModal.js +209 -0
  42. package/sampark/sampark-chat/screens/PeerChatScreen.js +47 -30
  43. package/sampark/sampark-chat/screens/SamparkChatsScreen.js +336 -220
  44. package/sampark/sampark-chat/screens/groupChatScreen.js +19 -51
  45. package/sampark/sampark-chat/sdk/client/GroupCall.d.ts +2 -0
  46. package/sampark/sampark-chat/sdk/client/GroupCall.js +37 -0
  47. package/sampark/sampark-chat/sdk/client/Groupchat.d.ts +8 -0
  48. package/sampark/sampark-chat/sdk/client/Groupchat.js +99 -28
  49. package/sampark/sampark-chat/sdk/client/JanusClient.js +1 -1
  50. package/sampark/sampark-chat/sdk/enum/ActionTypes.d.ts +3 -1
  51. package/sampark/sampark-chat/sdk/enum/ActionTypes.js +2 -0
  52. package/sampark/sampark-chat/sdk/interface/SamparkGroupCallService.d.ts +1 -0
  53. package/sampark/sampark-chat/sdk/interface/SamparkGroupChatService.d.ts +2 -0
  54. package/sampark/sampark-chat/sdk/types/GetGroupsRequest.d.ts +2 -1
  55. package/sampark/sampark-chat/sdk/types/GetGroupsRequest.js +2 -1
  56. package/sampark/sampark-chat/sdk/types/TransferOwnershipRequest.d.ts +12 -0
  57. package/sampark/sampark-chat/sdk/types/TransferOwnershipRequest.js +15 -0
  58. package/sampark/sampark-chat/sdk/types/UpdateParticipantRoleRequest.d.ts +12 -0
  59. package/sampark/sampark-chat/sdk/types/UpdateParticipantRoleRequest.js +16 -0
  60. package/sampark/sampark-chat/theme/colors.d.ts +3 -0
  61. package/sampark/sampark-chat/theme/colors.js +4 -1
  62. package/sampark/sampark-chat/theme/fonts.d.ts +8 -0
  63. package/sampark/sampark-chat/theme/fonts.js +8 -0
  64. package/sampark/sampark-chat/theme/icons.d.ts +30 -0
  65. package/sampark/sampark-chat/theme/icons.js +7 -1
  66. /package/sampark/sampark-chat/components/{models → modals}/ReactionModal.d.ts +0 -0
  67. /package/sampark/sampark-chat/components/{models → modals}/ReactionModal.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@samparkchat/sampark-web-chat",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "main": "sampark/sampark-web-chat/index.js",
5
5
  "types": "sampark/sampark-web-chat/index.d.ts",
6
6
  "private": false,
@@ -134,35 +134,35 @@ var AttachmentFileSharing = function (_a) {
134
134
  position: 'absolute',
135
135
  bottom: '70px',
136
136
  left: '20px',
137
- backgroundColor: 'white',
137
+ backgroundColor: colors.white,
138
138
  borderRadius: '12px',
139
139
  boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
140
140
  padding: '8px',
141
141
  minWidth: '200px',
142
142
  zIndex: 1000
143
143
  } },
144
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
144
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
145
145
  var _a;
146
146
  (_a = imageInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
147
147
  } },
148
148
  React.createElement("div", { style: styles.attachmentIcon },
149
149
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faImage.icon, style: { fontSize: CustomIcons.faImage.size, color: colors.white } })),
150
150
  React.createElement("span", { style: styles.attachmentText }, "Attach Image")),
151
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
151
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
152
152
  var _a;
153
153
  (_a = videoInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
154
154
  } },
155
155
  React.createElement("div", { style: styles.attachmentIcon },
156
156
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faVideo.icon, style: { fontSize: CustomIcons.faVideo.size, color: colors.white } })),
157
157
  React.createElement("span", { style: styles.attachmentText }, "Attach Video")),
158
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
158
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
159
159
  var _a;
160
160
  (_a = audioInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
161
161
  } },
162
162
  React.createElement("div", { style: styles.attachmentIcon },
163
163
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faHeadphones.icon, style: { fontSize: CustomIcons.faHeadphones.size, color: colors.white } })),
164
164
  React.createElement("span", { style: styles.attachmentText }, "Attach Audio")),
165
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
165
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
166
166
  var _a;
167
167
  (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
168
168
  } },
@@ -1,3 +1,14 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
13
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
14
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -38,6 +49,7 @@ import React, { useRef } from 'react';
38
49
  import colors from '../theme/colors';
39
50
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
40
51
  import CustomIcons from '../theme/icons';
52
+ import fonts from '../theme/fonts';
41
53
  var AttachmentGroupFileSharing = function (_a) {
42
54
  var isVisible = _a.isVisible, onClose = _a.onClose, onAttachImage = _a.onAttachImage, onAttachVideo = _a.onAttachVideo, onAttachAudio = _a.onAttachAudio, onAttachFile = _a.onAttachFile, client = _a.client, roomId = _a.roomId, userId = _a.userId, userName = _a.userName, _b = _a.uploadSource, uploadSource = _b === void 0 ? 'group_chat' : _b, onFileUpload = _a.onFileUpload;
43
55
  var imageInputRef = useRef(null);
@@ -65,7 +77,6 @@ var AttachmentGroupFileSharing = function (_a) {
65
77
  _a.label = 3;
66
78
  case 3:
67
79
  if (uploadResult) {
68
- // console.log('[AttachmentGroupFileSharing] file uploaded successfully:', uploadResult);
69
80
  onFileUpload === null || onFileUpload === void 0 ? void 0 : onFileUpload(uploadResult.fileId);
70
81
  onClose();
71
82
  }
@@ -116,53 +127,52 @@ var AttachmentGroupFileSharing = function (_a) {
116
127
  marginRight: '12px'
117
128
  },
118
129
  iconStyle: {
119
- color: 'white',
130
+ color: colors.white,
120
131
  fontSize: '16px'
121
132
  },
122
133
  attachmentText: {
123
- fontSize: '16px',
124
- color: '#333'
134
+ // fontSize: '16px',
125
135
  }
126
136
  };
127
137
  return (React.createElement("div", { className: "attachment-menu", style: {
128
138
  position: 'absolute',
129
139
  bottom: '70px',
130
140
  left: '20px',
131
- backgroundColor: 'white',
141
+ backgroundColor: colors.white,
132
142
  borderRadius: '12px',
133
143
  boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
134
144
  padding: '8px',
135
145
  minWidth: '200px',
136
146
  zIndex: 1000
137
147
  } },
138
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
148
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
139
149
  var _a;
140
150
  (_a = imageInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
141
151
  } },
142
152
  React.createElement("div", { style: styles.attachmentIcon },
143
153
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faImage.icon, style: { fontSize: CustomIcons.faImage.size, color: colors.white } })),
144
- React.createElement("span", { style: styles.attachmentText }, "Attach Image")),
145
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
154
+ React.createElement("span", { style: __assign({}, fonts.content) }, "Attach Image")),
155
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
146
156
  var _a;
147
157
  (_a = videoInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
148
158
  } },
149
159
  React.createElement("div", { style: styles.attachmentIcon },
150
160
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faVideo.icon, style: { fontSize: CustomIcons.faVideo.size, color: colors.white } })),
151
- React.createElement("span", { style: styles.attachmentText }, "Attach Video")),
152
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
161
+ React.createElement("span", { style: __assign({}, fonts.content) }, "Attach Video")),
162
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
153
163
  var _a;
154
164
  (_a = audioInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
155
165
  } },
156
166
  React.createElement("div", { style: styles.attachmentIcon },
157
167
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faHeadphones.icon, style: { fontSize: CustomIcons.faHeadphones.size, color: colors.white } })),
158
- React.createElement("span", { style: styles.attachmentText }, "Attach Audio")),
159
- React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = '#f5f5f5'; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
168
+ React.createElement("span", { style: __assign({}, fonts.content) }, "Attach Audio")),
169
+ React.createElement("div", { style: styles.attachmentMenuItem, onMouseEnter: function (e) { return e.currentTarget.style.backgroundColor = colors.optionHover; }, onMouseLeave: function (e) { return e.currentTarget.style.backgroundColor = 'transparent'; }, onClick: function () {
160
170
  var _a;
161
171
  (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click();
162
172
  } },
163
173
  React.createElement("div", { style: styles.attachmentIcon },
164
174
  React.createElement(FontAwesomeIcon, { icon: CustomIcons.faFile.icon, style: { fontSize: CustomIcons.faFile.size, color: colors.white } })),
165
- React.createElement("span", { style: styles.attachmentText }, "Attach File")),
175
+ React.createElement("span", { style: __assign({}, fonts.content) }, "Attach File")),
166
176
  React.createElement("input", { type: "file", ref: imageInputRef, accept: "image/*", style: { display: 'none' }, onChange: function (e) {
167
177
  var files = e.target.files;
168
178
  if (onAttachImage) {
@@ -1,6 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
3
  import CustomIcons from '../theme/icons';
4
+ import colors from '../theme/colors';
4
5
  var formatTime = function (s) {
5
6
  if (!isFinite(s))
6
7
  return '0:00';
@@ -64,19 +65,19 @@ var AudioPlayerInline = function (_a) {
64
65
  justifyContent: 'center'
65
66
  } },
66
67
  React.createElement(FontAwesomeIcon, { icon: playing ? CustomIcons.faCirclePause.icon : CustomIcons.faPlay.icon, style: {
67
- color: (playing ? CustomIcons.faCirclePause.color : CustomIcons.faPlay.color) || 'white',
68
+ color: (playing ? CustomIcons.faCirclePause.color : CustomIcons.faPlay.color),
68
69
  fontSize: (playing ? CustomIcons.faCirclePause.size : CustomIcons.faPlay.size) || 18
69
70
  } })),
70
71
  React.createElement("div", { style: { flex: 1, display: 'flex', flexDirection: 'column', gap: 6 } },
71
72
  React.createElement("div", { style: { height: 18, display: 'flex', alignItems: 'center', gap: 8 } },
72
73
  React.createElement("div", { style: { flex: 1, height: 6, background: 'rgba(255,255,255,0.12)', borderRadius: 6, position: 'relative' } },
73
74
  React.createElement("div", { style: { position: 'absolute', left: 0, top: 0, bottom: 0, width: "".concat((duration ? (current / duration) * 100 : 0), "%"), background: 'rgba(255,255,255,0.28)', borderRadius: 6 } }))),
74
- React.createElement("div", { style: { display: 'flex', justifyContent: 'flex-end', fontSize: 12, color: 'rgba(255,255,255,0.95)' } },
75
+ React.createElement("div", { style: { display: 'flex', justifyContent: 'flex-end', fontSize: 12, color: colors.white } },
75
76
  React.createElement("div", null,
76
77
  formatTime(current),
77
78
  " / ",
78
79
  formatTime(duration)))),
79
- React.createElement("a", { href: url, download: fileName, style: { color: CustomIcons.faArrowDown.color || 'white', textDecoration: 'none', fontSize: CustomIcons.faArrowDown.size || 18 }, "aria-label": "Download audio" },
80
- React.createElement(FontAwesomeIcon, { icon: CustomIcons.faArrowDown.icon, style: { color: CustomIcons.faArrowDown.color || 'white', fontSize: CustomIcons.faArrowDown.size || 18 } }))));
80
+ React.createElement("a", { href: url, download: fileName, style: { color: CustomIcons.faArrowDown.color, textDecoration: 'none', fontSize: CustomIcons.faArrowDown.size || 18 }, "aria-label": "Download audio" },
81
+ React.createElement(FontAwesomeIcon, { icon: CustomIcons.faArrowDown.icon, style: { color: CustomIcons.faArrowDown.color, fontSize: CustomIcons.faArrowDown.size || 18 } }))));
81
82
  };
82
83
  export default AudioPlayerInline;
@@ -16,11 +16,21 @@ interface GroupVideoCallProps {
16
16
  clientUsers: User[];
17
17
  primaryColor: any;
18
18
  secondaryColor: any;
19
+ callSettings: CallSettings;
19
20
  }
20
21
  interface User {
21
22
  user_id: string;
22
23
  user_name: string;
23
24
  profile_pic?: string;
24
25
  }
26
+ interface CallSettings {
27
+ is_one_to_one_calls: boolean;
28
+ is_group_calls: boolean;
29
+ is_invite_users: boolean;
30
+ is_shared_screen: boolean;
31
+ is_remove_participants: boolean;
32
+ is_record_calls: boolean;
33
+ is_microphone_control: boolean;
34
+ }
25
35
  declare const _default: React.NamedExoticComponent<GroupVideoCallProps>;
26
36
  export default _default;
@@ -60,8 +60,9 @@ import { faVideo, faVideoSlash, faMicrophone, faMicrophoneSlash, faPhoneSlash, f
60
60
  import CustomIcons from "../theme/icons";
61
61
  import colors from "../theme/colors";
62
62
  import fonts from "../theme/fonts";
63
+ import MeetingAdminTransferModal from "./modals/MeetingAdminTransferModal";
63
64
  var GroupVideoCall = function (_a) {
64
- var client = _a.client, userId = _a.userId, userName = _a.userName, onClose = _a.onClose, isInitiator = _a.isInitiator, callingMode = _a.callingMode, janusClient = _a.janusClient, janusHandleId = _a.janusHandleId, createSubscriberHandle = _a.createSubscriberHandle, roomId = _a.roomId, janusCallGroupId = _a.janusCallGroupId, janusCallGroupName = _a.janusCallGroupName, _b = _a.clientUsers, clientUsers = _b === void 0 ? [] : _b, primaryColor = _a.primaryColor, secondaryColor = _a.secondaryColor;
65
+ var client = _a.client, userId = _a.userId, userName = _a.userName, onClose = _a.onClose, isInitiator = _a.isInitiator, callingMode = _a.callingMode, janusClient = _a.janusClient, janusHandleId = _a.janusHandleId, createSubscriberHandle = _a.createSubscriberHandle, roomId = _a.roomId, janusCallGroupId = _a.janusCallGroupId, janusCallGroupName = _a.janusCallGroupName, _b = _a.clientUsers, clientUsers = _b === void 0 ? [] : _b, primaryColor = _a.primaryColor, secondaryColor = _a.secondaryColor, callSettings = _a.callSettings;
65
66
  var getHeaderGradient = function () {
66
67
  var primary = primaryColor || colors.blue;
67
68
  var secondary = secondaryColor || colors.blueLight;
@@ -126,6 +127,8 @@ var GroupVideoCall = function (_a) {
126
127
  var subscriberCreationQueue = useRef(Promise.resolve());
127
128
  var activeSubscriberCreations = useRef(0);
128
129
  var maxConcurrentCreations = 2; // Limit concurrent attach operations
130
+ var _17 = useState(false), showOwnershipTransferModal = _17[0], setShowOwnershipTransferModal = _17[1];
131
+ var previousIsInitiatorRef = useRef(isInitiator);
129
132
  var logICEDiagnostics = function (type, pc) { return __awaiter(void 0, void 0, void 0, function () {
130
133
  var stats, err_1;
131
134
  return __generator(this, function (_a) {
@@ -414,6 +417,12 @@ var GroupVideoCall = function (_a) {
414
417
  onClose();
415
418
  }
416
419
  }, [exitedByAdmin]);
420
+ useEffect(function () {
421
+ if (!previousIsInitiatorRef.current && isInitiator) {
422
+ showJoinNotification("Now you are owner of this call");
423
+ }
424
+ previousIsInitiatorRef.current = isInitiator;
425
+ }, [isInitiator]);
417
426
  useEffect(function () {
418
427
  if (isScreenSharing) {
419
428
  busyUsers.forEach(function (busyUserId) {
@@ -575,7 +584,7 @@ var GroupVideoCall = function (_a) {
575
584
  });
576
585
  }); };
577
586
  var recreatePublisherConnection = function () { return __awaiter(void 0, void 0, void 0, function () {
578
- var pc_1, candidatesSent_1, offer, hasAudio, hasVideo, response, err_4;
587
+ var pc_1, candidatesSent_1, offer, hasAudio, hasVideo, uniqueFileName, response, updateKafkaResponse, err_4;
579
588
  return __generator(this, function (_a) {
580
589
  switch (_a.label) {
581
590
  case 0:
@@ -585,7 +594,7 @@ var GroupVideoCall = function (_a) {
585
594
  }
586
595
  _a.label = 1;
587
596
  case 1:
588
- _a.trys.push([1, 7, 8, 9]);
597
+ _a.trys.push([1, 8, 9, 10]);
589
598
  isPublishingRef.current = true;
590
599
  setPublisherState('joining');
591
600
  if (pcRef.current) {
@@ -597,7 +606,7 @@ var GroupVideoCall = function (_a) {
597
606
  return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 300); })];
598
607
  case 2:
599
608
  _a.sent();
600
- if (!(janusClient && janusHandleId && localStream && publisherState !== 'published')) return [3 /*break*/, 6];
609
+ if (!(janusClient && janusHandleId && localStream && publisherState !== 'published')) return [3 /*break*/, 7];
601
610
  setIsPublishing(true);
602
611
  setPublisherState('publishing');
603
612
  pc_1 = new RTCPeerConnection(pcConfig);
@@ -699,22 +708,27 @@ var GroupVideoCall = function (_a) {
699
708
  _a.sent();
700
709
  hasAudio = localStream.getAudioTracks().length > 0 && micEnabled;
701
710
  hasVideo = localStream.getVideoTracks().length > 0 && cameraEnabled;
702
- return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo }, offer)];
711
+ uniqueFileName = "".concat(roomId, "_").concat(userId, "_").concat(Date.now());
712
+ return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo, record: callSettings.is_record_calls, filename: uniqueFileName }, offer)];
703
713
  case 5:
704
714
  response = _a.sent();
705
715
  setPublisherState('published');
706
- _a.label = 6;
707
- case 6: return [3 /*break*/, 9];
708
- case 7:
716
+ if (!callSettings.is_record_calls) return [3 /*break*/, 7];
717
+ return [4 /*yield*/, client.groupVideoCall.updateKafkaHandler(roomId, janusHandleId, uniqueFileName, uniqueFileName)];
718
+ case 6:
719
+ updateKafkaResponse = _a.sent();
720
+ _a.label = 7;
721
+ case 7: return [3 /*break*/, 10];
722
+ case 8:
709
723
  err_4 = _a.sent();
710
724
  console.error("Error recreating publisher connection:", err_4);
711
725
  setIsPublishing(false);
712
726
  setPublisherState('idle');
713
- return [3 /*break*/, 9];
714
- case 8:
727
+ return [3 /*break*/, 10];
728
+ case 9:
715
729
  isPublishingRef.current = false;
716
730
  return [7 /*endfinally*/];
717
- case 9: return [2 /*return*/];
731
+ case 10: return [2 /*return*/];
718
732
  }
719
733
  });
720
734
  }); };
@@ -1464,30 +1478,43 @@ var GroupVideoCall = function (_a) {
1464
1478
  pd = event.plugindata;
1465
1479
  if (!(event.janus === "event" && ((_c = pd === null || pd === void 0 ? void 0 : pd.data) === null || _c === void 0 ? void 0 : _c.videoroom))) return [3 /*break*/, 3];
1466
1480
  handlePublishers = function (publishers) { return __awaiter(void 0, void 0, void 0, function () {
1467
- var myPubId, _i, publishers_1, pub, pubId;
1481
+ var myPubId, _loop_2, _i, publishers_1, pub;
1468
1482
  return __generator(this, function (_a) {
1469
1483
  switch (_a.label) {
1470
1484
  case 0:
1471
1485
  if (!Array.isArray(publishers)) return [3 /*break*/, 4];
1472
1486
  myPubId = myPublisherIdRef.current;
1487
+ _loop_2 = function (pub) {
1488
+ var pubId, isNewPublisher;
1489
+ return __generator(this, function (_b) {
1490
+ switch (_b.label) {
1491
+ case 0:
1492
+ pubId = Number(pub.id);
1493
+ if (!(pubId !== myPubId)) return [3 /*break*/, 2];
1494
+ isNewPublisher = !notifiedPublishersRef.current.has(pubId) &&
1495
+ !remoteStreams.some(function (s) { return s.id === pubId; }) &&
1496
+ !Array.from(remoteSubscribersRef.current.values()).some(function (sub) { return sub.publisherId === pubId; });
1497
+ return [4 /*yield*/, subscribeToPublisher(pub.id, pub.display)];
1498
+ case 1:
1499
+ _b.sent();
1500
+ if (pd.data.videoroom === "event" && pub.display && isNewPublisher) {
1501
+ notifiedPublishersRef.current.add(pubId); // Mark as notified
1502
+ showJoinNotification("".concat(pub.display, " has joined the call"));
1503
+ }
1504
+ return [3 /*break*/, 2];
1505
+ case 2: return [2 /*return*/];
1506
+ }
1507
+ });
1508
+ };
1473
1509
  _i = 0, publishers_1 = publishers;
1474
1510
  _a.label = 1;
1475
1511
  case 1:
1476
1512
  if (!(_i < publishers_1.length)) return [3 /*break*/, 4];
1477
1513
  pub = publishers_1[_i];
1478
- pubId = Number(pub.id);
1479
- if (!(pubId !== myPubId)) return [3 /*break*/, 3];
1480
- return [4 /*yield*/, subscribeToPublisher(pub.id, pub.display)];
1514
+ return [5 /*yield**/, _loop_2(pub)];
1481
1515
  case 2:
1482
1516
  _a.sent();
1483
- // Show notification when new user joins (only for event, not initial join)
1484
- // Check if we haven't already notified about this publisher
1485
- if (pd.data.videoroom === "event" && pub.display && !notifiedPublishersRef.current.has(pubId)) {
1486
- console.log("🎉 New user joined! Showing notification for:", pub.display);
1487
- notifiedPublishersRef.current.add(pubId); // Mark as notified
1488
- showJoinNotification(pub.display);
1489
- }
1490
- return [3 /*break*/, 3];
1517
+ _a.label = 3;
1491
1518
  case 3:
1492
1519
  _i++;
1493
1520
  return [3 /*break*/, 1];
@@ -1922,7 +1949,7 @@ var GroupVideoCall = function (_a) {
1922
1949
  }); };
1923
1950
  useEffect(function () {
1924
1951
  var publishStream = function () { return __awaiter(void 0, void 0, void 0, function () {
1925
- var pc_3, candidatesGenerated_1, offer, hasAudio, hasVideo, response, err_27;
1952
+ var pc_3, candidatesGenerated_1, offer, hasAudio, hasVideo, uniqueFileName, response, updateKafkaResponse, err_27;
1926
1953
  return __generator(this, function (_a) {
1927
1954
  switch (_a.label) {
1928
1955
  case 0:
@@ -1933,10 +1960,10 @@ var GroupVideoCall = function (_a) {
1933
1960
  !isPublishing &&
1934
1961
  streamInitialized &&
1935
1962
  hasJoinedRoom &&
1936
- publisherState !== 'published')) return [3 /*break*/, 6];
1963
+ publisherState !== 'published')) return [3 /*break*/, 8];
1937
1964
  _a.label = 1;
1938
1965
  case 1:
1939
- _a.trys.push([1, 5, , 6]);
1966
+ _a.trys.push([1, 7, , 8]);
1940
1967
  setIsPublishing(true);
1941
1968
  setPublisherState('publishing');
1942
1969
  pc_3 = new RTCPeerConnection(pcConfig);
@@ -2004,14 +2031,21 @@ var GroupVideoCall = function (_a) {
2004
2031
  _a.sent();
2005
2032
  hasAudio = localStream.getAudioTracks().length > 0 && micEnabled;
2006
2033
  hasVideo = localStream.getVideoTracks().length > 0 && cameraEnabled;
2007
- return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo }, offer)];
2034
+ uniqueFileName = "".concat(roomId, "_").concat(userId, "_").concat(Date.now());
2035
+ return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo, record: callSettings.is_record_calls, filename: uniqueFileName }, offer)];
2008
2036
  case 4:
2009
2037
  response = _a.sent();
2038
+ if (!callSettings.is_record_calls) return [3 /*break*/, 6];
2039
+ return [4 /*yield*/, client.groupVideoCall.updateKafkaHandler(roomId, janusHandleId, uniqueFileName, uniqueFileName)];
2040
+ case 5:
2041
+ updateKafkaResponse = _a.sent();
2042
+ _a.label = 6;
2043
+ case 6:
2010
2044
  if (response === null || response === void 0 ? void 0 : response.error) {
2011
2045
  throw new Error("Janus publish error: ".concat(response.error));
2012
2046
  }
2013
- return [3 /*break*/, 6];
2014
- case 5:
2047
+ return [3 /*break*/, 8];
2048
+ case 7:
2015
2049
  err_27 = _a.sent();
2016
2050
  console.error("Error publishing initial stream:", err_27);
2017
2051
  setIsPublishing(false);
@@ -2022,8 +2056,8 @@ var GroupVideoCall = function (_a) {
2022
2056
  setIsPublishing(false);
2023
2057
  }, 2000 * (reconnectAttempts + 1));
2024
2058
  }
2025
- return [3 /*break*/, 6];
2026
- case 6: return [2 /*return*/];
2059
+ return [3 /*break*/, 8];
2060
+ case 8: return [2 /*return*/];
2027
2061
  }
2028
2062
  });
2029
2063
  }); };
@@ -2176,23 +2210,37 @@ var GroupVideoCall = function (_a) {
2176
2210
  return map;
2177
2211
  }, [remoteStreams, speakingUsers]);
2178
2212
  var filteredAvailableUsers = React.useMemo(function () {
2179
- if (!searchQuery.trim())
2180
- return availableUsers;
2181
- var query = searchQuery.toLowerCase();
2182
- return availableUsers.filter(function (user) {
2213
+ var users = availableUsers;
2214
+ if (searchQuery.trim()) {
2215
+ var query_1 = searchQuery.toLowerCase();
2216
+ users = availableUsers.filter(function (user) {
2217
+ var _a, _b;
2218
+ return ((_a = user.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query_1)) ||
2219
+ ((_b = user.user_id) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(query_1));
2220
+ });
2221
+ }
2222
+ return users.sort(function (a, b) {
2183
2223
  var _a, _b;
2184
- return ((_a = user.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query)) ||
2185
- ((_b = user.user_id) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(query));
2224
+ var nameA = ((_a = a.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
2225
+ var nameB = ((_b = b.user_name) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || '';
2226
+ return nameA.localeCompare(nameB);
2186
2227
  });
2187
2228
  }, [availableUsers, searchQuery]);
2188
2229
  var filteredCurrentCallUsers = React.useMemo(function () {
2189
- if (!searchQuery.trim())
2190
- return usersInCurrentCall;
2191
- var query = searchQuery.toLowerCase();
2192
- return usersInCurrentCall.filter(function (user) {
2230
+ var users = usersInCurrentCall;
2231
+ if (searchQuery.trim()) {
2232
+ var query_2 = searchQuery.toLowerCase();
2233
+ users = usersInCurrentCall.filter(function (user) {
2234
+ var _a, _b;
2235
+ return ((_a = user.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query_2)) ||
2236
+ ((_b = user.user_id) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(query_2));
2237
+ });
2238
+ }
2239
+ return users.sort(function (a, b) {
2193
2240
  var _a, _b;
2194
- return ((_a = user.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes(query)) ||
2195
- ((_b = user.user_id) === null || _b === void 0 ? void 0 : _b.toLowerCase().includes(query));
2241
+ var nameA = ((_a = a.user_name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
2242
+ var nameB = ((_b = b.user_name) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || '';
2243
+ return nameA.localeCompare(nameB);
2196
2244
  });
2197
2245
  }, [usersInCurrentCall, searchQuery]);
2198
2246
  var getStreamForUserId = function (targetUserId) {
@@ -2212,14 +2260,14 @@ var GroupVideoCall = function (_a) {
2212
2260
  var gridCols = Math.ceil(Math.sqrt(Math.max(1, count)));
2213
2261
  var gridRows = Math.ceil(count / gridCols);
2214
2262
  var forceRepublish = function () { return __awaiter(void 0, void 0, void 0, function () {
2215
- var hasAudio, hasVideo, offer, response, err_28;
2263
+ var hasAudio, hasVideo, offer, uniqueFileName, response, updateKafkaResponse, err_28;
2216
2264
  return __generator(this, function (_a) {
2217
2265
  switch (_a.label) {
2218
2266
  case 0:
2219
- if (!(pcRef.current && janusClient && janusHandleId && localStream)) return [3 /*break*/, 7];
2267
+ if (!(pcRef.current && janusClient && janusHandleId && localStream)) return [3 /*break*/, 9];
2220
2268
  _a.label = 1;
2221
2269
  case 1:
2222
- _a.trys.push([1, 6, , 7]);
2270
+ _a.trys.push([1, 8, , 9]);
2223
2271
  hasAudio = localStream.getAudioTracks().length > 0 && micEnabled;
2224
2272
  hasVideo = localStream.getVideoTracks().length > 0 && cameraEnabled;
2225
2273
  return [4 /*yield*/, janusClient.sendMessage(janusHandleId, {
@@ -2238,15 +2286,21 @@ var GroupVideoCall = function (_a) {
2238
2286
  return [4 /*yield*/, pcRef.current.setLocalDescription(offer)];
2239
2287
  case 4:
2240
2288
  _a.sent();
2241
- return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo }, offer)];
2289
+ uniqueFileName = "".concat(roomId, "_").concat(userId, "_").concat(Date.now());
2290
+ return [4 /*yield*/, janusClient.sendMessage(janusHandleId, { request: "publish", audio: hasAudio, video: hasVideo, record: callSettings.is_record_calls, filename: uniqueFileName }, offer)];
2242
2291
  case 5:
2243
2292
  response = _a.sent();
2244
- return [3 /*break*/, 7];
2293
+ if (!callSettings.is_record_calls) return [3 /*break*/, 7];
2294
+ return [4 /*yield*/, client.groupVideoCall.updateKafkaHandler(roomId, janusHandleId, uniqueFileName, uniqueFileName)];
2245
2295
  case 6:
2296
+ updateKafkaResponse = _a.sent();
2297
+ _a.label = 7;
2298
+ case 7: return [3 /*break*/, 9];
2299
+ case 8:
2246
2300
  err_28 = _a.sent();
2247
2301
  console.error("Error in force republish:", err_28);
2248
- return [3 /*break*/, 7];
2249
- case 7: return [2 /*return*/];
2302
+ return [3 /*break*/, 9];
2303
+ case 9: return [2 /*return*/];
2250
2304
  }
2251
2305
  });
2252
2306
  }); };
@@ -2289,6 +2343,50 @@ var GroupVideoCall = function (_a) {
2289
2343
  }
2290
2344
  });
2291
2345
  }); };
2346
+ var handleEndCall = function () {
2347
+ if (isInitiator && usersInCurrentCall.length > 1) {
2348
+ // Show ownership transfer modal if initiator and there are other participants
2349
+ setShowOwnershipTransferModal(true);
2350
+ }
2351
+ else {
2352
+ // Directly end the call if not initiator or alone in the call
2353
+ cleanupSession();
2354
+ onClose();
2355
+ }
2356
+ };
2357
+ var handleOwnershipTransfer = function (newOwnerId) { return __awaiter(void 0, void 0, void 0, function () {
2358
+ var error_3;
2359
+ return __generator(this, function (_a) {
2360
+ switch (_a.label) {
2361
+ case 0:
2362
+ _a.trys.push([0, 3, , 4]);
2363
+ if (!(client && roomId)) return [3 /*break*/, 2];
2364
+ return [4 /*yield*/, client.groupVideoCall.transferOwnership(roomId, newOwnerId)];
2365
+ case 1:
2366
+ _a.sent();
2367
+ _a.label = 2;
2368
+ case 2:
2369
+ // Close modal and end call
2370
+ setShowOwnershipTransferModal(false);
2371
+ cleanupSession();
2372
+ onClose();
2373
+ return [3 /*break*/, 4];
2374
+ case 3:
2375
+ error_3 = _a.sent();
2376
+ console.error("Error transferring ownership:", error_3);
2377
+ return [3 /*break*/, 4];
2378
+ case 4: return [2 /*return*/];
2379
+ }
2380
+ });
2381
+ }); };
2382
+ var handleCancelOwnershipTransfer = function () {
2383
+ setShowOwnershipTransferModal(false);
2384
+ };
2385
+ var handleEndCallAnyway = function () {
2386
+ setShowOwnershipTransferModal(false);
2387
+ cleanupSession();
2388
+ onClose();
2389
+ };
2292
2390
  useEffect(function () {
2293
2391
  window.forceRepublish = forceRepublish;
2294
2392
  window.recreateConnection = recreatePublisherConnection;
@@ -2474,10 +2572,7 @@ var GroupVideoCall = function (_a) {
2474
2572
  React.createElement(FontAwesomeIcon, { style: { fontSize: '20px' }, icon: faUserPlus })),
2475
2573
  React.createElement("span", { className: "custom-tooltip" }, "Invite participants")),
2476
2574
  React.createElement("div", { className: "control-button-wrapper" },
2477
- React.createElement("button", { style: __assign(__assign({}, styles.controlButton), styles.endCallButton), onClick: function () {
2478
- cleanupSession();
2479
- onClose();
2480
- } },
2575
+ React.createElement("button", { style: __assign(__assign({}, styles.controlButton), styles.endCallButton), onClick: handleEndCall },
2481
2576
  React.createElement(FontAwesomeIcon, { style: { fontSize: '20px' }, icon: faPhoneSlash })),
2482
2577
  React.createElement("span", { className: "custom-tooltip" }, "End call")))),
2483
2578
  showScreenSharePopup && (React.createElement("div", { style: styles.screenSharePopupOverlay, onClick: function () { return setShowScreenSharePopup(false); } },
@@ -2695,8 +2790,8 @@ var GroupVideoCall = function (_a) {
2695
2790
  } },
2696
2791
  React.createElement("span", { style: { fontSize: '20px' } }, "\uD83D\uDC4B"),
2697
2792
  React.createElement("span", null,
2698
- React.createElement("strong", null, notification.userName),
2699
- " joined the call"))); }))));
2793
+ React.createElement("strong", null, notification.userName)))); })),
2794
+ React.createElement(MeetingAdminTransferModal, { open: showOwnershipTransferModal, onClose: handleCancelOwnershipTransfer, onTransfer: handleOwnershipTransfer, onEndCallAnyway: handleEndCallAnyway, participants: usersInCurrentCall, currentUserId: userId, primaryColor: primaryColor, secondaryColor: secondaryColor })));
2700
2795
  };
2701
2796
  var styles = {
2702
2797
  container: {
@@ -2884,7 +2979,7 @@ var styles = {
2884
2979
  display: "grid",
2885
2980
  gap: "10px",
2886
2981
  padding: "20px",
2887
- height: "calc(100vh - 120px)",
2982
+ height: "calc(100vh - 100px)",
2888
2983
  },
2889
2984
  videoWrapper: {
2890
2985
  position: "relative",
@@ -2941,8 +3036,8 @@ var styles = {
2941
3036
  position: "absolute",
2942
3037
  top: "8px",
2943
3038
  right: "8px",
2944
- width: "20px",
2945
- height: "20px",
3039
+ width: "30px",
3040
+ height: "30px",
2946
3041
  borderRadius: "50%",
2947
3042
  background: "rgba(34, 197, 94, 0.8)",
2948
3043
  border: "2px solid rgba(34, 197, 94, 0.4)",
@@ -2990,7 +3085,7 @@ var styles = {
2990
3085
  controlsContainer: {
2991
3086
  position: "absolute",
2992
3087
  left: "50%",
2993
- bottom: "32px",
3088
+ bottom: "12px",
2994
3089
  transform: "translateX(-50%)",
2995
3090
  display: "flex",
2996
3091
  gap: "24px",