omikit-plugin 3.3.29 → 4.0.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 (50) hide show
  1. package/README.md +994 -1217
  2. package/android/build.gradle +22 -72
  3. package/android/gradle.properties +4 -4
  4. package/android/src/main/java/com/omikitplugin/FLLocalCameraModule.kt +1 -1
  5. package/android/src/main/java/com/omikitplugin/FLRemoteCameraModule.kt +1 -1
  6. package/android/src/main/java/com/omikitplugin/OmikitPluginModule.kt +326 -356
  7. package/android/src/main/java/com/omikitplugin/constants/constant.kt +2 -1
  8. package/ios/CallProcess/CallManager.swift +45 -35
  9. package/ios/Constant/Constant.swift +1 -0
  10. package/ios/Library/OmikitPlugin.m +75 -1
  11. package/ios/Library/OmikitPlugin.swift +199 -16
  12. package/ios/OmikitPlugin-Protocol.h +161 -0
  13. package/lib/commonjs/NativeOmikitPlugin.js +9 -0
  14. package/lib/commonjs/NativeOmikitPlugin.js.map +1 -0
  15. package/lib/commonjs/index.js +11 -0
  16. package/lib/commonjs/index.js.map +1 -1
  17. package/lib/commonjs/omi_audio_type.js +20 -0
  18. package/lib/commonjs/omi_audio_type.js.map +1 -0
  19. package/lib/commonjs/omi_local_camera.js +18 -2
  20. package/lib/commonjs/omi_local_camera.js.map +1 -1
  21. package/lib/commonjs/omi_remote_camera.js +18 -2
  22. package/lib/commonjs/omi_remote_camera.js.map +1 -1
  23. package/lib/commonjs/omi_start_call_status.js +30 -0
  24. package/lib/commonjs/omi_start_call_status.js.map +1 -1
  25. package/lib/commonjs/omikit.js +125 -14
  26. package/lib/commonjs/omikit.js.map +1 -1
  27. package/lib/module/NativeOmikitPlugin.js +3 -0
  28. package/lib/module/NativeOmikitPlugin.js.map +1 -0
  29. package/lib/module/index.js +1 -0
  30. package/lib/module/index.js.map +1 -1
  31. package/lib/module/omi_audio_type.js +14 -0
  32. package/lib/module/omi_audio_type.js.map +1 -0
  33. package/lib/module/omi_local_camera.js +19 -2
  34. package/lib/module/omi_local_camera.js.map +1 -1
  35. package/lib/module/omi_remote_camera.js +19 -2
  36. package/lib/module/omi_remote_camera.js.map +1 -1
  37. package/lib/module/omi_start_call_status.js +30 -0
  38. package/lib/module/omi_start_call_status.js.map +1 -1
  39. package/lib/module/omikit.js +119 -15
  40. package/lib/module/omikit.js.map +1 -1
  41. package/omikit-plugin.podspec +26 -24
  42. package/package.json +11 -2
  43. package/src/NativeOmikitPlugin.ts +160 -0
  44. package/src/index.tsx +2 -1
  45. package/src/omi_audio_type.tsx +9 -0
  46. package/src/omi_local_camera.tsx +17 -3
  47. package/src/omi_remote_camera.tsx +17 -3
  48. package/src/omi_start_call_status.tsx +29 -10
  49. package/src/omikit.tsx +118 -28
  50. package/src/types/index.d.ts +111 -11
@@ -1,11 +1,25 @@
1
1
  import type { HostComponent } from 'react-native';
2
2
  import { NativeModules, requireNativeComponent, ViewProps } from 'react-native';
3
3
 
4
- const FLLocalCamera = NativeModules.FLLocalCameraView;
4
+ // Safe lazy loading — requireNativeComponent can throw in bridgeless mode
5
+ // if the native view is not registered for Fabric
6
+ let _localCameraView: HostComponent<ViewProps> | null = null;
7
+ const getLocalCameraView = (): HostComponent<ViewProps> => {
8
+ if (!_localCameraView) {
9
+ _localCameraView = requireNativeComponent('FLLocalCameraView');
10
+ }
11
+ return _localCameraView;
12
+ };
5
13
 
6
- export const OmiLocalCameraView: HostComponent<ViewProps> =
7
- requireNativeComponent('FLLocalCameraView');
14
+ export const OmiLocalCameraView = new Proxy({} as HostComponent<ViewProps>, {
15
+ get(_target, prop) {
16
+ return (getLocalCameraView() as any)[prop];
17
+ },
18
+ });
8
19
 
20
+ // Module name separated from ViewManager name to avoid name collision
21
+ const FLLocalCamera = NativeModules.FLLocalCameraModule || NativeModules.FLLocalCameraView;
9
22
  export function refreshLocalCamera(): Promise<boolean> {
23
+ if (!FLLocalCamera) return Promise.resolve(false);
10
24
  return FLLocalCamera.refresh();
11
25
  }
@@ -1,11 +1,25 @@
1
1
  import type { HostComponent } from 'react-native';
2
2
  import { NativeModules, requireNativeComponent, ViewProps } from 'react-native';
3
3
 
4
- const FLRemoteCamera = NativeModules.FLRemoteCameraView;
4
+ // Safe lazy loading — requireNativeComponent can throw in bridgeless mode
5
+ // if the native view is not registered for Fabric
6
+ let _remoteCameraView: HostComponent<ViewProps> | null = null;
7
+ const getRemoteCameraView = (): HostComponent<ViewProps> => {
8
+ if (!_remoteCameraView) {
9
+ _remoteCameraView = requireNativeComponent('FLRemoteCameraView');
10
+ }
11
+ return _remoteCameraView;
12
+ };
5
13
 
6
- export const OmiRemoteCameraView: HostComponent<ViewProps> =
7
- requireNativeComponent('FLRemoteCameraView');
14
+ export const OmiRemoteCameraView = new Proxy({} as HostComponent<ViewProps>, {
15
+ get(_target, prop) {
16
+ return (getRemoteCameraView() as any)[prop];
17
+ },
18
+ });
8
19
 
20
+ // Module name separated from ViewManager name to avoid name collision
21
+ const FLRemoteCamera = NativeModules.FLRemoteCameraModule || NativeModules.FLRemoteCameraView;
9
22
  export function refreshRemoteCamera(): Promise<boolean> {
23
+ if (!FLRemoteCamera) return Promise.resolve(false);
10
24
  return FLRemoteCamera.refresh();
11
25
  }
@@ -1,12 +1,31 @@
1
+ /**
2
+ * Status codes returned by startCall() function
3
+ * Use these to handle different call initiation results
4
+ */
1
5
  export enum OmiStartCallStatus {
2
- invalidUuid = 0,
3
- invalidPhoneNumber = 1,
4
- samePhoneNumber = 2,
5
- maxRetry = 3,
6
- permissionDenied = 4,
7
- couldNotFindEndpoint = 5,
8
- accountRegisterFailed = 6,
9
- startCallFailed = 7,
10
- startCallSuccess = 8,
11
- haveAnotherCall = 9,
6
+ // Validation errors (0-3)
7
+ invalidUuid = 0, // Invalid user UUID
8
+ invalidPhoneNumber = 1, // Invalid phone number format
9
+ samePhoneNumber = 2, // Cannot call same phone number
10
+ maxRetry = 3, // Maximum retry attempts reached
11
+
12
+ // Permission errors (4, 450-452)
13
+ permissionDenied = 4, // Microphone/Camera permission denied
14
+ permissionMicrophone = 450, // Microphone permission required (Android 15+)
15
+ permissionCamera = 451, // Camera permission required (Android 15+)
16
+ permissionOverlay = 452, // System alert window permission required (Android 15+)
17
+
18
+ // Call errors (5-7)
19
+ couldNotFindEndpoint = 5, // Could not find endpoint
20
+ accountRegisterFailed = 6, // Account registration failed
21
+ startCallFailed = 7, // Start call failed
22
+
23
+ // Success statuses (8, 407)
24
+ startCallSuccess = 8, // Call initiated successfully (Android)
25
+ startCallSuccessIOS = 407, // Call initiated successfully (iOS)
26
+
27
+ // Other errors (9+)
28
+ haveAnotherCall = 9, // Already have another call in progress
29
+ accountTurnOffNumberInternal = 10, // Internal number has been deactivated
30
+ noNetwork = 11, // No network connection available
12
31
  }
package/src/omikit.tsx CHANGED
@@ -1,4 +1,5 @@
1
- import { NativeModules, Platform, NativeEventEmitter, DeviceEventEmitter } from 'react-native';
1
+ import { NativeModules, Platform, NativeEventEmitter, DeviceEventEmitter, TurboModuleRegistry } from 'react-native';
2
+ import type { Spec } from './NativeOmikitPlugin';
2
3
 
3
4
  const LINKING_ERROR =
4
5
  `The package 'omikit-plugin' doesn't seem to be linked. Make sure: \n\n` +
@@ -6,22 +7,52 @@ const LINKING_ERROR =
6
7
  '- You rebuilt the app after installing the package\n' +
7
8
  '- You are not using Expo Go\n';
8
9
 
9
- // Khai báo chính xác Native Module
10
- const OmikitPlugin = NativeModules.OmikitPlugin
11
- ? NativeModules.OmikitPlugin
12
- : new Proxy(
13
- {},
14
- {
15
- get() {
16
- throw new Error(LINKING_ERROR);
17
- },
18
- }
19
- );
10
+ // Resolve native module: TurboModule (New Arch) → NativeModules (Old Arch) → null
11
+ const resolvedModule: Spec | null = (() => {
12
+ try {
13
+ // Try TurboModule first (New Architecture / bridgeless mode)
14
+ const turboModule = TurboModuleRegistry.get<Spec>('OmikitPlugin');
15
+ if (turboModule) return turboModule;
16
+ } catch (_) {}
17
+
18
+ // Fallback to NativeModules (Old Architecture / bridge mode)
19
+ if (NativeModules.OmikitPlugin) {
20
+ return NativeModules.OmikitPlugin;
21
+ }
20
22
 
21
- // ✅ Setup omiEmitter cho iOS và Android
22
- const omiEmitter = Platform.OS === 'ios'
23
- ? new NativeEventEmitter(OmikitPlugin)
24
- : DeviceEventEmitter;
23
+ return null;
24
+ })();
25
+
26
+ // Wrap in Proxy that throws LINKING_ERROR only when SDK methods are actually called
27
+ const OmikitPlugin: Spec = resolvedModule || new Proxy(
28
+ {} as Spec,
29
+ {
30
+ get(_target, prop) {
31
+ if (prop === 'addListener' || prop === 'removeListeners') {
32
+ return () => {};
33
+ }
34
+ throw new Error(LINKING_ERROR);
35
+ },
36
+ }
37
+ );
38
+
39
+ // Setup omiEmitter — safe for Old Arch, New Arch, and bridgeless mode
40
+ const omiEmitter = (() => {
41
+ if (Platform.OS !== 'ios') {
42
+ return DeviceEventEmitter;
43
+ }
44
+ try {
45
+ // Best case: NativeEventEmitter with resolved native module
46
+ if (resolvedModule) {
47
+ return new NativeEventEmitter(resolvedModule as any);
48
+ }
49
+ // New Arch without interop: NativeEventEmitter without module arg (RN 0.74+)
50
+ return new NativeEventEmitter();
51
+ } catch (_) {
52
+ // Last resort fallback
53
+ return DeviceEventEmitter;
54
+ }
55
+ })();
25
56
 
26
57
  /**
27
58
  * Starts the Omikit services.
@@ -41,14 +72,14 @@ export function configPushNotification(data: any): Promise<any> {
41
72
  }
42
73
 
43
74
  /**
44
- * Retrieves the initial call details when start call
75
+ * Retrieves the initial call details when start call
45
76
  * @returns {Promise<any>} A promise containing the initial call details.
46
77
  */
47
78
  export function getInitialCall(): Promise<any> {
48
79
  if (Platform.OS == "ios") {
49
- return OmikitPlugin.getInitialCall();
80
+ return OmikitPlugin.getInitialCall({ counter: 0 });
50
81
  } else {
51
- return OmikitPlugin.getInitialCall(4);
82
+ return OmikitPlugin.getInitialCall({ counter: 4 });
52
83
  }
53
84
  }
54
85
 
@@ -73,9 +104,9 @@ export function initCallWithApiKey(data: any): Promise<boolean> {
73
104
  /**
74
105
  * Starts a new call with the given data.
75
106
  * @param {any} data - Call configuration data.
76
- * @returns {Promise<boolean>} A promise that resolves to `true` if the call starts successfully.
107
+ * @returns {Promise<any>} A promise that resolves with call details if successful.
77
108
  */
78
- export function startCall(data: any): Promise<boolean> {
109
+ export function startCall(data: any): Promise<any> {
79
110
  return OmikitPlugin.startCall(data);
80
111
  }
81
112
 
@@ -106,9 +137,9 @@ export function endCall(): Promise<any> {
106
137
 
107
138
  /**
108
139
  * Toggles the mute status of the microphone.
109
- * @returns {Promise<boolean>} A promise that resolves to `true` if the microphone is muted, `false` otherwise.
140
+ * @returns {Promise<boolean | null>} A promise that resolves to `true` if the microphone is muted, `false` otherwise, or `null` if unavailable.
110
141
  */
111
- export function toggleMute(): Promise<boolean> {
142
+ export function toggleMute(): Promise<boolean | null> {
112
143
  return OmikitPlugin.toggleMute();
113
144
  }
114
145
 
@@ -122,9 +153,9 @@ export function toggleSpeaker(): Promise<boolean> {
122
153
 
123
154
  /**
124
155
  * Toggles the hold call.
125
- * @returns {Promise<boolean>} A promise that resolves to `true` if when hold call success, `false` otherwise.
156
+ * @returns {Promise<void>} A promise that resolves when hold call is toggled.
126
157
  */
127
- export function toggleHold(): Promise<boolean> {
158
+ export function toggleHold(): Promise<void> {
128
159
  return OmikitPlugin.toggleHold();
129
160
  }
130
161
 
@@ -282,7 +313,7 @@ export function hideSystemNotificationOnly(): Promise<boolean> {
282
313
  }
283
314
 
284
315
  export function hideSystemNotificationAndUnregister(reason: string): Promise<boolean> {
285
- return OmikitPlugin.hideSystemNotificationAndUnregister(reason);
316
+ return OmikitPlugin.hideSystemNotificationAndUnregister({ reason });
286
317
  }
287
318
 
288
319
  export const OmiCallEvent = {
@@ -338,7 +369,7 @@ export function checkAndRequestPermissions(isVideo: boolean = false): Promise<bo
338
369
  if (Platform.OS !== 'android') {
339
370
  return Promise.resolve(true);
340
371
  }
341
- return OmikitPlugin.checkAndRequestPermissions(isVideo);
372
+ return OmikitPlugin.checkAndRequestPermissions({ isVideo });
342
373
  }
343
374
 
344
375
  /**
@@ -362,6 +393,65 @@ export function requestPermissionsByCodes(codes: number[]): Promise<boolean> {
362
393
  if (Platform.OS !== 'android') {
363
394
  return Promise.resolve(true);
364
395
  }
365
- return OmikitPlugin.requestPermissionsByCodes(codes);
396
+ return OmikitPlugin.requestPermissionsByCodes({ codes });
397
+ }
398
+
399
+ // MARK: - Getter Functions
400
+
401
+ /**
402
+ * Retrieves user info by phone number.
403
+ * @param {string} phone - The phone number to look up.
404
+ * @returns {Promise<any>} User info object or null.
405
+ */
406
+ export function getUserInfo(phone: string): Promise<any> {
407
+ return OmikitPlugin.getUserInfo({ phone });
408
+ }
409
+
410
+ /**
411
+ * Retrieves the project ID from OmiClient.
412
+ * @returns {Promise<string | null>} The project ID or null.
413
+ */
414
+ export function getProjectId(): Promise<string | null> {
415
+ return OmikitPlugin.getProjectId();
416
+ }
417
+
418
+ /**
419
+ * Retrieves SIP connection info (user@realm).
420
+ * @returns {Promise<string | null>} SIP info string or null.
421
+ */
422
+ export function getSipInfo(): Promise<string | null> {
423
+ return OmikitPlugin.getSipInfo();
424
+ }
425
+
426
+ /**
427
+ * Retrieves the app ID from OmiClient.
428
+ * @returns {Promise<string | null>} The app ID or null.
429
+ */
430
+ export function getAppId(): Promise<string | null> {
431
+ return OmikitPlugin.getAppId();
432
+ }
433
+
434
+ /**
435
+ * Retrieves the device ID from OmiClient.
436
+ * @returns {Promise<string | null>} The device ID or null.
437
+ */
438
+ export function getDeviceId(): Promise<string | null> {
439
+ return OmikitPlugin.getDeviceId();
440
+ }
441
+
442
+ /**
443
+ * Retrieves the FCM token from OmiClient.
444
+ * @returns {Promise<string | null>} The FCM token or null.
445
+ */
446
+ export function getFcmToken(): Promise<string | null> {
447
+ return OmikitPlugin.getFcmToken();
448
+ }
449
+
450
+ /**
451
+ * Retrieves the VoIP token (iOS only, Android returns null).
452
+ * @returns {Promise<string | null>} The VoIP token or null.
453
+ */
454
+ export function getVoipToken(): Promise<string | null> {
455
+ return OmikitPlugin.getVoipToken();
366
456
  }
367
457
 
@@ -1,12 +1,30 @@
1
1
  declare module 'omikit-plugin' {
2
2
  import { NativeEventEmitter } from 'react-native';
3
3
 
4
+ // ============================================
5
+ // FUNCTIONS
6
+ // ============================================
7
+
4
8
  export function startServices(): Promise<any>;
5
9
  export function configPushNotification(data: any): Promise<any>;
6
10
  export function getInitialCall(): Promise<any>;
7
11
  export function initCallWithUserPassword(data: any): Promise<boolean>;
8
12
  export function initCallWithApiKey(data: any): Promise<boolean>;
9
- export function startCall(data: any): Promise<boolean>;
13
+
14
+ /**
15
+ * Starts a new call
16
+ * @param data - Call configuration { phoneNumber: string, isVideo: boolean }
17
+ * @returns Promise with call result { status: OmiStartCallStatus, message?: string, _id?: string }
18
+ */
19
+ export function startCall(data: {
20
+ phoneNumber: string;
21
+ isVideo: boolean;
22
+ }): Promise<{
23
+ status: OmiStartCallStatus | number | string;
24
+ message?: string;
25
+ _id?: string;
26
+ }>;
27
+
10
28
  export function startCallWithUuid(data: any): Promise<boolean>;
11
29
  export function joinCall(): Promise<any>;
12
30
  export function endCall(): Promise<any>;
@@ -25,30 +43,112 @@ declare module 'omikit-plugin' {
25
43
  export function systemAlertWindow(): Promise<boolean>;
26
44
  export function openSystemAlertSetting(): Promise<void>;
27
45
  export function getAudio(): Promise<any>;
28
- export function setAudio(data: any): Promise<void>;
46
+ export function setAudio(data: { portType: OmiAudioType | number }): Promise<void>;
29
47
  export function getCurrentAudio(): Promise<any>;
30
48
  export function transferCall(data: any): Promise<boolean>;
31
49
  export function rejectCall(): Promise<boolean>;
32
50
  export function dropCall(): Promise<boolean>;
33
- export function testEventEmission(): Promise<boolean>;
34
51
  export function getKeepAliveStatus(): Promise<any>;
35
52
  export function triggerKeepAlivePing(): Promise<boolean>;
36
53
  export function checkPermissionStatus(): Promise<any>;
37
54
  export function checkAndRequestPermissions(isVideo?: boolean): Promise<boolean>;
38
55
  export function requestSystemAlertWindowPermission(): Promise<boolean>;
39
56
  export function requestPermissionsByCodes(codes: number[]): Promise<boolean>;
57
+ export function hideSystemNotificationSafely(): Promise<boolean>;
58
+ export function hideSystemNotificationOnly(): Promise<boolean>;
59
+ export function hideSystemNotificationAndUnregister(reason: string): Promise<boolean>;
60
+ export function checkCredentials(data: any): Promise<{
61
+ success: boolean;
62
+ statusCode?: number;
63
+ message?: string;
64
+ }>;
65
+ export function registerWithOptions(data: any): Promise<{
66
+ success: boolean;
67
+ statusCode?: number;
68
+ message?: string;
69
+ }>;
70
+
71
+ // User & Info
72
+ export function getUserInfo(phone: string): Promise<any>;
40
73
 
74
+ // Getter Functions
75
+ /** Get the current project ID */
76
+ export function getProjectId(): Promise<string | null>;
77
+ /** Get the current app ID */
78
+ export function getAppId(): Promise<string | null>;
79
+ /** Get the current device ID */
80
+ export function getDeviceId(): Promise<string | null>;
81
+ /** Get the FCM token (Android) or push token */
82
+ export function getFcmToken(): Promise<string | null>;
83
+ /** Get SIP registration info (format: user@realm) */
84
+ export function getSipInfo(): Promise<string | null>;
85
+ /** Get VoIP token (iOS only, returns null on Android) */
86
+ export function getVoipToken(): Promise<string | null>;
87
+
88
+ // ============================================
89
+ // ENUMS
90
+ // ============================================
91
+
92
+ /**
93
+ * Call state enum for tracking call lifecycle
94
+ */
41
95
  export enum OmiCallState {
42
- unknown,
43
- calling,
44
- incoming,
45
- early,
46
- connecting,
47
- confirmed,
48
- disconnected,
49
- hold,
96
+ unknown = 0,
97
+ calling = 1,
98
+ incoming = 2,
99
+ early = 3,
100
+ connecting = 4,
101
+ confirmed = 5,
102
+ disconnected = 6,
103
+ hold = 7,
50
104
  }
51
105
 
106
+ /**
107
+ * Status codes returned by startCall() function
108
+ * Use these to handle different call initiation results
109
+ */
110
+ export enum OmiStartCallStatus {
111
+ // Validation errors (0-3)
112
+ invalidUuid = 0,
113
+ invalidPhoneNumber = 1,
114
+ samePhoneNumber = 2,
115
+ maxRetry = 3,
116
+
117
+ // Permission errors (4, 450-452)
118
+ permissionDenied = 4,
119
+ permissionMicrophone = 450,
120
+ permissionCamera = 451,
121
+ permissionOverlay = 452,
122
+
123
+ // Call errors (5-7)
124
+ couldNotFindEndpoint = 5,
125
+ accountRegisterFailed = 6,
126
+ startCallFailed = 7,
127
+
128
+ // Success statuses (8, 407)
129
+ startCallSuccess = 8,
130
+ startCallSuccessIOS = 407,
131
+
132
+ // Other errors (9+)
133
+ haveAnotherCall = 9,
134
+ accountTurnOffNumberInternal = 10,
135
+ noNetwork = 11,
136
+ }
137
+
138
+ /**
139
+ * Audio output types for setAudio()
140
+ */
141
+ export enum OmiAudioType {
142
+ receiver = 0,
143
+ speaker = 1,
144
+ bluetooth = 2,
145
+ headphones = 3,
146
+ }
147
+
148
+ // ============================================
149
+ // CONSTANTS & EVENTS
150
+ // ============================================
151
+
52
152
  export const OmiCallEvent: {
53
153
  onCallStateChanged: string;
54
154
  onSpeaker: string;