@cloudflare/realtimekit-react-native 0.0.0 → 0.0.1-staging.2

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 (83) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +83 -0
  3. package/RealtimeKitCore.podspec +19 -0
  4. package/android/build.gradle +58 -0
  5. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  6. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  7. package/android/gradlew +185 -0
  8. package/android/gradlew.bat +89 -0
  9. package/android/src/main/AndroidManifest.xml +23 -0
  10. package/android/src/main/java/com/reactnativecore/BackgroundTimer/RNBackgroundTimer.java +97 -0
  11. package/android/src/main/java/com/reactnativecore/Constants.java +14 -0
  12. package/android/src/main/java/com/reactnativecore/CoreModule.java +49 -0
  13. package/android/src/main/java/com/reactnativecore/CorePackage.java +34 -0
  14. package/android/src/main/java/com/reactnativecore/DyteHelperModule.java +268 -0
  15. package/android/src/main/java/com/reactnativecore/DyteHolder.java +7 -0
  16. package/android/src/main/java/com/reactnativecore/ForegroundService.java +48 -0
  17. package/android/src/main/java/com/reactnativecore/NotificationHelper.java +127 -0
  18. package/android/src/main/java/com/reactnativecore/RNPermissionsModule.java +226 -0
  19. package/android/src/main/java/com/reactnativecore/incallmanager/AppRTCBluetoothManager.java +637 -0
  20. package/android/src/main/java/com/reactnativecore/incallmanager/AppRTCProximitySensor.java +133 -0
  21. package/android/src/main/java/com/reactnativecore/incallmanager/AppRTCUtils.java +41 -0
  22. package/android/src/main/java/com/reactnativecore/incallmanager/InCallManagerModule.java +1881 -0
  23. package/android/src/main/java/com/reactnativecore/incallmanager/InCallProximityManager.java +162 -0
  24. package/android/src/main/java/com/reactnativecore/incallmanager/InCallWakeLockUtils.java +116 -0
  25. package/android/src/main/java/com/reactnativecore/incallmanager/ThreadUtils.java +39 -0
  26. package/app.plugin.js +1 -0
  27. package/ios/BroadcastEventEmitter.h +11 -0
  28. package/ios/BroadcastEventEmitter.m +72 -0
  29. package/ios/Core.h +5 -0
  30. package/ios/Core.m +28 -0
  31. package/ios/Core.xcodeproj/project.pbxproj +287 -0
  32. package/ios/DyteRNBackgroundTimer.h +22 -0
  33. package/ios/DyteRNBackgroundTimer.m +90 -0
  34. package/ios/DyteRNPermissionHandlerNotifications.h +17 -0
  35. package/ios/DyteRNPermissionHandlerNotifications.m +127 -0
  36. package/ios/DyteRNPermissions.h +50 -0
  37. package/ios/DyteRNPermissions.m +275 -0
  38. package/ios/DyteScreensharePickerView.h +8 -0
  39. package/ios/DyteScreensharePickerView.m +27 -0
  40. package/ios/PrivacyInfo.xcprivacy +60 -0
  41. package/ios/RNInCallManager.h +16 -0
  42. package/ios/RNInCallManager.m +1354 -0
  43. package/ios/permissions/DyteRNPermissionHandlerBluetoothPeripheral.h +4 -0
  44. package/ios/permissions/DyteRNPermissionHandlerBluetoothPeripheral.m +87 -0
  45. package/ios/permissions/DyteRNPermissionHandlerCamera.h +5 -0
  46. package/ios/permissions/DyteRNPermissionHandlerCamera.m +38 -0
  47. package/ios/permissions/DyteRNPermissionHandlerMicrophone.h +5 -0
  48. package/ios/permissions/DyteRNPermissionHandlerMicrophone.m +34 -0
  49. package/ios/permissions/DyteRNPermissionHandlerPhotoLibrary.h +8 -0
  50. package/ios/permissions/DyteRNPermissionHandlerPhotoLibrary.m +70 -0
  51. package/ios/screenshare/DyteDarwinNotificationCenter.swift +21 -0
  52. package/ios/screenshare/DyteScreenshareAtomic.swift +29 -0
  53. package/ios/screenshare/DyteScreenshareHandler.swift +103 -0
  54. package/ios/screenshare/DyteScreenshareUploader.swift +139 -0
  55. package/ios/screenshare/DyteSocketConnection.swift +190 -0
  56. package/lib/BackgroundHandler.d.ts +20 -0
  57. package/lib/BackgroundHandler.js +87 -0
  58. package/lib/LocalMediaError.d.ts +4 -0
  59. package/lib/LocalMediaError.js +6 -0
  60. package/lib/LocalMediaHandler.d.ts +118 -0
  61. package/lib/LocalMediaHandler.js +853 -0
  62. package/lib/LocalMediaInterfaces.d.ts +76 -0
  63. package/lib/LocalMediaInterfaces.js +1 -0
  64. package/lib/LocalMediaUtils.d.ts +93 -0
  65. package/lib/LocalMediaUtils.js +276 -0
  66. package/lib/NativeAudioManager.d.ts +16 -0
  67. package/lib/NativeAudioManager.js +93 -0
  68. package/lib/PermissionHandler.d.ts +34 -0
  69. package/lib/PermissionHandler.js +179 -0
  70. package/lib/ReactContext.d.ts +42 -0
  71. package/lib/ReactContext.js +96 -0
  72. package/lib/ReactHooks.d.ts +11 -0
  73. package/lib/ReactHooks.js +73 -0
  74. package/lib/index.d.ts +10 -0
  75. package/lib/index.js +40 -0
  76. package/lib/utils/crypto.d.ts +17 -0
  77. package/lib/utils/crypto.js +82 -0
  78. package/package.json +51 -4
  79. package/plugin/build/withDyte.d.ts +25 -0
  80. package/plugin/build/withDyte.js +100 -0
  81. package/plugin/src/withDyte.ts +150 -0
  82. package/plugin/tsconfig.json +10 -0
  83. package/plugin/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,190 @@
1
+ import Foundation
2
+
3
+ class DyteSocketConnection: NSObject {
4
+ var didOpen: (() -> Void)?
5
+ var didClose: ((Error?) -> Void)?
6
+ var streamHasSpaceAvailable: (() -> Void)?
7
+
8
+ private let filePath: String
9
+ private var socketHandle: Int32 = -1
10
+ private var address: sockaddr_un?
11
+
12
+ private var inputStream: InputStream?
13
+ private var outputStream: OutputStream?
14
+
15
+ private var networkQueue: DispatchQueue?
16
+ private var shouldKeepRunning = false
17
+
18
+ init?(filePath path: String) {
19
+ filePath = path
20
+ socketHandle = Darwin.socket(AF_UNIX, SOCK_STREAM, 0)
21
+
22
+ guard socketHandle != -1 else {
23
+ print("failure: create socket")
24
+ return nil
25
+ }
26
+ }
27
+
28
+ func open() -> Bool {
29
+ print("open socket connection")
30
+
31
+ guard FileManager.default.fileExists(atPath: filePath) else {
32
+ print("failure: socket file missing")
33
+ return false
34
+ }
35
+
36
+ guard setupAddress() == true else {
37
+ return false
38
+ }
39
+
40
+ guard connectSocket() == true else {
41
+ return false
42
+ }
43
+
44
+ setupStreams()
45
+
46
+ inputStream?.open()
47
+ outputStream?.open()
48
+
49
+ return true
50
+ }
51
+
52
+ func close() {
53
+ unscheduleStreams()
54
+
55
+ inputStream?.delegate = nil
56
+ outputStream?.delegate = nil
57
+
58
+ inputStream?.close()
59
+ outputStream?.close()
60
+
61
+ inputStream = nil
62
+ outputStream = nil
63
+ }
64
+
65
+ func writeToStream(buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int {
66
+ outputStream?.write(buffer, maxLength: length) ?? 0
67
+ }
68
+ }
69
+
70
+ extension DyteSocketConnection: StreamDelegate {
71
+
72
+ func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
73
+ switch eventCode {
74
+ case .openCompleted:
75
+ print("client stream open completed")
76
+ if aStream == outputStream {
77
+ didOpen?()
78
+ }
79
+ case .hasBytesAvailable:
80
+ if aStream == inputStream {
81
+ var buffer: UInt8 = 0
82
+ let numberOfBytesRead = inputStream?.read(&buffer, maxLength: 1)
83
+ if numberOfBytesRead == 0 && aStream.streamStatus == .atEnd {
84
+ print("server socket closed")
85
+ close()
86
+ notifyDidClose(error: nil)
87
+ }
88
+ }
89
+ case .hasSpaceAvailable:
90
+ if aStream == outputStream {
91
+ streamHasSpaceAvailable?()
92
+ }
93
+ case .errorOccurred:
94
+ print("client stream error occured: \(String(describing: aStream.streamError))")
95
+ close()
96
+ notifyDidClose(error: aStream.streamError)
97
+
98
+ default:
99
+ break
100
+ }
101
+ }
102
+ }
103
+
104
+ private extension DyteSocketConnection {
105
+
106
+ func setupAddress() -> Bool {
107
+ var addr = sockaddr_un()
108
+ guard filePath.count < MemoryLayout.size(ofValue: addr.sun_path) else {
109
+ print("failure: fd path is too long")
110
+ return false
111
+ }
112
+
113
+ _ = withUnsafeMutablePointer(to: &addr.sun_path.0) { ptr in
114
+ filePath.withCString {
115
+ strncpy(ptr, $0, filePath.count)
116
+ }
117
+ }
118
+
119
+ address = addr
120
+ return true
121
+ }
122
+
123
+ func connectSocket() -> Bool {
124
+ guard var addr = address else {
125
+ return false
126
+ }
127
+
128
+ let status = withUnsafePointer(to: &addr) { ptr in
129
+ ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) {
130
+ Darwin.connect(socketHandle, $0, socklen_t(MemoryLayout<sockaddr_un>.size))
131
+ }
132
+ }
133
+
134
+ guard status == noErr else {
135
+ print("failure: \(status)")
136
+ return false
137
+ }
138
+
139
+ return true
140
+ }
141
+
142
+ func setupStreams() {
143
+ var readStream: Unmanaged<CFReadStream>?
144
+ var writeStream: Unmanaged<CFWriteStream>?
145
+
146
+ CFStreamCreatePairWithSocket(kCFAllocatorDefault, socketHandle, &readStream, &writeStream)
147
+
148
+ inputStream = readStream?.takeRetainedValue()
149
+ inputStream?.delegate = self
150
+ inputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
151
+
152
+ outputStream = writeStream?.takeRetainedValue()
153
+ outputStream?.delegate = self
154
+ outputStream?.setProperty(kCFBooleanTrue, forKey: Stream.PropertyKey(kCFStreamPropertyShouldCloseNativeSocket as String))
155
+
156
+ scheduleStreams()
157
+ }
158
+
159
+ func scheduleStreams() {
160
+ shouldKeepRunning = true
161
+
162
+ networkQueue = DispatchQueue.global(qos: .userInitiated)
163
+ networkQueue?.async { [weak self] in
164
+ self?.inputStream?.schedule(in: .current, forMode: .common)
165
+ self?.outputStream?.schedule(in: .current, forMode: .common)
166
+ RunLoop.current.run()
167
+
168
+ var isRunning = false
169
+
170
+ repeat {
171
+ isRunning = self?.shouldKeepRunning ?? false && RunLoop.current.run(mode: .default, before: .distantFuture)
172
+ } while (isRunning)
173
+ }
174
+ }
175
+
176
+ func unscheduleStreams() {
177
+ networkQueue?.sync { [weak self] in
178
+ self?.inputStream?.remove(from: .current, forMode: .common)
179
+ self?.outputStream?.remove(from: .current, forMode: .common)
180
+ }
181
+
182
+ shouldKeepRunning = false
183
+ }
184
+
185
+ func notifyDidClose(error: Error?) {
186
+ if didClose != nil {
187
+ didClose?(error)
188
+ }
189
+ }
190
+ }
@@ -0,0 +1,20 @@
1
+ declare class BackgroundTimer {
2
+ uniqueId: number;
3
+ callbacks: {
4
+ [key: string]: any;
5
+ };
6
+ backgroundTimer: number | NodeJS.Timeout | null;
7
+ backgroundListener: any;
8
+ constructor();
9
+ start(delay?: number): any;
10
+ stop(): any;
11
+ runBackgroundTimer(callback: any, delay: any): void;
12
+ backgroundClockMethod(callback: any, delay: any): void;
13
+ stopBackgroundTimer(): void;
14
+ setTimeout(callback: any, timeout: any): number;
15
+ clearTimeout(timeoutId: any): void;
16
+ setInterval(callback: any, timeout: any): number;
17
+ clearInterval(intervalId: any): void;
18
+ }
19
+ declare const _default: BackgroundTimer;
20
+ export default _default;
@@ -0,0 +1,87 @@
1
+ import { DeviceEventEmitter, NativeAppEventEmitter, NativeEventEmitter, NativeModules, Platform, } from 'react-native';
2
+ const { DyteRNBackgroundTimer } = NativeModules;
3
+ const Emitter = new NativeEventEmitter(DyteRNBackgroundTimer);
4
+ class BackgroundTimer {
5
+ constructor() {
6
+ this.uniqueId = 0;
7
+ this.callbacks = {};
8
+ Emitter.addListener('backgroundTimer.timeout', (id) => {
9
+ if (this.callbacks[id]) {
10
+ const callbackById = this.callbacks[id];
11
+ const { callback } = callbackById;
12
+ if (!this.callbacks[id].interval) {
13
+ delete this.callbacks[id];
14
+ }
15
+ else {
16
+ DyteRNBackgroundTimer.backgroundTimerSetTimeout(id, this.callbacks[id].timeout);
17
+ }
18
+ callback();
19
+ }
20
+ });
21
+ }
22
+ // Original API
23
+ start(delay = 0) {
24
+ return DyteRNBackgroundTimer.start(delay);
25
+ }
26
+ stop() {
27
+ Emitter.removeAllListeners('backgroundTimer.timeout');
28
+ return DyteRNBackgroundTimer.stop();
29
+ }
30
+ runBackgroundTimer(callback, delay) {
31
+ const EventEmitter = Platform.select({
32
+ ios: () => NativeAppEventEmitter,
33
+ android: () => DeviceEventEmitter,
34
+ })();
35
+ this.start(0);
36
+ this.backgroundListener = EventEmitter.addListener('backgroundTimer', () => {
37
+ this.backgroundListener.remove();
38
+ this.backgroundClockMethod(callback, delay);
39
+ });
40
+ }
41
+ backgroundClockMethod(callback, delay) {
42
+ this.backgroundTimer = this.setTimeout(() => {
43
+ callback();
44
+ this.backgroundClockMethod(callback, delay);
45
+ }, delay);
46
+ }
47
+ stopBackgroundTimer() {
48
+ this.stop();
49
+ this.clearTimeout(this.backgroundTimer);
50
+ }
51
+ // New API, allowing for multiple timers
52
+ setTimeout(callback, timeout) {
53
+ this.uniqueId += 1;
54
+ const timeoutId = this.uniqueId;
55
+ this.callbacks[timeoutId] = {
56
+ callback,
57
+ interval: false,
58
+ timeout,
59
+ };
60
+ DyteRNBackgroundTimer.setTimeout(timeoutId, timeout);
61
+ return timeoutId;
62
+ }
63
+ clearTimeout(timeoutId) {
64
+ if (this.callbacks[timeoutId]) {
65
+ delete this.callbacks[timeoutId];
66
+ // DyteRNBackgroundTimer.clearTimeout(timeoutId);
67
+ }
68
+ }
69
+ setInterval(callback, timeout) {
70
+ this.uniqueId += 1;
71
+ const intervalId = this.uniqueId;
72
+ this.callbacks[intervalId] = {
73
+ callback,
74
+ interval: true,
75
+ timeout,
76
+ };
77
+ DyteRNBackgroundTimer.backgroundTimerSetTimeout(intervalId, timeout);
78
+ return intervalId;
79
+ }
80
+ clearInterval(intervalId) {
81
+ if (this.callbacks[intervalId]) {
82
+ delete this.callbacks[intervalId];
83
+ // DyteRNBackgroundTimer.clearTimeout(intervalId);
84
+ }
85
+ }
86
+ }
87
+ export default new BackgroundTimer();
@@ -0,0 +1,4 @@
1
+ export default class LocalMediaError extends Error {
2
+ code: string;
3
+ constructor(message: string, code: string);
4
+ }
@@ -0,0 +1,6 @@
1
+ export default class LocalMediaError extends Error {
2
+ constructor(message, code) {
3
+ super(message);
4
+ this.code = code;
5
+ }
6
+ }
@@ -0,0 +1,118 @@
1
+ import { EventEmitter } from 'events';
2
+ import LocalMediaUtils from './LocalMediaUtils';
3
+ import { MediaPermission } from './LocalMediaInterfaces';
4
+ import type { MediaStreamTrack } from '@dyteinternals/react-native-webrtc';
5
+ import type { MediaDeviceInfo } from './LocalMediaInterfaces';
6
+ export declare enum MediaEvents {
7
+ AUDIO_TRACK_CHANGE = 0,
8
+ VIDEO_TRACK_CHANGE = 1,
9
+ SCREENSHARE_TRACK_CHANGE = 2,
10
+ SCREENSHARE_ENDED = 3,
11
+ DEVICE_CHANGE = 4,
12
+ SCREENSHARE_STARTED = 5,
13
+ MEDIA_PERMISSION_UPDATE = 6,
14
+ DEVICE_LIST_UPDATED = 7
15
+ }
16
+ export default class LocalMediaHandler extends EventEmitter {
17
+ #private;
18
+ audioTrack: MediaStreamTrack;
19
+ rawAudioTrack: MediaStreamTrack;
20
+ videoTrack: MediaStreamTrack;
21
+ rawVideoTrack: MediaStreamTrack;
22
+ screenShareTracks: {
23
+ audio?: MediaStreamTrack;
24
+ video?: MediaStreamTrack;
25
+ };
26
+ audioEnabled: boolean;
27
+ videoEnabled: boolean;
28
+ screenShareEnabled: boolean;
29
+ currentDevices: {
30
+ audio?: MediaDeviceInfo;
31
+ video?: MediaDeviceInfo;
32
+ speaker?: MediaDeviceInfo;
33
+ };
34
+ permissions: {
35
+ audio?: MediaPermission;
36
+ video?: MediaPermission;
37
+ };
38
+ _handleAppStateChange: (nextAppState: any) => void;
39
+ private configureForeground;
40
+ constructor(localMediaUtils: LocalMediaUtils);
41
+ destructor(): void;
42
+ private handlePermissionErrors;
43
+ private conditionallyRestartAudio;
44
+ private conditionallyRestartVideo;
45
+ private shouldReacquireTrack;
46
+ removeDocumentEventListeners(): Promise<void>;
47
+ private onUnmute;
48
+ private removeMediaStreamTrackListeners;
49
+ private addMediaStreamTrackListeners;
50
+ setupAudioStream(deviceId?: string, forceStopTrack?: boolean): Promise<void>;
51
+ private onVisibilityChange;
52
+ setupVideoStream(deviceId?: string, forceStopTrack?: boolean): Promise<void>;
53
+ setupSpeaker(deviceId?: string): Promise<void>;
54
+ getOperationalWebcamDeviceId(): Promise<{
55
+ isOperational: boolean;
56
+ deviceId: string;
57
+ }>;
58
+ getOperationalMicDeviceId(): Promise<{
59
+ isOperational: boolean;
60
+ deviceId: string;
61
+ }>;
62
+ setupStreams({ audio, video, }: {
63
+ audio: boolean;
64
+ video: boolean;
65
+ }): Promise<void>;
66
+ private stopAudioTrack;
67
+ private stopVideoTrack;
68
+ private stopScreenShareTracks;
69
+ removeAudioTrack(): void;
70
+ removeVideoTrack(): void;
71
+ removeScreenShareTracks(tracks?: {
72
+ audio?: boolean;
73
+ video?: boolean;
74
+ }): void;
75
+ removeAllTracks(): void;
76
+ private setAudioTrack;
77
+ private setVideoTrack;
78
+ private setScreenShareTracks;
79
+ private onScreenShareEnded;
80
+ disableAudio(): void;
81
+ enableAudio(): Promise<void>;
82
+ enableVideo(): Promise<void>;
83
+ disableVideo(): Promise<void>;
84
+ toggleAudio(): Promise<void>;
85
+ toggleVideo(): Promise<void>;
86
+ setAudioDevice(device: MediaDeviceInfo): Promise<void>;
87
+ setVideoDevice(device: MediaDeviceInfo): Promise<void>;
88
+ setSpeakerDevice(device?: MediaDeviceInfo): Promise<void>;
89
+ setDevice(route: MediaDeviceInfo): Promise<any>;
90
+ private oniOSBroadcastStart;
91
+ private oniOSBroadcastStop;
92
+ toggleScreenShare(): Promise<void>;
93
+ enableScreenShare(): Promise<void>;
94
+ disableScreenShare(): Promise<void>;
95
+ destruct(): void;
96
+ getAllDevices(): MediaDeviceInfo[];
97
+ getCurrentDevices(): {
98
+ audio?: MediaDeviceInfo;
99
+ video?: MediaDeviceInfo;
100
+ speaker?: MediaDeviceInfo;
101
+ };
102
+ getDeviceById(deviceId: string, kind: 'audioinput' | 'audiooutput' | 'videoinput'): MediaDeviceInfo;
103
+ getAudioDevices(): MediaDeviceInfo[];
104
+ getVideoDevices(): MediaDeviceInfo[];
105
+ getSpeakerDevices(): MediaDeviceInfo[];
106
+ onDeviceChange(changedDevices: {
107
+ added: MediaDeviceInfo[];
108
+ removed: MediaDeviceInfo[];
109
+ }, forceDeviceChange: boolean): Promise<void>;
110
+ cleanUpTracks(): void;
111
+ destructMediaHandler(): Promise<void>;
112
+ static init(_: any): Promise<LocalMediaHandler>;
113
+ emit(event: keyof typeof MediaEvents, ...args: any[]): boolean;
114
+ on(event: keyof typeof MediaEvents, listener: (...args: any[]) => void): this;
115
+ }
116
+ export interface RNLocalMediaHandler {
117
+ new (): LocalMediaHandler;
118
+ }