diff --git a/packages/react-bindings/src/hooks/callStateHooks.ts b/packages/react-bindings/src/hooks/callStateHooks.ts
index 1acc23eae7..1c6ed58f7e 100644
--- a/packages/react-bindings/src/hooks/callStateHooks.ts
+++ b/packages/react-bindings/src/hooks/callStateHooks.ts
@@ -9,6 +9,7 @@ import {
Comparator,
EgressResponse,
MemberResponse,
+ OwnCapability,
StreamVideoParticipant,
UserResponse,
} from '@stream-io/video-client';
@@ -320,6 +321,24 @@ export const useCallThumbnail = () => {
return useObservableValue(thumbnails$);
};
+/**
+ * A hook which returns the local participant's own capabilities.
+ */
+export const useOwnCapabilities = (): OwnCapability[] | undefined => {
+ const { ownCapabilities$ } = useCallState();
+ return useObservableValue(ownCapabilities$);
+};
+
+/**
+ * Hook that returns true if the local participant has all the given permissions.
+ *
+ * @param permissions the permissions to check.
+ */
+export const useHasPermissions = (...permissions: OwnCapability[]): boolean => {
+ const capabilities = useOwnCapabilities();
+ return permissions.every((permission) => capabilities?.includes(permission));
+};
+
/**
* Returns the camera state of the current call.
*
diff --git a/packages/react-bindings/src/hooks/index.ts b/packages/react-bindings/src/hooks/index.ts
index aed7cb0f38..10dd1ca90c 100644
--- a/packages/react-bindings/src/hooks/index.ts
+++ b/packages/react-bindings/src/hooks/index.ts
@@ -1,6 +1,5 @@
import * as CallStateHooks from './callStateHooks';
-export * from './permissions';
export * from './store';
/**
diff --git a/packages/react-bindings/src/hooks/permissions.ts b/packages/react-bindings/src/hooks/permissions.ts
deleted file mode 100644
index 13eac30983..0000000000
--- a/packages/react-bindings/src/hooks/permissions.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { OwnCapability } from '@stream-io/video-client';
-import { useCallState } from './callStateHooks';
-import { useObservableValue } from './useObservableValue';
-
-/**
- * Hook that returns true if the local participant has all the given permissions.
- *
- * @param permissions the permissions to check.
- *
- * @category Call State
- */
-export const useHasPermissions = (...permissions: OwnCapability[]): boolean => {
- const capabilities = useOwnCapabilities();
- return permissions.every((permission) => capabilities?.includes(permission));
-};
-
-/**
- * A hook which returns the local participant's own capabilities.
- *
- * @category Call State
- */
-export const useOwnCapabilities = (): OwnCapability[] | undefined => {
- const { ownCapabilities$ } = useCallState();
- return useObservableValue(ownCapabilities$);
-};
diff --git a/packages/react-bindings/src/wrappers/Restricted.tsx b/packages/react-bindings/src/wrappers/Restricted.tsx
index a0ff5b5b08..5b60ad619a 100644
--- a/packages/react-bindings/src/wrappers/Restricted.tsx
+++ b/packages/react-bindings/src/wrappers/Restricted.tsx
@@ -2,7 +2,7 @@ import { OwnCapability } from '@stream-io/video-client';
import { PropsWithChildren } from 'react';
import { useCall } from '../contexts';
-import { useCallStateHooks, useOwnCapabilities } from '../hooks';
+import { useCallStateHooks } from '../hooks';
type RestrictedProps = PropsWithChildren<{
/**
@@ -32,8 +32,8 @@ export const Restricted = ({
children,
}: RestrictedProps) => {
const call = useCall();
+ const { useCallSettings, useOwnCapabilities } = useCallStateHooks();
const ownCapabilities = useOwnCapabilities();
- const { useCallSettings } = useCallStateHooks();
const settings = useCallSettings();
const hasPermissions = requiredGrants[requireAll ? 'every' : 'some'](
(capability) => ownCapabilities?.includes(capability),
diff --git a/packages/react-native-sdk/docusaurus/docs/reactnative/03-core/09-permissions-and-moderation.mdx b/packages/react-native-sdk/docusaurus/docs/reactnative/03-core/09-permissions-and-moderation.mdx
index c289c14787..cedaf0560a 100644
--- a/packages/react-native-sdk/docusaurus/docs/reactnative/03-core/09-permissions-and-moderation.mdx
+++ b/packages/react-native-sdk/docusaurus/docs/reactnative/03-core/09-permissions-and-moderation.mdx
@@ -3,9 +3,6 @@ title: Permissions & Moderation
description: Explanation of call permissions and moderation features
---
-import SDKSpecific from '../SDKSpecific';
-
-
In many types of calls, there is a requirement for providing different users with certain permissions and capabilities.
A typical example is a webinar where the host wants to control who can speak or who can share their video or screen.
@@ -37,7 +34,7 @@ or perform some permission-related actions:
### Check permissions
```ts
-import { OwnCapability } from '@stream-io/video-client';
+import { OwnCapability } from '@stream-io/video-react-native-sdk';
const call = streamVideoClient.call(type, id);
const canSendAudio = call.permissionsContext.hasPermission(
@@ -48,8 +45,12 @@ const canSendAudio = call.permissionsContext.hasPermission(
In our React Native Video SDK, you can use the `useHasPermissions` hook to check for permissions.
```tsx
-import { useHasPermissions, OwnCapability } from '@stream-io/video-react-native-sdk';
+import {
+ useCallStateHooks,
+ OwnCapability,
+} from '@stream-io/video-react-native-sdk';
+const { useHasPermissions } = useCallStateHooks();
const canSendAudio = useHasPermissions(OwnCapability.SEND_AUDIO);
```
@@ -170,14 +171,13 @@ const call = streamVideoClient.call(type, id);
const { own_capabilities } = call.state.metadata;
```
-
-
-In our React Video SDK, you can use the `useOwnCapabilities` hook.
+In our React Native Video SDK, you can use the `useOwnCapabilities` hook.
```tsx
+import { useCallStateHooks } from '@stream-io/video-react-bindings';
+
+const { useOwnCapabilities } = useCallStateHooks();
const ownCapabilities = useOwnCapabilities();
```
-
-
Capabilities will have the type [`OwnCapability`](https://github.com/GetStream/stream-video-js/blob/main/packages/client/src/gen/coordinator/index.ts).
diff --git a/packages/react-native-sdk/src/hooks/usePermissionNotification.tsx b/packages/react-native-sdk/src/hooks/usePermissionNotification.tsx
index a5d0eed5da..a9f5127e17 100644
--- a/packages/react-native-sdk/src/hooks/usePermissionNotification.tsx
+++ b/packages/react-native-sdk/src/hooks/usePermissionNotification.tsx
@@ -1,8 +1,5 @@
import { CallingState, OwnCapability } from '@stream-io/video-client';
-import {
- useCallStateHooks,
- useHasPermissions,
-} from '@stream-io/video-react-bindings';
+import { useCallStateHooks } from '@stream-io/video-react-bindings';
import { useCallback, useEffect } from 'react';
import { Alert } from 'react-native';
import { usePrevious } from '../utils/hooks/usePrevious';
@@ -30,9 +27,9 @@ export const usePermissionNotification = (
props: PermissionNotificationProps,
) => {
const { permission, messageApproved, messageRevoked } = props;
+ const { useCallCallingState, useHasPermissions } = useCallStateHooks();
const hasPermission = useHasPermissions(permission);
const previousHasPermission = usePrevious(hasPermission);
- const { useCallCallingState } = useCallStateHooks();
const callingState = useCallCallingState();
const showGrantedNotification = useCallback(() => {
diff --git a/packages/react-native-sdk/src/hooks/usePermissionRequest.tsx b/packages/react-native-sdk/src/hooks/usePermissionRequest.tsx
index 19aab8d8c3..7e440f5753 100644
--- a/packages/react-native-sdk/src/hooks/usePermissionRequest.tsx
+++ b/packages/react-native-sdk/src/hooks/usePermissionRequest.tsx
@@ -1,11 +1,12 @@
import { OwnCapability, PermissionRequestEvent } from '@stream-io/video-client';
-import { useCall, useHasPermissions } from '@stream-io/video-react-bindings';
+import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
import { useCallback, useEffect } from 'react';
import { Alert } from 'react-native';
export const usePermissionRequest = () => {
const call = useCall();
+ const { useHasPermissions } = useCallStateHooks();
const userHasUpdateCallPermissionsCapability = useHasPermissions(
OwnCapability.UPDATE_CALL_PERMISSIONS,
);
diff --git a/packages/react-sdk/docusaurus/docs/React/02-guides/08-permissions-and-moderation.mdx b/packages/react-sdk/docusaurus/docs/React/02-guides/08-permissions-and-moderation.mdx
index 36e6687186..2748d4518c 100644
--- a/packages/react-sdk/docusaurus/docs/React/02-guides/08-permissions-and-moderation.mdx
+++ b/packages/react-sdk/docusaurus/docs/React/02-guides/08-permissions-and-moderation.mdx
@@ -3,8 +3,6 @@ title: Permissions & Moderation
description: Explanation of call permissions and moderation features
---
-import SDKSpecific from '../SDKSpecific';
-
In many types of calls, there is a requirement for providing different users with certain permissions and capabilities.
A typical example is a webinar where the host wants to control who can speak or who can share their video or screen.
@@ -44,16 +42,15 @@ const canSendAudio = call.permissionsContext.hasPermission(
);
```
-
-
In our React Video SDK, you can use the `useHasPermissions` hook to check for permissions.
```tsx
+import { useCallStateHooks } from '@stream-io/video-react-sdk';
+
+const { useHasPermissions } = useCallStateHooks();
const canSendAudio = useHasPermissions(OwnCapability.SEND_AUDIO);
```
-
-
### Request permissions
Every user may request permission to perform certain actions depending on the call type and call settings.
@@ -171,14 +168,13 @@ const call = client.call(type, id);
const { ownCapabilities } = call.state;
```
-
-
In our React Video SDK, you can use the `useOwnCapabilities` hook.
```tsx
+import { useCallStateHooks } from '@stream-io/video-react-sdk';
+
+const { useOwnCapabilities } = useCallStateHooks();
const ownCapabilities = useOwnCapabilities();
```
-
-
Capabilities will have the type [`OwnCapability`](https://github.com/GetStream/stream-video-js/blob/main/packages/client/src/gen/coordinator/index.ts).
diff --git a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/08-permission-requests.mdx b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/08-permission-requests.mdx
index 6aaa2bf72d..f02f9ea53e 100644
--- a/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/08-permission-requests.mdx
+++ b/packages/react-sdk/docusaurus/docs/React/06-ui-cookbook/08-permission-requests.mdx
@@ -96,7 +96,7 @@ For readability the code snippet only contains the `MyPermissionRequests` and th
```tsx
import {
useRequestPermission,
- useHasPermissions,
+ useCallStateHooks,
OwnCapability,
} from '@stream-io/video-react-sdk';
@@ -119,6 +119,7 @@ const MyPermissionRequestButton = ({ children, capability }) => {
const MyPermissionRequests = () => {
const call = useCall();
+ const { useHasPermissions } = useCallStateHooks();
const canSendAudio = useHasPermissions(OwnCapability.SEND_AUDIO);
const canSendVideo = useHasPermissions(OwnCapability.SEND_VIDEO);
const canShareScreen = useHasPermissions(OwnCapability.SCREENSHARE);
@@ -163,7 +164,7 @@ For readability, the code snippet only contains the `MyPermissionRequestNotifica
```tsx
const MyPermissionRequestNotifications = () => {
const call = useCall();
- const { useLocalParticipant } = useCallStateHooks();
+ const { useLocalParticipant, useHasPermissions } = useCallStateHooks();
const localParticipant = useLocalParticipant();
const canUpdateCallPermissions = useHasPermissions(
OwnCapability.UPDATE_CALL_PERMISSIONS,
@@ -245,7 +246,6 @@ import {
useCall,
useCallStateHooks,
useRequestPermission,
- useHasPermissions,
} from '@stream-io/video-react-sdk';
import '@stream-io/video-react-sdk/dist/css/styles.css';
import { useEffect, useState } from 'react';
@@ -296,6 +296,7 @@ const MyPermissionRequestButton = ({ children, capability }) => {
const MyPermissionRequests = () => {
const call = useCall();
+ const { useHasPermissions } = useCallStateHooks();
const canSendAudio = useHasPermissions(OwnCapability.SEND_AUDIO);
const canSendVideo = useHasPermissions(OwnCapability.SEND_VIDEO);
const canShareScreen = useHasPermissions(OwnCapability.SCREENSHARE);
@@ -326,7 +327,7 @@ const MyPermissionRequests = () => {
const MyPermissionRequestNotifications = () => {
const call = useCall();
- const { useLocalParticipant } = useCallStateHooks();
+ const { useLocalParticipant, useHasPermissions } = useCallStateHooks();
const localParticipant = useLocalParticipant();
const canUpdateCallPermissions = useHasPermissions(
OwnCapability.UPDATE_CALL_PERMISSIONS,
diff --git a/packages/react-sdk/src/components/Notification/PermissionNotification.tsx b/packages/react-sdk/src/components/Notification/PermissionNotification.tsx
index f41e2ad065..025522bca2 100644
--- a/packages/react-sdk/src/components/Notification/PermissionNotification.tsx
+++ b/packages/react-sdk/src/components/Notification/PermissionNotification.tsx
@@ -7,7 +7,7 @@ import {
useRef,
useState,
} from 'react';
-import { useHasPermissions } from '@stream-io/video-react-bindings';
+import { useCallStateHooks } from '@stream-io/video-react-bindings';
export type PermissionNotificationProps = PropsWithChildren<{
/**
@@ -55,6 +55,7 @@ export const PermissionNotification = (props: PermissionNotificationProps) => {
visibilityTimeout = 3500,
children,
} = props;
+ const { useHasPermissions } = useCallStateHooks();
const hasPermission = useHasPermissions(permission);
const prevHasPermission = useRef(hasPermission);
const [showNotification, setShowNotification] = useState<
diff --git a/packages/react-sdk/src/components/Permissions/PermissionRequests.tsx b/packages/react-sdk/src/components/Permissions/PermissionRequests.tsx
index c1428e3a64..c797323f63 100644
--- a/packages/react-sdk/src/components/Permissions/PermissionRequests.tsx
+++ b/packages/react-sdk/src/components/Permissions/PermissionRequests.tsx
@@ -16,7 +16,6 @@ import {
TranslatorFunction,
useCall,
useCallStateHooks,
- useHasPermissions,
useI18n,
} from '@stream-io/video-react-bindings';
import clsx from 'clsx';
@@ -38,7 +37,7 @@ type HandleUpdatePermission = (
export const PermissionRequests = () => {
const call = useCall();
- const { useLocalParticipant } = useCallStateHooks();
+ const { useLocalParticipant, useHasPermissions } = useCallStateHooks();
const localParticipant = useLocalParticipant();
const [expanded, setExpanded] = useState(false);
const [permissionRequests, setPermissionRequests] = useState<
diff --git a/packages/react-sdk/src/hooks/useRequestPermission.ts b/packages/react-sdk/src/hooks/useRequestPermission.ts
index fbdcd526bd..ca104131c1 100644
--- a/packages/react-sdk/src/hooks/useRequestPermission.ts
+++ b/packages/react-sdk/src/hooks/useRequestPermission.ts
@@ -1,9 +1,10 @@
import { useCallback, useEffect, useState } from 'react';
import { OwnCapability } from '@stream-io/video-client';
-import { useCall, useHasPermissions } from '@stream-io/video-react-bindings';
+import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
export const useRequestPermission = (permission: OwnCapability) => {
const call = useCall();
+ const { useHasPermissions } = useCallStateHooks();
const hasPermission = useHasPermissions(permission);
const [isAwaitingPermission, setIsAwaitingPermission] = useState(false); // TODO: load with possibly pending state
diff --git a/sample-apps/react-native/dogfood/src/components/AudioRoom/PermissionRequestsPanel.tsx b/sample-apps/react-native/dogfood/src/components/AudioRoom/PermissionRequestsPanel.tsx
index ce07cbd616..eb4c6903b5 100644
--- a/sample-apps/react-native/dogfood/src/components/AudioRoom/PermissionRequestsPanel.tsx
+++ b/sample-apps/react-native/dogfood/src/components/AudioRoom/PermissionRequestsPanel.tsx
@@ -2,7 +2,7 @@ import {
OwnCapability,
PermissionRequestEvent,
useCall,
- useHasPermissions,
+ useCallStateHooks,
useI18n,
} from '@stream-io/video-react-native-sdk';
import React, { useEffect, useState } from 'react';
@@ -12,6 +12,7 @@ export const PermissionRequestsPanel = () => {
const call = useCall();
const { t } = useI18n();
+ const { useHasPermissions } = useCallStateHooks();
const canUpdatePermissions = useHasPermissions(
OwnCapability.UPDATE_CALL_PERMISSIONS,
);
diff --git a/sample-apps/react-native/dogfood/src/components/AudioRoom/ToggleAudioButton.tsx b/sample-apps/react-native/dogfood/src/components/AudioRoom/ToggleAudioButton.tsx
index de23193295..5f50a27d99 100644
--- a/sample-apps/react-native/dogfood/src/components/AudioRoom/ToggleAudioButton.tsx
+++ b/sample-apps/react-native/dogfood/src/components/AudioRoom/ToggleAudioButton.tsx
@@ -4,7 +4,6 @@ import {
useCall,
useCallStateHooks,
useConnectedUser,
- useHasPermissions,
useIncallManager,
} from '@stream-io/video-react-native-sdk';
import React, { useEffect, useState } from 'react';
@@ -15,7 +14,7 @@ export default function ToggleAudioButton() {
const call = useCall();
const connectedUser = useConnectedUser();
- const { useLocalParticipant } = useCallStateHooks();
+ const { useLocalParticipant, useHasPermissions } = useCallStateHooks();
const localParticipant = useLocalParticipant();
const isMuted = !localParticipant?.publishedTracks.includes(
SfuModels.TrackType.AUDIO,
diff --git a/sample-apps/react-native/dogfood/src/components/ParticipantActions.tsx b/sample-apps/react-native/dogfood/src/components/ParticipantActions.tsx
index 4d67681520..fe8fdfdb34 100644
--- a/sample-apps/react-native/dogfood/src/components/ParticipantActions.tsx
+++ b/sample-apps/react-native/dogfood/src/components/ParticipantActions.tsx
@@ -14,11 +14,11 @@ import { VideoSlash } from '../assets/VideoSlash';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import React, { useCallback } from 'react';
import {
- useCall,
- useHasPermissions,
- useI18n,
Avatar,
colorPallet,
+ useCall,
+ useCallStateHooks,
+ useI18n,
} from '@stream-io/video-react-native-sdk';
import { generateParticipantTitle } from '../utils';
@@ -39,6 +39,7 @@ export const ParticipantActions = (props: ParticipantActionsType) => {
const { participant, setSelectedParticipant } = props;
const call = useCall();
const { t } = useI18n();
+ const { useHasPermissions } = useCallStateHooks();
const userHasMuteUsersCapability = useHasPermissions(
OwnCapability.MUTE_USERS,
);
diff --git a/sample-apps/react/audio-rooms/src/components/Room/LiveRoomControls.tsx b/sample-apps/react/audio-rooms/src/components/Room/LiveRoomControls.tsx
index b138693734..f4c562e25b 100644
--- a/sample-apps/react/audio-rooms/src/components/Room/LiveRoomControls.tsx
+++ b/sample-apps/react/audio-rooms/src/components/Room/LiveRoomControls.tsx
@@ -6,7 +6,6 @@ import {
useCall,
useCallStateHooks,
useConnectedUser,
- useHasPermissions,
} from '@stream-io/video-react-sdk';
import { useCallback, useEffect, useState } from 'react';
import {
@@ -27,8 +26,12 @@ export const LiveRoomControls = ({
openRequestsList,
}: LiveRoomControlsProps) => {
const call = useCall();
- const { useCallCustomData, useCallCallingState, useLocalParticipant } =
- useCallStateHooks();
+ const {
+ useCallCustomData,
+ useCallCallingState,
+ useLocalParticipant,
+ useHasPermissions,
+ } = useCallStateHooks();
const customData = useCallCustomData();
const callingState = useCallCallingState();
const connectedUser = useConnectedUser();
diff --git a/sample-apps/react/audio-rooms/src/components/Room/RoomUI.tsx b/sample-apps/react/audio-rooms/src/components/Room/RoomUI.tsx
index 93d8df30f4..4967607861 100644
--- a/sample-apps/react/audio-rooms/src/components/Room/RoomUI.tsx
+++ b/sample-apps/react/audio-rooms/src/components/Room/RoomUI.tsx
@@ -6,7 +6,6 @@ import {
StreamVideoParticipant,
useCall,
useCallStateHooks,
- useHasPermissions,
} from '@stream-io/video-react-sdk';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { ChatIcon, CloseIcon, ListIcon, PersonIcon } from '../icons';
@@ -35,6 +34,7 @@ export const RoomUI = ({ loadRoom }: RoomUIProps) => {
useParticipants,
useCallEndedAt,
useIsCallLive,
+ useHasPermissions,
} = useCallStateHooks();
const customData = useCallCustomData();
const endedAt = useCallEndedAt();
diff --git a/sample-apps/react/audio-rooms/src/components/Room/SpeakerElement.tsx b/sample-apps/react/audio-rooms/src/components/Room/SpeakerElement.tsx
index 9bb1acb1c3..4427dd2f38 100644
--- a/sample-apps/react/audio-rooms/src/components/Room/SpeakerElement.tsx
+++ b/sample-apps/react/audio-rooms/src/components/Room/SpeakerElement.tsx
@@ -6,7 +6,6 @@ import {
StreamVideoParticipant,
useCall,
useCallStateHooks,
- useHasPermissions,
} from '@stream-io/video-react-sdk';
import { CloseIcon, MuteMicrophoneIcon } from '../icons';
import type { CustomCallData } from '../../types';
@@ -17,7 +16,7 @@ export const SpeakerElement = ({
speaker: StreamVideoParticipant;
}) => {
const call = useCall();
- const { useCallCustomData } = useCallStateHooks();
+ const { useCallCustomData, useHasPermissions } = useCallStateHooks();
const customData = useCallCustomData();
const canMuteUsers = useHasPermissions(OwnCapability.MUTE_USERS);
diff --git a/sample-apps/react/audio-rooms/src/hooks/useSpeakingRequests.ts b/sample-apps/react/audio-rooms/src/hooks/useSpeakingRequests.ts
index 7044173b1d..0606903f88 100644
--- a/sample-apps/react/audio-rooms/src/hooks/useSpeakingRequests.ts
+++ b/sample-apps/react/audio-rooms/src/hooks/useSpeakingRequests.ts
@@ -3,11 +3,12 @@ import {
OwnCapability,
PermissionRequestEvent,
useCall,
- useHasPermissions,
+ useCallStateHooks,
} from '@stream-io/video-react-sdk';
export const useSpeakingRequests = () => {
const call = useCall();
+ const { useHasPermissions } = useCallStateHooks();
const canUpdatePermissions = useHasPermissions(
OwnCapability.UPDATE_CALL_PERMISSIONS,
);