@realtimexsco/live-chat 1.4.16 → 1.4.17
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/PERMISSIONS.md +236 -0
- package/README.md +26 -18
- package/dist/index.cjs +64 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.mjs +63 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -10
package/PERMISSIONS.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Admin permissions & custom UI
|
|
2
|
+
|
|
3
|
+
How `@realtimexsco/live-chat` applies workspace **effective settings**, and how to keep the same rules when you replace UI with your own components.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
After the chat session is ready, the package fetches:
|
|
10
|
+
|
|
11
|
+
```http
|
|
12
|
+
GET /settings/effective
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Settings are stored in `ChatEffectiveSettingsProvider` and used to **gate** features in the default UI:
|
|
16
|
+
|
|
17
|
+
| Rule | Behavior |
|
|
18
|
+
|------|----------|
|
|
19
|
+
| Feature denied | Control stays **visible** |
|
|
20
|
+
| Interaction | **Disabled** |
|
|
21
|
+
| Hover | Tooltip with reason (e.g. *This feature is disabled by your administrator.*) |
|
|
22
|
+
|
|
23
|
+
Default components already honor these gates. **Custom slot components must honor them too** — the package cannot force-disable arbitrary host JSX.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## What the API controls
|
|
28
|
+
|
|
29
|
+
| API field | UI effect |
|
|
30
|
+
|-----------|-----------|
|
|
31
|
+
| `pushNotificationEnabled` | Settings → push toggle (visible, disabled + tooltip if off) |
|
|
32
|
+
| `audioCallEnabled` / `videoCallEnabled` | Header phone / video buttons |
|
|
33
|
+
| `calls.allowedByPlatform` | Checked first for calls |
|
|
34
|
+
| `calls.configured` | Calls not configured message |
|
|
35
|
+
| `calls.enabled` | Calls disabled by admin |
|
|
36
|
+
| `blockUsersEnabled` | Block user menu item |
|
|
37
|
+
| `attachments.enabled` | Paperclip / attach |
|
|
38
|
+
| `attachments.maxFileSizeMB` | Max upload size |
|
|
39
|
+
| `attachments.allowedMimeTypes` | Allowed MIME (`*` / `*/*` = all) |
|
|
40
|
+
| `attachments.maxAttachmentsPerMessage` | Max files per message |
|
|
41
|
+
| `groupCreationEnabled` | “New group” tab |
|
|
42
|
+
| `groupPolicy.defaults` / `locked` | Group permission drawer |
|
|
43
|
+
| `messageTimers.*` | Edit / delete time windows (DM vs group) |
|
|
44
|
+
| `maxAdminsPerGroup` | Max group admins |
|
|
45
|
+
| `maxParticipantsPerGroup` | Max group members |
|
|
46
|
+
| `maxPinnedMessagesPerConversation` | Max pins |
|
|
47
|
+
|
|
48
|
+
### Calls check order
|
|
49
|
+
|
|
50
|
+
1. `calls.allowedByPlatform`
|
|
51
|
+
2. `calls.configured`
|
|
52
|
+
3. `calls.enabled`
|
|
53
|
+
4. `audioCallEnabled` / `videoCallEnabled`
|
|
54
|
+
|
|
55
|
+
Same rules apply in **DM and group** chats.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Exports you need
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import {
|
|
63
|
+
useAdminFeatureGate,
|
|
64
|
+
useEffectiveSettingsOptional,
|
|
65
|
+
AdminPermissionTooltip,
|
|
66
|
+
ADMIN_PERMISSION_DENIED_MESSAGE,
|
|
67
|
+
type CallFeatureGate,
|
|
68
|
+
type AdminFeatureKey,
|
|
69
|
+
} from "@realtimexsco/live-chat";
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Feature keys (`useAdminFeatureGate`)
|
|
73
|
+
|
|
74
|
+
| Key | Gate |
|
|
75
|
+
|-----|------|
|
|
76
|
+
| `"audioCall"` | Voice call |
|
|
77
|
+
| `"videoCall"` | Video call |
|
|
78
|
+
| `"pushNotification"` | Push toggle |
|
|
79
|
+
| `"blockUsers"` | Block user |
|
|
80
|
+
| `"attachments"` | Attach files |
|
|
81
|
+
| `"groupCreation"` | Create group |
|
|
82
|
+
|
|
83
|
+
### Gate shape (`CallFeatureGate`)
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
{
|
|
87
|
+
visible: boolean; // keep UI visible
|
|
88
|
+
enabled: boolean; // allow click / toggle
|
|
89
|
+
disabledReason: string | null; // tooltip text when disabled
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Two ways to customize (important)
|
|
96
|
+
|
|
97
|
+
### Option A — Prefer small slots (recommended)
|
|
98
|
+
|
|
99
|
+
Override only the look of a control. Let the package wrapper apply gates + tooltips.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// ✅ Good — package HeaderCallActions still applies permissions
|
|
103
|
+
components: {
|
|
104
|
+
PhoneCallButton: MyPhoneButton,
|
|
105
|
+
VideoCallButton: MyVideoButton,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ❌ Avoid unless you wire gates yourself
|
|
109
|
+
components: {
|
|
110
|
+
HeaderCallActions: MyCallActions, // replaces gated wrapper
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Your button should still honor props the package passes:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
function MyVideoButton({
|
|
118
|
+
onVideoCall,
|
|
119
|
+
disabled,
|
|
120
|
+
disabledReason,
|
|
121
|
+
className,
|
|
122
|
+
}: VideoCallButtonSlotProps) {
|
|
123
|
+
return (
|
|
124
|
+
<button
|
|
125
|
+
type="button"
|
|
126
|
+
className={className}
|
|
127
|
+
disabled={disabled}
|
|
128
|
+
aria-disabled={disabled}
|
|
129
|
+
onClick={disabled ? undefined : onVideoCall}
|
|
130
|
+
>
|
|
131
|
+
Video
|
|
132
|
+
</button>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
(The package wraps this with `AdminPermissionTooltip` when used via default `HeaderCallActions`.)
|
|
138
|
+
|
|
139
|
+
### Option B — Full custom slot
|
|
140
|
+
|
|
141
|
+
If you replace a whole slot (e.g. `HeaderCallActions`, custom attach button, custom push row), **you** must read the gate and apply disable + tooltip.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import {
|
|
145
|
+
useAdminFeatureGate,
|
|
146
|
+
AdminPermissionTooltip,
|
|
147
|
+
} from "@realtimexsco/live-chat";
|
|
148
|
+
|
|
149
|
+
function MyVideoCallButton({ onVideoCall, className }) {
|
|
150
|
+
const gate = useAdminFeatureGate("videoCall");
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<AdminPermissionTooltip
|
|
154
|
+
disabled={!gate.enabled}
|
|
155
|
+
message={gate.disabledReason}
|
|
156
|
+
side="bottom"
|
|
157
|
+
>
|
|
158
|
+
<button
|
|
159
|
+
type="button"
|
|
160
|
+
className={className}
|
|
161
|
+
disabled={!gate.enabled}
|
|
162
|
+
onClick={gate.enabled ? onVideoCall : undefined}
|
|
163
|
+
>
|
|
164
|
+
Video
|
|
165
|
+
</button>
|
|
166
|
+
</AdminPermissionTooltip>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Same pattern for other features — change the key only:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
useAdminFeatureGate("audioCall");
|
|
175
|
+
useAdminFeatureGate("pushNotification");
|
|
176
|
+
useAdminFeatureGate("blockUsers");
|
|
177
|
+
useAdminFeatureGate("attachments");
|
|
178
|
+
useAdminFeatureGate("groupCreation");
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Contract for every custom permission-aware control
|
|
184
|
+
|
|
185
|
+
| Do | Don’t |
|
|
186
|
+
|----|--------|
|
|
187
|
+
| Keep the control **visible** when denied | Hide the button when permission is off |
|
|
188
|
+
| Set `disabled={!gate.enabled}` | Leave it clickable |
|
|
189
|
+
| Wrap with `AdminPermissionTooltip` | Skip the tooltip |
|
|
190
|
+
| Use `useAdminFeatureGate` / gate props | Hardcode your own permission logic |
|
|
191
|
+
| Clear `onClick` when disabled | Fire the action when disabled |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Advanced: raw settings
|
|
196
|
+
|
|
197
|
+
For limits (file size, max participants, timers, locked group policy), use:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const { settings, loading, isGroupPermissionLocked } =
|
|
201
|
+
useEffectiveSettingsOptional();
|
|
202
|
+
|
|
203
|
+
settings.attachments.maxFileSizeMB;
|
|
204
|
+
settings.maxParticipantsPerGroup;
|
|
205
|
+
settings.messageTimers.dmEditMinutes;
|
|
206
|
+
isGroupPermissionLocked("onlyAdminCanSendMessage");
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
While `loading` is `true`, show a spinner instead of flashing the wrong enabled state (same idea as the push settings row).
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Loading state
|
|
214
|
+
|
|
215
|
+
Effective settings and feature-specific APIs (e.g. push config) may load after the modal/UI opens. Recommended pattern:
|
|
216
|
+
|
|
217
|
+
1. If `loading` → show row + spinner
|
|
218
|
+
2. When ready → show control with correct enabled/disabled state
|
|
219
|
+
3. Never flash “enabled” then suddenly disable without explanation
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Checklist for host apps
|
|
224
|
+
|
|
225
|
+
- [ ] Default UI: no extra work — gates are built in
|
|
226
|
+
- [ ] Custom `PhoneCallButton` / `VideoCallButton`: honor `disabled` (+ optional `disabledReason`)
|
|
227
|
+
- [ ] Custom `HeaderCallActions` / full call UI: use `useAdminFeatureGate` + `AdminPermissionTooltip`
|
|
228
|
+
- [ ] Custom push / attach / block / create-group UI: same gate + tooltip pattern
|
|
229
|
+
- [ ] Do not override `HeaderCallActions` only for styling — override `PhoneCallButton` / `VideoCallButton` instead
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Related
|
|
234
|
+
|
|
235
|
+
- Package docs: [https://realtimex.softwareco.com/documentations/package](https://realtimex.softwareco.com/documentations/package)
|
|
236
|
+
- npm: [https://www.npmjs.com/package/@realtimexsco/live-chat](https://www.npmjs.com/package/@realtimexsco/live-chat)
|
package/README.md
CHANGED
|
@@ -2,22 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
> Drop-in real-time chat UI for React and Next.js — direct messages, group chats, reactions, replies, forwarding, pinned/starred messages, and more. Built on Socket.IO, Zustand, Tailwind CSS v4, and Radix UI.
|
|
4
4
|
|
|
5
|
-
[
|
|
6
|
-
[
|
|
7
|
-
[
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
|
12
|
-
| **
|
|
13
|
-
| **
|
|
14
|
-
| **
|
|
15
|
-
| **
|
|
5
|
+
[npm version](https://www.npmjs.com/package/@realtimexsco/live-chat)
|
|
6
|
+
[npm downloads](https://www.npmjs.com/package/@realtimexsco/live-chat)
|
|
7
|
+
[license](#license)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
| | |
|
|
11
|
+
| ------------ | ---------------------------------------------------------------------------------- |
|
|
12
|
+
| **Package** | `[@realtimexsco/live-chat](https://www.npmjs.com/package/@realtimexsco/live-chat)` |
|
|
13
|
+
| **Styles** | `@realtimexsco/live-chat/styles.css` |
|
|
14
|
+
| **Requires** | React 17+, Tailwind CSS **v4**, Zustand 4+ |
|
|
15
|
+
| **Docs** | [Package documentation](https://realtimex.softwareco.com/documentations/package) |
|
|
16
|
+
| **License** | [MIT](#license) |
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
Socket.IO, REST client, Zustand store, Radix UI, emoji picker, and chat UI are **bundled**. Your app only installs peer dependencies.
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
23
|
+
|
|
24
|
+
|
|
21
25
|
## Install
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -49,23 +53,27 @@ export default function ChatPage() {
|
|
|
49
53
|
|
|
50
54
|
---
|
|
51
55
|
|
|
56
|
+
|
|
57
|
+
|
|
52
58
|
## Features
|
|
53
59
|
|
|
54
60
|
DMs · groups · Socket.IO · reactions · replies · forward · edit/delete · pin/star · attachments · search · typing · read receipts · light/dark · locale/timezone · full UI customization
|
|
55
61
|
|
|
56
62
|
---
|
|
57
63
|
|
|
64
|
+
|
|
65
|
+
|
|
58
66
|
## More information
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
|
|
69
|
+
| Topic | Link |
|
|
70
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
62
71
|
| Full setup & docs | [https://realtimex.softwareco.com/documentations/package](https://realtimex.softwareco.com/documentations/package) |
|
|
63
|
-
| npm package
|
|
64
|
-
| License
|
|
72
|
+
| npm package | [npmjs.com/package/@realtimexsco/live-chat](https://www.npmjs.com/package/@realtimexsco/live-chat) |
|
|
73
|
+
| License | [MIT](#license) |
|
|
65
74
|
|
|
66
|
-
---
|
|
67
75
|
|
|
68
|
-
|
|
76
|
+
---
|
|
69
77
|
|
|
70
78
|
## License
|
|
71
79
|
|
|
@@ -77,4 +85,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
77
85
|
|
|
78
86
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
79
87
|
|
|
80
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
88
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/index.cjs
CHANGED
|
@@ -9039,23 +9039,24 @@ var DefaultHeaderCallActions = ({
|
|
|
9039
9039
|
showVideoCall = true,
|
|
9040
9040
|
onPhoneCall,
|
|
9041
9041
|
onVideoCall,
|
|
9042
|
+
phoneCallDisabled = false,
|
|
9043
|
+
videoCallDisabled = false,
|
|
9044
|
+
phoneCallDisabledReason = null,
|
|
9045
|
+
videoCallDisabledReason = null,
|
|
9042
9046
|
className
|
|
9043
9047
|
}) => {
|
|
9044
9048
|
const { components, slotClassName } = useChatCustomizationOptional();
|
|
9045
|
-
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
9046
9049
|
const PhoneSlot = components.PhoneCallButton;
|
|
9047
9050
|
const VideoSlot = components.VideoCallButton;
|
|
9048
|
-
const audioGate = getAudioCallGate();
|
|
9049
|
-
const videoGate = getVideoCallGate();
|
|
9050
9051
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
9051
|
-
const phoneEnabled = showPhoneCall &&
|
|
9052
|
-
const videoEnabled = showVideoCall &&
|
|
9052
|
+
const phoneEnabled = showPhoneCall && !phoneCallDisabled;
|
|
9053
|
+
const videoEnabled = showVideoCall && !videoCallDisabled;
|
|
9053
9054
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9054
9055
|
showPhoneCall && (PhoneSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9055
9056
|
AdminPermissionTooltip,
|
|
9056
9057
|
{
|
|
9057
|
-
disabled:
|
|
9058
|
-
message:
|
|
9058
|
+
disabled: phoneCallDisabled,
|
|
9059
|
+
message: phoneCallDisabledReason,
|
|
9059
9060
|
side: "bottom",
|
|
9060
9061
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9061
9062
|
PhoneSlot,
|
|
@@ -9063,10 +9064,12 @@ var DefaultHeaderCallActions = ({
|
|
|
9063
9064
|
activeChannel,
|
|
9064
9065
|
conversationId,
|
|
9065
9066
|
onPhoneCall: phoneEnabled ? onPhoneCall : void 0,
|
|
9067
|
+
disabled: phoneCallDisabled,
|
|
9068
|
+
disabledReason: phoneCallDisabledReason,
|
|
9066
9069
|
className: cn(
|
|
9067
9070
|
className,
|
|
9068
9071
|
slotClassName("phoneCallButton"),
|
|
9069
|
-
|
|
9072
|
+
phoneCallDisabled && "opacity-40"
|
|
9070
9073
|
)
|
|
9071
9074
|
}
|
|
9072
9075
|
) })
|
|
@@ -9074,8 +9077,8 @@ var DefaultHeaderCallActions = ({
|
|
|
9074
9077
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9075
9078
|
AdminPermissionTooltip,
|
|
9076
9079
|
{
|
|
9077
|
-
disabled:
|
|
9078
|
-
message:
|
|
9080
|
+
disabled: phoneCallDisabled,
|
|
9081
|
+
message: phoneCallDisabledReason,
|
|
9079
9082
|
side: "bottom",
|
|
9080
9083
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9081
9084
|
Button,
|
|
@@ -9084,7 +9087,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9084
9087
|
size: "icon",
|
|
9085
9088
|
className: cn(actionBtnClass, className, slotClassName("phoneCallButton")),
|
|
9086
9089
|
"aria-label": "Voice call",
|
|
9087
|
-
disabled:
|
|
9090
|
+
disabled: phoneCallDisabled,
|
|
9088
9091
|
onClick: phoneEnabled ? onPhoneCall : void 0,
|
|
9089
9092
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Phone, { size: 15 })
|
|
9090
9093
|
}
|
|
@@ -9094,8 +9097,8 @@ var DefaultHeaderCallActions = ({
|
|
|
9094
9097
|
showVideoCall && (VideoSlot ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9095
9098
|
AdminPermissionTooltip,
|
|
9096
9099
|
{
|
|
9097
|
-
disabled:
|
|
9098
|
-
message:
|
|
9100
|
+
disabled: videoCallDisabled,
|
|
9101
|
+
message: videoCallDisabledReason,
|
|
9099
9102
|
side: "bottom",
|
|
9100
9103
|
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9101
9104
|
VideoSlot,
|
|
@@ -9103,10 +9106,12 @@ var DefaultHeaderCallActions = ({
|
|
|
9103
9106
|
activeChannel,
|
|
9104
9107
|
conversationId,
|
|
9105
9108
|
onVideoCall: videoEnabled ? onVideoCall : void 0,
|
|
9109
|
+
disabled: videoCallDisabled,
|
|
9110
|
+
disabledReason: videoCallDisabledReason,
|
|
9106
9111
|
className: cn(
|
|
9107
9112
|
className,
|
|
9108
9113
|
slotClassName("videoCallButton"),
|
|
9109
|
-
|
|
9114
|
+
videoCallDisabled && "opacity-40"
|
|
9110
9115
|
)
|
|
9111
9116
|
}
|
|
9112
9117
|
) })
|
|
@@ -9114,8 +9119,8 @@ var DefaultHeaderCallActions = ({
|
|
|
9114
9119
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
9115
9120
|
AdminPermissionTooltip,
|
|
9116
9121
|
{
|
|
9117
|
-
disabled:
|
|
9118
|
-
message:
|
|
9122
|
+
disabled: videoCallDisabled,
|
|
9123
|
+
message: videoCallDisabledReason,
|
|
9119
9124
|
side: "bottom",
|
|
9120
9125
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9121
9126
|
Button,
|
|
@@ -9124,7 +9129,7 @@ var DefaultHeaderCallActions = ({
|
|
|
9124
9129
|
size: "icon",
|
|
9125
9130
|
className: cn(actionBtnClass, className, slotClassName("videoCallButton")),
|
|
9126
9131
|
"aria-label": "Video call",
|
|
9127
|
-
disabled:
|
|
9132
|
+
disabled: videoCallDisabled,
|
|
9128
9133
|
onClick: videoEnabled ? onVideoCall : void 0,
|
|
9129
9134
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { size: 15 })
|
|
9130
9135
|
}
|
|
@@ -9135,12 +9140,27 @@ var DefaultHeaderCallActions = ({
|
|
|
9135
9140
|
};
|
|
9136
9141
|
var HeaderCallActions = (props) => {
|
|
9137
9142
|
const { components, slotClassName } = useChatCustomizationOptional();
|
|
9143
|
+
const { getAudioCallGate, getVideoCallGate } = useEffectiveSettingsOptional();
|
|
9138
9144
|
const Custom = components.HeaderCallActions;
|
|
9139
9145
|
const showPhoneCall = props.showPhoneCall ?? true;
|
|
9140
9146
|
const showVideoCall = props.showVideoCall ?? true;
|
|
9147
|
+
const audioGate = getAudioCallGate();
|
|
9148
|
+
const videoGate = getVideoCallGate();
|
|
9141
9149
|
if (!showPhoneCall && !showVideoCall) return null;
|
|
9142
|
-
const
|
|
9143
|
-
|
|
9150
|
+
const gatedProps = {
|
|
9151
|
+
...props,
|
|
9152
|
+
showPhoneCall,
|
|
9153
|
+
showVideoCall,
|
|
9154
|
+
onPhoneCall: audioGate.enabled ? props.onPhoneCall : void 0,
|
|
9155
|
+
onVideoCall: videoGate.enabled ? props.onVideoCall : void 0,
|
|
9156
|
+
phoneCallDisabled: !audioGate.enabled,
|
|
9157
|
+
videoCallDisabled: !videoGate.enabled,
|
|
9158
|
+
phoneCallDisabledReason: audioGate.disabledReason,
|
|
9159
|
+
videoCallDisabledReason: videoGate.disabledReason
|
|
9160
|
+
};
|
|
9161
|
+
const hasButtonSlots = components.PhoneCallButton != null || components.VideoCallButton != null;
|
|
9162
|
+
const useCustom = Custom != null && Custom !== HeaderCallActions && !hasButtonSlots;
|
|
9163
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-0.5", slotClassName("headerCallActions")), children: useCustom ? /* @__PURE__ */ jsxRuntime.jsx(Custom, { ...gatedProps }) : /* @__PURE__ */ jsxRuntime.jsx(DefaultHeaderCallActions, { ...gatedProps }) });
|
|
9144
9164
|
};
|
|
9145
9165
|
var HeaderCallActions_default = HeaderCallActions;
|
|
9146
9166
|
function OptionsMenuItem({
|
|
@@ -19736,11 +19756,35 @@ var packageDefaultComponents = {
|
|
|
19736
19756
|
ChatSocketStatus: ChatSocketStatus_default
|
|
19737
19757
|
};
|
|
19738
19758
|
|
|
19759
|
+
// src/hooks/useAdminFeatureGate.ts
|
|
19760
|
+
function useAdminFeatureGate(feature) {
|
|
19761
|
+
const ctx = useEffectiveSettingsOptional();
|
|
19762
|
+
switch (feature) {
|
|
19763
|
+
case "audioCall":
|
|
19764
|
+
return ctx.getAudioCallGate();
|
|
19765
|
+
case "videoCall":
|
|
19766
|
+
return ctx.getVideoCallGate();
|
|
19767
|
+
case "pushNotification":
|
|
19768
|
+
return ctx.getPushNotificationGate();
|
|
19769
|
+
case "blockUsers":
|
|
19770
|
+
return ctx.getBlockUsersGate();
|
|
19771
|
+
case "attachments":
|
|
19772
|
+
return ctx.getAttachmentsGate();
|
|
19773
|
+
case "groupCreation":
|
|
19774
|
+
return ctx.getGroupCreationGate();
|
|
19775
|
+
default: {
|
|
19776
|
+
const _exhaustive = feature;
|
|
19777
|
+
return _exhaustive;
|
|
19778
|
+
}
|
|
19779
|
+
}
|
|
19780
|
+
}
|
|
19781
|
+
|
|
19739
19782
|
// src/index.ts
|
|
19740
19783
|
init_settings_types();
|
|
19741
19784
|
init_api_service();
|
|
19742
19785
|
var index_default = ChatMain_default;
|
|
19743
19786
|
|
|
19787
|
+
exports.AdminPermissionTooltip = AdminPermissionTooltip;
|
|
19744
19788
|
exports.Calendar = Calendar;
|
|
19745
19789
|
exports.CalendarDayButton = CalendarDayButton;
|
|
19746
19790
|
exports.Channel = Channel;
|
|
@@ -19823,6 +19867,7 @@ exports.smoothScrollToMessage = smoothScrollToMessage;
|
|
|
19823
19867
|
exports.startOfLocalDay = startOfLocalDay;
|
|
19824
19868
|
exports.toDateInputValue = toDateInputValue;
|
|
19825
19869
|
exports.uniqueList = uniqueList;
|
|
19870
|
+
exports.useAdminFeatureGate = useAdminFeatureGate;
|
|
19826
19871
|
exports.useChatAlerts = useChatAlerts;
|
|
19827
19872
|
exports.useChatContext = useChatContext;
|
|
19828
19873
|
exports.useChatController = useChatController;
|