@stream-io/video-react-native-sdk 0.2.0 → 0.2.1
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 +7 -0
- package/dist/commonjs/components/Call/CallControls/ScreenShareButton.js +120 -0
- package/dist/commonjs/components/Call/CallControls/ScreenShareButton.js.map +1 -0
- package/dist/commonjs/components/Call/CallControls/index.js +11 -0
- package/dist/commonjs/components/Call/CallControls/index.js.map +1 -1
- package/dist/commonjs/components/Participant/ParticipantView/ParticipantLabel.js +5 -4
- package/dist/commonjs/components/Participant/ParticipantView/ParticipantLabel.js.map +1 -1
- package/dist/commonjs/components/Participant/ParticipantView/VideoRenderer.js +1 -1
- package/dist/commonjs/components/Participant/ParticipantView/VideoRenderer.js.map +1 -1
- package/dist/commonjs/constants/TestIds.js +1 -0
- package/dist/commonjs/constants/TestIds.js.map +1 -1
- package/dist/commonjs/hooks/index.js +11 -0
- package/dist/commonjs/hooks/index.js.map +1 -1
- package/dist/commonjs/hooks/useIsIosScreenshareBroadcastStarted.js +25 -0
- package/dist/commonjs/hooks/useIsIosScreenshareBroadcastStarted.js.map +1 -0
- package/dist/commonjs/icons/ScreenShare.js +2 -14
- package/dist/commonjs/icons/ScreenShare.js.map +1 -1
- package/dist/commonjs/icons/ScreenShareIndicator.js +38 -0
- package/dist/commonjs/icons/ScreenShareIndicator.js.map +1 -0
- package/dist/commonjs/icons/index.js +11 -0
- package/dist/commonjs/icons/index.js.map +1 -1
- package/dist/commonjs/theme/theme.js +4 -0
- package/dist/commonjs/theme/theme.js.map +1 -1
- package/dist/commonjs/translations/en.json +1 -0
- package/dist/commonjs/version.js +1 -1
- package/dist/module/components/Call/CallControls/ScreenShareButton.js +112 -0
- package/dist/module/components/Call/CallControls/ScreenShareButton.js.map +1 -0
- package/dist/module/components/Call/CallControls/index.js +1 -0
- package/dist/module/components/Call/CallControls/index.js.map +1 -1
- package/dist/module/components/Participant/ParticipantView/ParticipantLabel.js +6 -5
- package/dist/module/components/Participant/ParticipantView/ParticipantLabel.js.map +1 -1
- package/dist/module/components/Participant/ParticipantView/VideoRenderer.js +1 -1
- package/dist/module/components/Participant/ParticipantView/VideoRenderer.js.map +1 -1
- package/dist/module/constants/TestIds.js +1 -0
- package/dist/module/constants/TestIds.js.map +1 -1
- package/dist/module/hooks/index.js +1 -0
- package/dist/module/hooks/index.js.map +1 -1
- package/dist/module/hooks/useIsIosScreenshareBroadcastStarted.js +19 -0
- package/dist/module/hooks/useIsIosScreenshareBroadcastStarted.js.map +1 -0
- package/dist/module/icons/ScreenShare.js +3 -15
- package/dist/module/icons/ScreenShare.js.map +1 -1
- package/dist/module/icons/ScreenShareIndicator.js +28 -0
- package/dist/module/icons/ScreenShareIndicator.js.map +1 -0
- package/dist/module/icons/index.js +1 -0
- package/dist/module/icons/index.js.map +1 -1
- package/dist/module/theme/theme.js +4 -0
- package/dist/module/theme/theme.js.map +1 -1
- package/dist/module/translations/en.json +1 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/components/Call/CallControls/ScreenShareButton.d.ts +22 -0
- package/dist/typescript/components/Call/CallControls/ScreenShareButton.d.ts.map +1 -0
- package/dist/typescript/components/Call/CallControls/index.d.ts +1 -0
- package/dist/typescript/components/Call/CallControls/index.d.ts.map +1 -1
- package/dist/typescript/components/Participant/ParticipantView/ParticipantLabel.d.ts.map +1 -1
- package/dist/typescript/components/Participant/ParticipantView/VideoRenderer.d.ts.map +1 -1
- package/dist/typescript/constants/TestIds.d.ts +1 -0
- package/dist/typescript/constants/TestIds.d.ts.map +1 -1
- package/dist/typescript/hooks/index.d.ts +1 -0
- package/dist/typescript/hooks/index.d.ts.map +1 -1
- package/dist/typescript/hooks/useIsIosScreenshareBroadcastStarted.d.ts +2 -0
- package/dist/typescript/hooks/useIsIosScreenshareBroadcastStarted.d.ts.map +1 -0
- package/dist/typescript/icons/ScreenShare.d.ts.map +1 -1
- package/dist/typescript/icons/ScreenShareIndicator.d.ts +8 -0
- package/dist/typescript/icons/ScreenShareIndicator.d.ts.map +1 -0
- package/dist/typescript/icons/index.d.ts +1 -0
- package/dist/typescript/icons/index.d.ts.map +1 -1
- package/dist/typescript/theme/theme.d.ts +4 -0
- package/dist/typescript/theme/theme.d.ts.map +1 -1
- package/dist/typescript/translations/index.d.ts +1 -0
- package/dist/typescript/translations/index.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/expo-config-plugin/dist/common/types.d.ts +2 -0
- package/expo-config-plugin/dist/index.js +2 -0
- package/expo-config-plugin/dist/withAndroidManifest.js +9 -5
- package/expo-config-plugin/dist/withBuildProperties.d.ts +2 -2
- package/expo-config-plugin/dist/withBuildProperties.js +2 -2
- package/expo-config-plugin/dist/withIosScreenCapture/addBroadcastExtensionXcodeTarget.d.ts +11 -0
- package/expo-config-plugin/dist/withIosScreenCapture/addBroadcastExtensionXcodeTarget.js +225 -0
- package/expo-config-plugin/dist/withIosScreenCapture/index.d.ts +4 -0
- package/expo-config-plugin/dist/withIosScreenCapture/index.js +20 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withFilesMod.d.ts +4 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withFilesMod.js +71 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withPlistUpdates.d.ts +4 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withPlistUpdates.js +33 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withTarget.d.ts +4 -0
- package/expo-config-plugin/dist/withIosScreenCapture/withTarget.js +122 -0
- package/expo-config-plugin/static/Atomic.swift +36 -0
- package/expo-config-plugin/static/DarwinNotificationCenter.swift +25 -0
- package/expo-config-plugin/static/SampleHandler.swift +99 -0
- package/expo-config-plugin/static/SampleUploader.swift +143 -0
- package/expo-config-plugin/static/SocketConnection.swift +195 -0
- package/ios/StreamVideoReactNative-Bridging-Header.h +2 -1
- package/ios/StreamVideoReactNative.h +4 -2
- package/ios/StreamVideoReactNative.m +82 -1
- package/ios/StreamVideoReactNative.xcodeproj/project.pbxproj +3 -3
- package/package.json +2 -1
- package/src/components/Call/CallControls/ScreenShareButton.tsx +127 -0
- package/src/components/Call/CallControls/index.tsx +1 -0
- package/src/components/Participant/ParticipantView/ParticipantLabel.tsx +14 -5
- package/src/components/Participant/ParticipantView/VideoRenderer.tsx +3 -1
- package/src/constants/TestIds.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useIsIosScreenshareBroadcastStarted.ts +33 -0
- package/src/icons/ScreenShare.tsx +3 -18
- package/src/icons/ScreenShareIndicator.tsx +34 -0
- package/src/icons/index.tsx +1 -0
- package/src/theme/theme.ts +8 -0
- package/src/translations/en.json +1 -0
- package/src/version.ts +1 -1
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
2
3
|
#import "StreamVideoReactNative.h"
|
|
3
4
|
#import "WebRTCModule.h"
|
|
4
5
|
#import "WebRTCModuleOptions.h"
|
|
5
6
|
|
|
7
|
+
// Do not change these consts, it is what is used react-native-webrtc
|
|
8
|
+
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
|
|
9
|
+
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
|
|
10
|
+
|
|
11
|
+
void broadcastNotificationCallback(CFNotificationCenterRef center,
|
|
12
|
+
void *observer,
|
|
13
|
+
CFStringRef name,
|
|
14
|
+
const void *object,
|
|
15
|
+
CFDictionaryRef userInfo) {
|
|
16
|
+
StreamVideoReactNative *this = (__bridge StreamVideoReactNative*)observer;
|
|
17
|
+
NSString *eventName = (__bridge NSString*)name;
|
|
18
|
+
[this screenShareEventReceived: eventName];
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
6
22
|
@implementation StreamVideoReactNative
|
|
23
|
+
{
|
|
24
|
+
bool hasListeners;
|
|
25
|
+
CFNotificationCenterRef _notificationCenter;
|
|
26
|
+
}
|
|
7
27
|
RCT_EXPORT_MODULE();
|
|
8
28
|
|
|
9
29
|
+(BOOL)requiresMainQueueSetup {
|
|
@@ -16,4 +36,65 @@ RCT_EXPORT_MODULE();
|
|
|
16
36
|
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
|
|
17
37
|
options.videoEncoderFactory = simulcastVideoEncoderFactory;
|
|
18
38
|
}
|
|
19
|
-
|
|
39
|
+
|
|
40
|
+
-(instancetype)init {
|
|
41
|
+
self = [super init];
|
|
42
|
+
if (self) {
|
|
43
|
+
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
|
|
44
|
+
[self setupObserver];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return self;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
-(void)dealloc {
|
|
51
|
+
[self clearObserver];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
-(void)setupObserver {
|
|
56
|
+
CFNotificationCenterAddObserver(_notificationCenter,
|
|
57
|
+
(__bridge const void *)(self),
|
|
58
|
+
broadcastNotificationCallback,
|
|
59
|
+
(__bridge CFStringRef)kBroadcastStartedNotification,
|
|
60
|
+
NULL,
|
|
61
|
+
CFNotificationSuspensionBehaviorDeliverImmediately);
|
|
62
|
+
CFNotificationCenterAddObserver(_notificationCenter,
|
|
63
|
+
(__bridge const void *)(self),
|
|
64
|
+
broadcastNotificationCallback,
|
|
65
|
+
(__bridge CFStringRef)kBroadcastStoppedNotification,
|
|
66
|
+
NULL,
|
|
67
|
+
CFNotificationSuspensionBehaviorDeliverImmediately);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
-(void)clearObserver {
|
|
71
|
+
CFNotificationCenterRemoveObserver(_notificationCenter,
|
|
72
|
+
(__bridge const void *)(self),
|
|
73
|
+
(__bridge CFStringRef)kBroadcastStartedNotification,
|
|
74
|
+
NULL);
|
|
75
|
+
CFNotificationCenterRemoveObserver(_notificationCenter,
|
|
76
|
+
(__bridge const void *)(self),
|
|
77
|
+
(__bridge CFStringRef)kBroadcastStoppedNotification,
|
|
78
|
+
NULL);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
-(void)startObserving {
|
|
82
|
+
hasListeners = YES;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
-(void)stopObserving {
|
|
86
|
+
hasListeners = NO;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
-(void)screenShareEventReceived:(NSString*)event {
|
|
90
|
+
if (hasListeners) {
|
|
91
|
+
[self sendEventWithName:@"StreamVideoReactNative_Ios_Screenshare_Event" body:@{@"name": event}];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
-(NSArray<NSString *> *)supportedEvents {
|
|
96
|
+
return @[@"StreamVideoReactNative_Ios_Screenshare_Event"];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@end
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
134814211AA4EA7D00B7C361 /* Products */ = {
|
|
40
40
|
isa = PBXGroup;
|
|
41
41
|
children = (
|
|
42
|
-
134814201AA4EA6300B7C361 /*
|
|
42
|
+
134814201AA4EA6300B7C361 /* libStreamVideoReactNative.a */,
|
|
43
43
|
);
|
|
44
44
|
name = Products;
|
|
45
45
|
sourceTree = "<group>";
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
);
|
|
72
72
|
name = StreamVideoReactNative;
|
|
73
73
|
productName = RCTDataManager;
|
|
74
|
-
productReference = 134814201AA4EA6300B7C361 /*
|
|
74
|
+
productReference = 134814201AA4EA6300B7C361 /* libStreamVideoReactNative.a */;
|
|
75
75
|
productType = "com.apple.product-type.library.static";
|
|
76
76
|
};
|
|
77
77
|
/* End PBXNativeTarget section */
|
|
@@ -271,4 +271,4 @@
|
|
|
271
271
|
/* End XCConfigurationList section */
|
|
272
272
|
};
|
|
273
273
|
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
|
|
274
|
-
}
|
|
274
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-native-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "dist/commonjs/index.js",
|
|
6
6
|
"module": "dist/module/index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"package.json",
|
|
31
31
|
"app.plugin.js",
|
|
32
32
|
"expo-config-plugin/README.md",
|
|
33
|
+
"expo-config-plugin/static/**/*",
|
|
33
34
|
"expo-config-plugin/dist/**/*",
|
|
34
35
|
"!expo-config-plugin/src/*",
|
|
35
36
|
"!expo-config-plugin/fixtures/*",
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { NativeModules, Platform, findNodeHandle } from 'react-native';
|
|
3
|
+
import { ScreenCapturePickerView } from '@stream-io/react-native-webrtc';
|
|
4
|
+
import { ScreenShare } from '../../../icons';
|
|
5
|
+
import { CallControlsButton } from './CallControlsButton';
|
|
6
|
+
import { SfuModels } from '@stream-io/video-client';
|
|
7
|
+
import { useCall, useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
8
|
+
import { useTheme } from '../../../contexts';
|
|
9
|
+
import { useIsIosScreenshareBroadcastStarted } from '../../../hooks';
|
|
10
|
+
import { usePrevious } from '../../../utils/hooks';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The props for the Screen Share button in the Call Controls.
|
|
14
|
+
*/
|
|
15
|
+
export type ScreenShareButtonProps = {
|
|
16
|
+
/**
|
|
17
|
+
* Handler to be called when the screen-share has been started.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
onScreenShareStartedHandler?: () => void;
|
|
21
|
+
/**
|
|
22
|
+
* Handler to be called when the screen-share has been stopped.
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
onScreenShareStoppedHandler?: () => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ios >= 14.0 or android
|
|
29
|
+
const CanScreenShare =
|
|
30
|
+
(Platform.OS === 'ios' &&
|
|
31
|
+
Number.parseInt(Platform.Version.split('.')[0], 10) >= 14) ||
|
|
32
|
+
Platform.OS === 'android';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Button to start/stop screen share.
|
|
36
|
+
* Note: This button is enabled only on iOS >= 14.0 and any Android version.
|
|
37
|
+
*/
|
|
38
|
+
export const ScreenShareButton = ({
|
|
39
|
+
onScreenShareStartedHandler,
|
|
40
|
+
onScreenShareStoppedHandler,
|
|
41
|
+
}: ScreenShareButtonProps) => {
|
|
42
|
+
const {
|
|
43
|
+
theme: { colors, screenShareButton },
|
|
44
|
+
} = useTheme();
|
|
45
|
+
const call = useCall();
|
|
46
|
+
const { useLocalParticipant } = useCallStateHooks();
|
|
47
|
+
|
|
48
|
+
const onScreenShareStartedHandlerRef = useRef(onScreenShareStartedHandler);
|
|
49
|
+
onScreenShareStartedHandlerRef.current = onScreenShareStartedHandler;
|
|
50
|
+
const onScreenShareStoppedHandlerRef = useRef(onScreenShareStoppedHandler);
|
|
51
|
+
onScreenShareStoppedHandlerRef.current = onScreenShareStoppedHandler;
|
|
52
|
+
|
|
53
|
+
const iosScreenShareStarted = useIsIosScreenshareBroadcastStarted();
|
|
54
|
+
const prevIosScreenShareStarted = usePrevious(iosScreenShareStarted);
|
|
55
|
+
|
|
56
|
+
const localParticipant = useLocalParticipant();
|
|
57
|
+
const hasPublishedScreenShare = localParticipant?.publishedTracks.includes(
|
|
58
|
+
SfuModels.TrackType.SCREEN_SHARE,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// listens to iOS screen share broadcast started event
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
const run = async () => {
|
|
64
|
+
if (Platform.OS !== 'ios') {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (iosScreenShareStarted && !prevIosScreenShareStarted) {
|
|
68
|
+
onScreenShareStartedHandlerRef.current?.();
|
|
69
|
+
const media = await navigator.mediaDevices.getDisplayMedia({
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
deviceId: 'broadcast',
|
|
72
|
+
video: true,
|
|
73
|
+
audio: true,
|
|
74
|
+
});
|
|
75
|
+
await call?.publishScreenShareStream(media);
|
|
76
|
+
} else if (!iosScreenShareStarted && prevIosScreenShareStarted) {
|
|
77
|
+
onScreenShareStoppedHandlerRef.current?.();
|
|
78
|
+
await call?.stopPublish(SfuModels.TrackType.SCREEN_SHARE);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
run();
|
|
82
|
+
}, [call, iosScreenShareStarted, prevIosScreenShareStarted]);
|
|
83
|
+
|
|
84
|
+
const screenCaptureRef = React.useRef(null);
|
|
85
|
+
|
|
86
|
+
const onPress = async () => {
|
|
87
|
+
if (Platform.OS === 'ios') {
|
|
88
|
+
const reactTag = findNodeHandle(screenCaptureRef.current);
|
|
89
|
+
await NativeModules.ScreenCapturePickerViewManager.show(reactTag);
|
|
90
|
+
// After this the iOS screen share broadcast started/stopped event will be triggered
|
|
91
|
+
// and the useEffect listener will handle the rest
|
|
92
|
+
} else {
|
|
93
|
+
if (!hasPublishedScreenShare) {
|
|
94
|
+
try {
|
|
95
|
+
const media = await navigator.mediaDevices.getDisplayMedia({
|
|
96
|
+
video: true,
|
|
97
|
+
audio: true,
|
|
98
|
+
});
|
|
99
|
+
onScreenShareStartedHandlerRef.current?.();
|
|
100
|
+
await call?.publishScreenShareStream(media);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// ignored.. user didnt allow the screen share in the popup
|
|
103
|
+
}
|
|
104
|
+
} else if (hasPublishedScreenShare) {
|
|
105
|
+
onScreenShareStoppedHandlerRef.current?.();
|
|
106
|
+
await call?.stopPublish(SfuModels.TrackType.SCREEN_SHARE);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<CallControlsButton
|
|
113
|
+
disabled={!CanScreenShare}
|
|
114
|
+
onPress={onPress}
|
|
115
|
+
color={colors.static_white}
|
|
116
|
+
style={{
|
|
117
|
+
container: screenShareButton.container,
|
|
118
|
+
svgContainer: screenShareButton.svgContainer,
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
<ScreenShare color={colors.static_black} />
|
|
122
|
+
{Platform.OS === 'ios' && (
|
|
123
|
+
<ScreenCapturePickerView ref={screenCaptureRef} />
|
|
124
|
+
)}
|
|
125
|
+
</CallControlsButton>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
MicOff,
|
|
5
|
+
PinVertical,
|
|
6
|
+
ScreenShareIndicator,
|
|
7
|
+
VideoSlash,
|
|
8
|
+
} from '../../../icons';
|
|
4
9
|
import { useCall, useI18n } from '@stream-io/video-react-bindings';
|
|
5
10
|
import { ComponentTestIds } from '../../../constants/TestIds';
|
|
6
11
|
import { ParticipantViewProps } from './ParticipantView';
|
|
@@ -43,6 +48,7 @@ export const ParticipantLabel = ({
|
|
|
43
48
|
const call = useCall();
|
|
44
49
|
const { t } = useI18n();
|
|
45
50
|
const participantName = name ?? userId;
|
|
51
|
+
|
|
46
52
|
const participantLabel = isLocalParticipant ? t('You') : participantName;
|
|
47
53
|
const isPinningEnabled = pin?.isLocalPin;
|
|
48
54
|
const isAudioMuted = !publishedTracks.includes(SfuModels.TrackType.AUDIO);
|
|
@@ -53,6 +59,11 @@ export const ParticipantLabel = ({
|
|
|
53
59
|
};
|
|
54
60
|
|
|
55
61
|
if (trackType === 'screenShareTrack') {
|
|
62
|
+
const screenShareText = isLocalParticipant
|
|
63
|
+
? t('You are sharing your screen')
|
|
64
|
+
: t('{{ userName }} is sharing their screen', {
|
|
65
|
+
userName: participantName,
|
|
66
|
+
});
|
|
56
67
|
return (
|
|
57
68
|
<View
|
|
58
69
|
style={[
|
|
@@ -72,7 +83,7 @@ export const ParticipantLabel = ({
|
|
|
72
83
|
screenShareIconContainer,
|
|
73
84
|
]}
|
|
74
85
|
>
|
|
75
|
-
<
|
|
86
|
+
<ScreenShareIndicator color={colors.static_white} />
|
|
76
87
|
</View>
|
|
77
88
|
<Text
|
|
78
89
|
style={[
|
|
@@ -83,9 +94,7 @@ export const ParticipantLabel = ({
|
|
|
83
94
|
]}
|
|
84
95
|
numberOfLines={1}
|
|
85
96
|
>
|
|
86
|
-
{
|
|
87
|
-
userName: participantLabel,
|
|
88
|
-
})}
|
|
97
|
+
{screenShareText}
|
|
89
98
|
</Text>
|
|
90
99
|
</View>
|
|
91
100
|
);
|
|
@@ -74,7 +74,9 @@ export const VideoRenderer = ({
|
|
|
74
74
|
const videoStreamToRender = (isScreenSharing
|
|
75
75
|
? screenShareStream
|
|
76
76
|
: videoStream) as unknown as MediaStream | undefined;
|
|
77
|
-
|
|
77
|
+
|
|
78
|
+
const mirror =
|
|
79
|
+
isLocalParticipant && !isScreenSharing && direction === 'front';
|
|
78
80
|
|
|
79
81
|
/**
|
|
80
82
|
* This effect updates the participant's viewportVisibilityState
|
package/src/constants/TestIds.ts
CHANGED
package/src/hooks/index.ts
CHANGED
|
@@ -3,5 +3,6 @@ export * from './usePermissionRequest';
|
|
|
3
3
|
export * from './usePermissionNotification';
|
|
4
4
|
export * from './push';
|
|
5
5
|
export * from './useAndroidKeepCallAliveEffect';
|
|
6
|
+
export * from './useIsIosScreenshareBroadcastStarted';
|
|
6
7
|
export * from './useIsInPiPMode';
|
|
7
8
|
export * from './useAutoEnterPiPEffect';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
type Event = {
|
|
5
|
+
name: 'iOS_BroadcastStarted' | 'iOS_BroadcastStopped';
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function useIsIosScreenshareBroadcastStarted() {
|
|
9
|
+
const [hasStarted, setHasStarted] = useState(false);
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (Platform.OS !== 'ios') {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const eventEmitter = new NativeEventEmitter(
|
|
17
|
+
NativeModules.StreamVideoReactNative,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const subscription = eventEmitter.addListener(
|
|
21
|
+
'StreamVideoReactNative_Ios_Screenshare_Event',
|
|
22
|
+
(event: Event) => {
|
|
23
|
+
setHasStarted(event.name === 'iOS_BroadcastStarted');
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
return () => {
|
|
28
|
+
subscription.remove();
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
return hasStarted;
|
|
33
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Svg, {
|
|
2
|
+
import Svg, { Path } from 'react-native-svg';
|
|
3
3
|
import { ColorValue } from 'react-native/types';
|
|
4
4
|
import { IconTestIds } from '../constants/TestIds';
|
|
5
5
|
|
|
@@ -9,25 +9,10 @@ type Props = {
|
|
|
9
9
|
|
|
10
10
|
export const ScreenShare = ({ color }: Props) => {
|
|
11
11
|
return (
|
|
12
|
-
<Svg viewBox="0 0
|
|
13
|
-
<Mask id="path-1-inside-1_1396_84816">
|
|
14
|
-
<Path
|
|
15
|
-
fillRule="evenodd"
|
|
16
|
-
clipRule="evenodd"
|
|
17
|
-
d="M 2 6.68176 C 2 5.57719 2.89543 4.68176 4 4.68176 H 20 C 21.1046 4.68176 22 5.57719 22 6.68176 V 16.3181 C 22 17.4227 21.1046 18.3181 20 18.3181 H 4 C 2.89543 18.3181 2 17.4227 2 16.3181 V 6.68176 Z M 10.4209 11.5243 L 8.3635 11.5 L 11.9999 7.25755 L 15.6362 11.5 L 13.5065 11.5247 V 15.7424 L 10.4209 15.7424 V 11.5243 Z"
|
|
18
|
-
/>
|
|
19
|
-
</Mask>
|
|
20
|
-
|
|
21
|
-
<Path
|
|
22
|
-
fill={color}
|
|
23
|
-
fillRule="evenodd"
|
|
24
|
-
clipRule="evenodd"
|
|
25
|
-
d="M 2 6.68176 C 2 5.57719 2.89543 4.68176 4 4.68176 H 20 C 21.1046 4.68176 22 5.57719 22 6.68176 V 16.3181 C 22 17.4227 21.1046 18.3181 20 18.3181 H 4 C 2.89543 18.3181 2 17.4227 2 16.3181 V 6.68176 Z M 10.4209 11.5243 L 8.3635 11.5 L 11.9999 7.25755 L 15.6362 11.5 L 13.5065 11.5247 V 15.7424 L 10.4209 15.7424 V 11.5243 Z"
|
|
26
|
-
/>
|
|
12
|
+
<Svg viewBox="0 0 36 36" testID={IconTestIds.SCREEN_SHARE}>
|
|
27
13
|
<Path
|
|
28
|
-
mask="url(#path-1-inside-1_1396_84816)"
|
|
29
14
|
fill={color}
|
|
30
|
-
d="
|
|
15
|
+
d="m25.407 1.718-14.814-.014a2.959 2.959 0 0 0-2.948 2.963v26.666a2.959 2.959 0 0 0 2.948 2.963h14.814a2.972 2.972 0 0 0 2.963-2.963V4.667a2.96 2.96 0 0 0-2.963-2.949Zm0 26.652H10.593V7.63h14.814v20.74Zm-6.222-8.563V22.4l4.741-4.43-4.74-4.414v2.518c-4.608.637-6.445 3.793-7.112 6.963 1.645-2.222 3.822-3.23 7.111-3.23Z"
|
|
31
16
|
/>
|
|
32
17
|
</Svg>
|
|
33
18
|
);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Svg, { Mask, Path } from 'react-native-svg';
|
|
3
|
+
import { ColorValue } from 'react-native/types';
|
|
4
|
+
import { IconTestIds } from '../constants/TestIds';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
color: ColorValue;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const ScreenShareIndicator = ({ color }: Props) => {
|
|
11
|
+
return (
|
|
12
|
+
<Svg viewBox="0 0 24 24" testID={IconTestIds.SCREEN_SHARE_INDICATOR}>
|
|
13
|
+
<Mask id="path-1-inside-1_1396_84816">
|
|
14
|
+
<Path
|
|
15
|
+
fillRule="evenodd"
|
|
16
|
+
clipRule="evenodd"
|
|
17
|
+
d="M 2 6.68176 C 2 5.57719 2.89543 4.68176 4 4.68176 H 20 C 21.1046 4.68176 22 5.57719 22 6.68176 V 16.3181 C 22 17.4227 21.1046 18.3181 20 18.3181 H 4 C 2.89543 18.3181 2 17.4227 2 16.3181 V 6.68176 Z M 10.4209 11.5243 L 8.3635 11.5 L 11.9999 7.25755 L 15.6362 11.5 L 13.5065 11.5247 V 15.7424 L 10.4209 15.7424 V 11.5243 Z"
|
|
18
|
+
/>
|
|
19
|
+
</Mask>
|
|
20
|
+
|
|
21
|
+
<Path
|
|
22
|
+
fill={color}
|
|
23
|
+
fillRule="evenodd"
|
|
24
|
+
clipRule="evenodd"
|
|
25
|
+
d="M 2 6.68176 C 2 5.57719 2.89543 4.68176 4 4.68176 H 20 C 21.1046 4.68176 22 5.57719 22 6.68176 V 16.3181 C 22 17.4227 21.1046 18.3181 20 18.3181 H 4 C 2.89543 18.3181 2 17.4227 2 16.3181 V 6.68176 Z M 10.4209 11.5243 L 8.3635 11.5 L 11.9999 7.25755 L 15.6362 11.5 L 13.5065 11.5247 V 15.7424 L 10.4209 15.7424 V 11.5243 Z"
|
|
26
|
+
/>
|
|
27
|
+
<Path
|
|
28
|
+
mask="url(#path-1-inside-1_1396_84816)"
|
|
29
|
+
fill={color}
|
|
30
|
+
d="M 8.3635 11.5 L 6.84499 10.1984 L 4.05865 13.4491 L 8.33982 13.4998 L 8.3635 11.5 Z M 10.4209 11.5243 H 12.4209 V 9.54789 L 10.4446 9.52449 L 10.4209 11.5243 Z M 11.9999 7.25755 L 13.5184 5.95597 L 11.9999 4.18437 L 10.4814 5.95597 L 11.9999 7.25755 Z M 15.6362 11.5 L 15.6594 13.4998 L 19.9419 13.4501 L 17.1547 10.1984 L 15.6362 11.5 Z M 13.5065 11.5247 L 13.4833 9.52483 L 11.5065 9.54778 V 11.5247 H 13.5065 Z M 13.5065 15.7424 L 13.5065 17.7424 L 15.5065 17.7424 V 15.7424 H 13.5065 Z M 10.4209 15.7424 H 8.42094 V 17.7424 H 10.4209 L 10.4209 15.7424 Z M 4 2.68176 C 1.79086 2.68176 0 4.47263 0 6.68176 H 4 V 6.68176 V 2.68176 Z M 20 2.68176 H 4 V 6.68176 H 20 V 2.68176 Z M 24 6.68176 C 24 4.47262 22.2091 2.68176 20 2.68176 V 6.68176 H 24 Z M 24 16.3181 V 6.68176 H 20 V 16.3181 H 24 Z M 20 20.3181 C 22.2091 20.3181 24 18.5273 24 16.3181 H 20 V 16.3181 V 20.3181 Z M 4 20.3181 H 20 V 16.3181 H 4 V 20.3181 Z M 0 16.3181 C 0 18.5273 1.79086 20.3181 4 20.3181 V 16.3181 H 4 H 0 Z M 0 6.68176 V 16.3181 H 4 V 6.68176 H 0 Z M 8.33982 13.4998 L 10.3973 13.5242 L 10.4446 9.52449 L 8.38719 9.50012 L 8.33982 13.4998 Z M 10.4814 5.95597 L 6.84499 10.1984 L 9.88202 12.8016 L 13.5184 8.55913 L 10.4814 5.95597 Z M 17.1547 10.1984 L 13.5184 5.95597 L 10.4814 8.55913 L 14.1177 12.8016 L 17.1547 10.1984 Z M 13.5297 13.5246 L 15.6594 13.4998 L 15.613 9.50011 L 13.4833 9.52483 L 13.5297 13.5246 Z M 11.5065 11.5247 V 15.7424 H 15.5065 V 11.5247 H 11.5065 Z M 13.5065 13.7424 L 10.4209 13.7424 L 10.4209 17.7424 L 13.5065 17.7424 L 13.5065 13.7424 Z M 12.4209 15.7424 V 11.5243 H 8.42094 V 15.7424 H 12.4209 Z"
|
|
31
|
+
/>
|
|
32
|
+
</Svg>
|
|
33
|
+
);
|
|
34
|
+
};
|
package/src/icons/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ export * from './Participants';
|
|
|
11
11
|
export * from './ThreeDots';
|
|
12
12
|
export * from './PinVertical';
|
|
13
13
|
export * from './Spotlight';
|
|
14
|
+
export * from './ScreenShareIndicator';
|
|
14
15
|
export * from './ScreenShare';
|
|
15
16
|
export * from './Reaction';
|
|
16
17
|
export * from './TopViewBackground';
|
package/src/theme/theme.ts
CHANGED
|
@@ -57,6 +57,10 @@ export type Theme = {
|
|
|
57
57
|
container: ViewStyle;
|
|
58
58
|
svgContainer: ViewStyle;
|
|
59
59
|
};
|
|
60
|
+
screenShareButton: {
|
|
61
|
+
container: ViewStyle;
|
|
62
|
+
svgContainer: ViewStyle;
|
|
63
|
+
};
|
|
60
64
|
toggleAudioPreviewButton: {
|
|
61
65
|
container: ViewStyle;
|
|
62
66
|
svgContainer: ViewStyle;
|
|
@@ -363,6 +367,10 @@ export const defaultTheme: Theme = {
|
|
|
363
367
|
container: {},
|
|
364
368
|
svgContainer: {},
|
|
365
369
|
},
|
|
370
|
+
screenShareButton: {
|
|
371
|
+
container: {},
|
|
372
|
+
svgContainer: {},
|
|
373
|
+
},
|
|
366
374
|
toggleAudioPreviewButton: {
|
|
367
375
|
container: {},
|
|
368
376
|
svgContainer: {},
|
package/src/translations/en.json
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"You are first to Join the call.": "You are first to Join the call.",
|
|
15
15
|
"Participants ({{ numberOfParticipants }})": "Participants ({{ numberOfParticipants }})",
|
|
16
16
|
"{{ userName }} is sharing their screen": "{{ userName }} is sharing their screen",
|
|
17
|
+
"You are sharing your screen": "You are sharing your screen",
|
|
17
18
|
"{{ numberOfParticipants }} participant(s) are in the call.": "{{ numberOfParticipants }} participant(s) are in the call.",
|
|
18
19
|
"You are about to join a call with id {{ callId }}.": "You are about to join a call with id {{ callId }}."
|
|
19
20
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.2.
|
|
1
|
+
export const version = '0.2.1';
|