@stream-io/video-react-sdk 0.0.91 → 0.1.0
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/CHANGELOG.md +32 -15
- package/dist/src/components/CallControls/ReactionsButton.js +3 -2
- package/dist/src/components/CallControls/ReactionsButton.js.map +1 -1
- package/dist/src/components/CallControls/RecordCallButton.js +7 -40
- package/dist/src/components/CallControls/RecordCallButton.js.map +1 -1
- package/dist/src/components/CallControls/ScreenShareButton.js +6 -46
- package/dist/src/components/CallControls/ScreenShareButton.js.map +1 -1
- package/dist/src/components/CallControls/ToggleAudioButton.js +2 -2
- package/dist/src/components/CallControls/ToggleAudioButton.js.map +1 -1
- package/dist/src/components/CallControls/ToggleVideoButton.js +2 -2
- package/dist/src/components/CallControls/ToggleVideoButton.js.map +1 -1
- package/dist/src/components/Permissions/PermissionRequests.d.ts +3 -1
- package/dist/src/components/Permissions/PermissionRequests.js +25 -13
- package/dist/src/components/Permissions/PermissionRequests.js.map +1 -1
- package/dist/src/hooks/index.d.ts +3 -0
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/hooks/useRequestPermission.d.ts +7 -0
- package/dist/src/hooks/useRequestPermission.js +52 -0
- package/dist/src/hooks/useRequestPermission.js.map +1 -0
- package/dist/src/hooks/useToggleAudioMuteState.d.ts +1 -1
- package/dist/src/hooks/useToggleAudioMuteState.js +14 -41
- package/dist/src/hooks/useToggleAudioMuteState.js.map +1 -1
- package/dist/src/hooks/useToggleCallRecording.d.ts +5 -0
- package/dist/src/hooks/useToggleCallRecording.js +43 -0
- package/dist/src/hooks/useToggleCallRecording.js.map +1 -0
- package/dist/src/hooks/useToggleScreenShare.d.ts +5 -0
- package/dist/src/hooks/useToggleScreenShare.js +37 -0
- package/dist/src/hooks/useToggleScreenShare.js.map +1 -0
- package/dist/src/hooks/useToggleVideoMuteState.d.ts +1 -1
- package/dist/src/hooks/useToggleVideoMuteState.js +14 -41
- package/dist/src/hooks/useToggleVideoMuteState.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -4
- package/src/components/CallControls/ReactionsButton.tsx +5 -3
- package/src/components/CallControls/RecordCallButton.tsx +9 -33
- package/src/components/CallControls/ScreenShareButton.tsx +13 -51
- package/src/components/CallControls/ToggleAudioButton.tsx +5 -5
- package/src/components/CallControls/ToggleVideoButton.tsx +7 -5
- package/src/components/Permissions/PermissionRequests.tsx +49 -22
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useRequestPermission.ts +48 -0
- package/src/hooks/useToggleAudioMuteState.ts +19 -48
- package/src/hooks/useToggleCallRecording.ts +39 -0
- package/src/hooks/useToggleScreenShare.ts +42 -0
- package/src/hooks/useToggleVideoMuteState.ts +19 -48
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { OwnCapability } from '@stream-io/video-client';
|
|
3
|
+
import { useCall, useHasPermissions } from '@stream-io/video-react-bindings';
|
|
4
|
+
|
|
5
|
+
export const useRequestPermission = (permission: OwnCapability) => {
|
|
6
|
+
const call = useCall();
|
|
7
|
+
const hasPermission = useHasPermissions(permission);
|
|
8
|
+
const canRequestPermission =
|
|
9
|
+
!!call?.permissionsContext.canRequest(permission);
|
|
10
|
+
const [isAwaitingPermission, setIsAwaitingPermission] = useState(false); // TODO: load with possibly pending state
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const reset = () => setIsAwaitingPermission(false);
|
|
14
|
+
|
|
15
|
+
if (hasPermission) reset();
|
|
16
|
+
}, [hasPermission]);
|
|
17
|
+
|
|
18
|
+
const requestPermission = useCallback(async () => {
|
|
19
|
+
if (isAwaitingPermission || !canRequestPermission) return false;
|
|
20
|
+
if (hasPermission) return true;
|
|
21
|
+
|
|
22
|
+
setIsAwaitingPermission(true);
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
await call?.requestPermissions({
|
|
26
|
+
permissions: [permission],
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
setIsAwaitingPermission(false);
|
|
30
|
+
throw new Error(`requestPermission failed: ${error}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return false;
|
|
34
|
+
}, [
|
|
35
|
+
call,
|
|
36
|
+
canRequestPermission,
|
|
37
|
+
hasPermission,
|
|
38
|
+
isAwaitingPermission,
|
|
39
|
+
permission,
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
requestPermission,
|
|
44
|
+
hasPermission,
|
|
45
|
+
canRequestPermission,
|
|
46
|
+
isAwaitingPermission,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
@@ -1,62 +1,33 @@
|
|
|
1
|
-
import { useCallback,
|
|
2
|
-
import {
|
|
3
|
-
useCall,
|
|
4
|
-
useHasPermissions,
|
|
5
|
-
useLocalParticipant,
|
|
6
|
-
} from '@stream-io/video-react-bindings';
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { useLocalParticipant } from '@stream-io/video-react-bindings';
|
|
7
3
|
import { OwnCapability, SfuModels } from '@stream-io/video-client';
|
|
8
4
|
|
|
9
5
|
import { useMediaDevices } from '../core';
|
|
6
|
+
import { useRequestPermission } from './useRequestPermission';
|
|
10
7
|
|
|
11
8
|
export const useToggleAudioMuteState = () => {
|
|
12
9
|
const { publishAudioStream, stopPublishingAudio } = useMediaDevices();
|
|
13
10
|
const localParticipant = useLocalParticipant();
|
|
14
|
-
const call = useCall();
|
|
15
|
-
const hasPermission = useHasPermissions(OwnCapability.SEND_AUDIO);
|
|
16
|
-
const [isAwaitingApproval, setIsAwaitingApproval] = useState(false);
|
|
17
11
|
|
|
18
|
-
const
|
|
19
|
-
|
|
12
|
+
const { isAwaitingPermission, requestPermission } = useRequestPermission(
|
|
13
|
+
OwnCapability.SEND_AUDIO,
|
|
20
14
|
);
|
|
21
15
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
// to keep the toggle function as stable as possible
|
|
17
|
+
const isAudioMutedReference = useRef(false);
|
|
18
|
+
|
|
19
|
+
isAudioMutedReference.current = !localParticipant?.publishedTracks.includes(
|
|
20
|
+
SfuModels.TrackType.AUDIO,
|
|
21
|
+
);
|
|
27
22
|
|
|
28
23
|
const toggleAudioMuteState = useCallback(async () => {
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
call.permissionsContext.canRequest(OwnCapability.SEND_AUDIO)
|
|
33
|
-
) {
|
|
34
|
-
setIsAwaitingApproval(true);
|
|
35
|
-
await call
|
|
36
|
-
.requestPermissions({
|
|
37
|
-
permissions: [OwnCapability.SEND_AUDIO],
|
|
38
|
-
})
|
|
39
|
-
.catch((reason) => {
|
|
40
|
-
console.log('RequestPermissions failed', reason);
|
|
41
|
-
});
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (isAudioMute) {
|
|
45
|
-
if (hasPermission) {
|
|
46
|
-
await publishAudioStream();
|
|
47
|
-
} else {
|
|
48
|
-
console.log('Cannot publish audio stream. Insufficient permissions.');
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
stopPublishingAudio();
|
|
24
|
+
if (isAudioMutedReference.current) {
|
|
25
|
+
const canPublish = await requestPermission();
|
|
26
|
+
if (canPublish) return publishAudioStream();
|
|
52
27
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
stopPublishingAudio,
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
return { toggleAudioMuteState, isAwaitingApproval };
|
|
28
|
+
|
|
29
|
+
if (!isAudioMutedReference.current) stopPublishingAudio();
|
|
30
|
+
}, [publishAudioStream, requestPermission, stopPublishingAudio]);
|
|
31
|
+
|
|
32
|
+
return { toggleAudioMuteState, isAwaitingPermission };
|
|
62
33
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
useCall,
|
|
5
|
+
useIsCallRecordingInProgress,
|
|
6
|
+
} from '@stream-io/video-react-bindings';
|
|
7
|
+
|
|
8
|
+
export const useToggleCallRecording = () => {
|
|
9
|
+
const call = useCall();
|
|
10
|
+
const isCallRecordingInProgress = useIsCallRecordingInProgress();
|
|
11
|
+
const [isAwaitingResponse, setIsAwaitingResponse] = useState(false);
|
|
12
|
+
|
|
13
|
+
// TODO: add permissions
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
// we wait until call.recording_started/stopped event to flips the
|
|
17
|
+
// `isCallRecordingInProgress` state variable.
|
|
18
|
+
// Once the flip happens, we remove the loading indicator
|
|
19
|
+
setIsAwaitingResponse((isAwaiting) => {
|
|
20
|
+
if (isAwaiting) return false;
|
|
21
|
+
return isAwaiting;
|
|
22
|
+
});
|
|
23
|
+
}, [isCallRecordingInProgress]);
|
|
24
|
+
|
|
25
|
+
const toggleCallRecording = useCallback(async () => {
|
|
26
|
+
try {
|
|
27
|
+
setIsAwaitingResponse(true);
|
|
28
|
+
if (isCallRecordingInProgress) {
|
|
29
|
+
await call?.stopRecording();
|
|
30
|
+
} else {
|
|
31
|
+
await call?.startRecording();
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.error(`Failed start recording`, e);
|
|
35
|
+
}
|
|
36
|
+
}, [call, isCallRecordingInProgress]);
|
|
37
|
+
|
|
38
|
+
return { toggleCallRecording, isAwaitingResponse, isCallRecordingInProgress };
|
|
39
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { useCall, useLocalParticipant } from '@stream-io/video-react-bindings';
|
|
3
|
+
import {
|
|
4
|
+
OwnCapability,
|
|
5
|
+
SfuModels,
|
|
6
|
+
getScreenShareStream,
|
|
7
|
+
} from '@stream-io/video-client';
|
|
8
|
+
import { useRequestPermission } from './useRequestPermission';
|
|
9
|
+
|
|
10
|
+
export const useToggleScreenShare = () => {
|
|
11
|
+
const localParticipant = useLocalParticipant();
|
|
12
|
+
const call = useCall();
|
|
13
|
+
const isScreenSharingReference = useRef(false);
|
|
14
|
+
const { isAwaitingPermission, requestPermission } = useRequestPermission(
|
|
15
|
+
OwnCapability.SCREENSHARE,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const isScreenSharing = !!localParticipant?.publishedTracks.includes(
|
|
19
|
+
SfuModels.TrackType.SCREEN_SHARE,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
isScreenSharingReference.current = isScreenSharing;
|
|
23
|
+
|
|
24
|
+
const toggleScreenShare = useCallback(async () => {
|
|
25
|
+
if (!isScreenSharingReference.current) {
|
|
26
|
+
const canPublish = await requestPermission();
|
|
27
|
+
if (!canPublish) return;
|
|
28
|
+
|
|
29
|
+
const stream = await getScreenShareStream().catch((e) => {
|
|
30
|
+
console.log(`Can't share screen: ${e}`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (stream) {
|
|
34
|
+
return call?.publishScreenShareStream(stream);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
call?.stopPublish(SfuModels.TrackType.SCREEN_SHARE);
|
|
39
|
+
}, [call, requestPermission]);
|
|
40
|
+
|
|
41
|
+
return { toggleScreenShare, isAwaitingPermission, isScreenSharing };
|
|
42
|
+
};
|
|
@@ -1,62 +1,33 @@
|
|
|
1
|
-
import { useCallback,
|
|
2
|
-
import {
|
|
3
|
-
useCall,
|
|
4
|
-
useHasPermissions,
|
|
5
|
-
useLocalParticipant,
|
|
6
|
-
} from '@stream-io/video-react-bindings';
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import { useLocalParticipant } from '@stream-io/video-react-bindings';
|
|
7
3
|
import { OwnCapability, SfuModels } from '@stream-io/video-client';
|
|
8
4
|
|
|
9
5
|
import { useMediaDevices } from '../core';
|
|
6
|
+
import { useRequestPermission } from './useRequestPermission';
|
|
10
7
|
|
|
11
8
|
export const useToggleVideoMuteState = () => {
|
|
12
9
|
const { publishVideoStream, stopPublishingVideo } = useMediaDevices();
|
|
13
10
|
const localParticipant = useLocalParticipant();
|
|
14
|
-
const call = useCall();
|
|
15
|
-
const hasPermission = useHasPermissions(OwnCapability.SEND_VIDEO);
|
|
16
|
-
const [isAwaitingApproval, setIsAwaitingApproval] = useState(false);
|
|
17
11
|
|
|
18
|
-
const
|
|
19
|
-
|
|
12
|
+
const { isAwaitingPermission, requestPermission } = useRequestPermission(
|
|
13
|
+
OwnCapability.SEND_VIDEO,
|
|
20
14
|
);
|
|
21
15
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
// to keep the toggle function as stable as possible
|
|
17
|
+
const isVideoMutedReference = useRef(false);
|
|
18
|
+
|
|
19
|
+
isVideoMutedReference.current = !localParticipant?.publishedTracks.includes(
|
|
20
|
+
SfuModels.TrackType.VIDEO,
|
|
21
|
+
);
|
|
27
22
|
|
|
28
23
|
const toggleVideoMuteState = useCallback(async () => {
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
call.permissionsContext.canRequest(OwnCapability.SEND_VIDEO)
|
|
33
|
-
) {
|
|
34
|
-
setIsAwaitingApproval(true);
|
|
35
|
-
await call
|
|
36
|
-
.requestPermissions({
|
|
37
|
-
permissions: [OwnCapability.SEND_VIDEO],
|
|
38
|
-
})
|
|
39
|
-
.catch((reason) => {
|
|
40
|
-
console.log('RequestPermissions failed', reason);
|
|
41
|
-
});
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (isVideoMute) {
|
|
45
|
-
if (hasPermission) {
|
|
46
|
-
await publishVideoStream();
|
|
47
|
-
} else {
|
|
48
|
-
console.log('Cannot publish video. Insufficient permissions.');
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
stopPublishingVideo();
|
|
24
|
+
if (isVideoMutedReference.current) {
|
|
25
|
+
const canPublish = await requestPermission();
|
|
26
|
+
if (canPublish) return publishVideoStream();
|
|
52
27
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
stopPublishingVideo,
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
return { toggleVideoMuteState, isAwaitingApproval };
|
|
28
|
+
|
|
29
|
+
if (!isVideoMutedReference.current) stopPublishingVideo();
|
|
30
|
+
}, [publishVideoStream, requestPermission, stopPublishingVideo]);
|
|
31
|
+
|
|
32
|
+
return { toggleVideoMuteState, isAwaitingPermission };
|
|
62
33
|
};
|