@kaleem766/react-native-incoming-call 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/IncomingCall.podspec +29 -0
- package/LICENSE +20 -0
- package/README.md +280 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +118 -0
- package/android/src/main/AndroidManifest.xml +35 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/incomingcall/IncomingCall.kt +219 -0
- package/android/src/main/java/com/margelo/nitro/incomingcall/IncomingCallActivity.kt +314 -0
- package/android/src/main/java/com/margelo/nitro/incomingcall/IncomingCallModule.kt +152 -0
- package/android/src/main/java/com/margelo/nitro/incomingcall/IncomingCallPackage.kt +31 -0
- package/android/src/main/java/com/margelo/nitro/incomingcall/IncomingCallService.kt +109 -0
- package/ios/IncomingCall.swift +28 -0
- package/lib/module/IncomingCall.nitro.js +4 -0
- package/lib/module/IncomingCall.nitro.js.map +1 -0
- package/lib/module/index.js +137 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/IncomingCall.nitro.d.ts +21 -0
- package/lib/typescript/src/IncomingCall.nitro.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +43 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/nitro.json +17 -0
- package/nitrogen/generated/android/c++/JHybridIncomingCallSpec.cpp +101 -0
- package/nitrogen/generated/android/c++/JHybridIncomingCallSpec.hpp +73 -0
- package/nitrogen/generated/android/c++/views/JHybridIncomingCallStateUpdater.cpp +72 -0
- package/nitrogen/generated/android/c++/views/JHybridIncomingCallStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/incomingcall+autolinking.cmake +83 -0
- package/nitrogen/generated/android/incomingcall+autolinking.gradle +27 -0
- package/nitrogen/generated/android/incomingcallOnLoad.cpp +56 -0
- package/nitrogen/generated/android/incomingcallOnLoad.hpp +34 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/incomingcall/HybridIncomingCallSpec.kt +87 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/incomingcall/incomingcallOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/incomingcall/views/HybridIncomingCallManager.kt +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/incomingcall/views/HybridIncomingCallStateUpdater.kt +23 -0
- package/nitrogen/generated/ios/IncomingCall+autolinking.rb +60 -0
- package/nitrogen/generated/ios/IncomingCall-Swift-Cxx-Bridge.cpp +33 -0
- package/nitrogen/generated/ios/IncomingCall-Swift-Cxx-Bridge.hpp +83 -0
- package/nitrogen/generated/ios/IncomingCall-Swift-Cxx-Umbrella.hpp +45 -0
- package/nitrogen/generated/ios/IncomingCallAutolinking.mm +33 -0
- package/nitrogen/generated/ios/IncomingCallAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridIncomingCallSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridIncomingCallSpecSwift.hpp +121 -0
- package/nitrogen/generated/ios/c++/views/HybridIncomingCallComponent.mm +127 -0
- package/nitrogen/generated/ios/swift/HybridIncomingCallSpec.swift +60 -0
- package/nitrogen/generated/ios/swift/HybridIncomingCallSpec_cxx.swift +270 -0
- package/nitrogen/generated/shared/c++/HybridIncomingCallSpec.cpp +32 -0
- package/nitrogen/generated/shared/c++/HybridIncomingCallSpec.hpp +73 -0
- package/nitrogen/generated/shared/c++/views/HybridIncomingCallComponent.cpp +127 -0
- package/nitrogen/generated/shared/c++/views/HybridIncomingCallComponent.hpp +115 -0
- package/nitrogen/generated/shared/json/IncomingCallConfig.json +14 -0
- package/package.json +180 -0
- package/src/IncomingCall.nitro.ts +27 -0
- package/src/index.tsx +173 -0
package/package.json
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kaleem766/react-native-incoming-call",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React Native incoming call UI for Android and iOS, built with Nitro Modules",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"android",
|
|
19
|
+
"ios",
|
|
20
|
+
"cpp",
|
|
21
|
+
"nitrogen",
|
|
22
|
+
"nitro.json",
|
|
23
|
+
"*.podspec",
|
|
24
|
+
"react-native.config.js",
|
|
25
|
+
"!ios/build",
|
|
26
|
+
"!android/build",
|
|
27
|
+
"!android/gradle",
|
|
28
|
+
"!android/gradlew",
|
|
29
|
+
"!android/gradlew.bat",
|
|
30
|
+
"!android/local.properties",
|
|
31
|
+
"!**/__tests__",
|
|
32
|
+
"!**/__fixtures__",
|
|
33
|
+
"!**/__mocks__",
|
|
34
|
+
"!**/.*"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"example": "yarn workspace react-native-incoming-call-example",
|
|
38
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
39
|
+
"prepare": "bob build",
|
|
40
|
+
"nitrogen": "nitrogen",
|
|
41
|
+
"typecheck": "tsc",
|
|
42
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
43
|
+
"test": "jest",
|
|
44
|
+
"release": "release-it --only-version"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"react-native",
|
|
48
|
+
"ios",
|
|
49
|
+
"android",
|
|
50
|
+
"incoming-call",
|
|
51
|
+
"call-ui",
|
|
52
|
+
"voip",
|
|
53
|
+
"nitro-modules",
|
|
54
|
+
"phone-call"
|
|
55
|
+
],
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/Muhammadkaleem/react-native-incoming-call.git"
|
|
59
|
+
},
|
|
60
|
+
"author": "MuhammadKaleem <kaleembhattii766@gmail.com> (https://www.github.com/Muhammadkaleem)",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/Muhammadkaleem/react-native-incoming-call/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/Muhammadkaleem/react-native-incoming-call#readme",
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"registry": "https://registry.npmjs.org/"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
71
|
+
"@eslint/compat": "^1.3.2",
|
|
72
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
73
|
+
"@eslint/js": "^9.35.0",
|
|
74
|
+
"@react-native/babel-preset": "0.83.0",
|
|
75
|
+
"@react-native/eslint-config": "0.83.0",
|
|
76
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
77
|
+
"@types/jest": "^29.5.14",
|
|
78
|
+
"@types/react": "^19.2.0",
|
|
79
|
+
"commitlint": "^19.8.1",
|
|
80
|
+
"del-cli": "^6.0.0",
|
|
81
|
+
"eslint": "^9.35.0",
|
|
82
|
+
"eslint-config-prettier": "^10.1.8",
|
|
83
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
84
|
+
"eslint-plugin-react-native": "^5.0.0",
|
|
85
|
+
"jest": "^29.7.0",
|
|
86
|
+
"lefthook": "^2.0.3",
|
|
87
|
+
"nitrogen": "^0.35.0",
|
|
88
|
+
"prettier": "^2.8.8",
|
|
89
|
+
"react": "19.2.0",
|
|
90
|
+
"react-native": "0.83.0",
|
|
91
|
+
"react-native-builder-bob": "^0.40.18",
|
|
92
|
+
"react-native-nitro-modules": "^0.35.0",
|
|
93
|
+
"release-it": "^19.0.4",
|
|
94
|
+
"turbo": "^2.5.6",
|
|
95
|
+
"typescript": "^5.9.2"
|
|
96
|
+
},
|
|
97
|
+
"peerDependencies": {
|
|
98
|
+
"react": "*",
|
|
99
|
+
"react-native": "*",
|
|
100
|
+
"react-native-nitro-modules": "^0.35.0"
|
|
101
|
+
},
|
|
102
|
+
"workspaces": [
|
|
103
|
+
"example"
|
|
104
|
+
],
|
|
105
|
+
"packageManager": "yarn@4.11.0",
|
|
106
|
+
"react-native-builder-bob": {
|
|
107
|
+
"source": "src",
|
|
108
|
+
"output": "lib",
|
|
109
|
+
"targets": [
|
|
110
|
+
[
|
|
111
|
+
"custom",
|
|
112
|
+
{
|
|
113
|
+
"script": "nitrogen",
|
|
114
|
+
"clean": "nitrogen/"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
"module",
|
|
119
|
+
{
|
|
120
|
+
"esm": true
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
[
|
|
124
|
+
"typescript",
|
|
125
|
+
{
|
|
126
|
+
"project": "tsconfig.build.json"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
]
|
|
130
|
+
},
|
|
131
|
+
"prettier": {
|
|
132
|
+
"quoteProps": "consistent",
|
|
133
|
+
"singleQuote": true,
|
|
134
|
+
"tabWidth": 2,
|
|
135
|
+
"trailingComma": "es5",
|
|
136
|
+
"useTabs": false
|
|
137
|
+
},
|
|
138
|
+
"jest": {
|
|
139
|
+
"preset": "react-native",
|
|
140
|
+
"modulePathIgnorePatterns": [
|
|
141
|
+
"<rootDir>/example/node_modules",
|
|
142
|
+
"<rootDir>/lib/"
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
"commitlint": {
|
|
146
|
+
"extends": [
|
|
147
|
+
"@commitlint/config-conventional"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
"release-it": {
|
|
151
|
+
"git": {
|
|
152
|
+
"commitMessage": "chore: release ${version}",
|
|
153
|
+
"tagName": "v${version}"
|
|
154
|
+
},
|
|
155
|
+
"npm": {
|
|
156
|
+
"publish": true
|
|
157
|
+
},
|
|
158
|
+
"github": {
|
|
159
|
+
"release": true
|
|
160
|
+
},
|
|
161
|
+
"plugins": {
|
|
162
|
+
"@release-it/conventional-changelog": {
|
|
163
|
+
"preset": {
|
|
164
|
+
"name": "angular"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"create-react-native-library": {
|
|
170
|
+
"type": "nitro-view",
|
|
171
|
+
"languages": "kotlin-swift",
|
|
172
|
+
"tools": [
|
|
173
|
+
"eslint",
|
|
174
|
+
"jest",
|
|
175
|
+
"lefthook",
|
|
176
|
+
"release-it"
|
|
177
|
+
],
|
|
178
|
+
"version": "0.57.2"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
HybridView,
|
|
3
|
+
HybridViewMethods,
|
|
4
|
+
HybridViewProps,
|
|
5
|
+
} from 'react-native-nitro-modules';
|
|
6
|
+
|
|
7
|
+
export interface IncomingCallProps extends HybridViewProps {
|
|
8
|
+
/** Background color of the call screen (CSS hex, e.g. "#1A1A2E") */
|
|
9
|
+
color: string;
|
|
10
|
+
/** Caller's display name */
|
|
11
|
+
callerName?: string;
|
|
12
|
+
/** Remote avatar URL */
|
|
13
|
+
avatar?: string;
|
|
14
|
+
/** "audio" | "video" – defaults to "audio" */
|
|
15
|
+
callType?: string;
|
|
16
|
+
/** Auto-reject timeout in milliseconds – defaults to 30000 */
|
|
17
|
+
timeout?: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface IncomingCallMethods extends HybridViewMethods {
|
|
21
|
+
/** Programmatically answer the call rendered in this view */
|
|
22
|
+
answerCall(): void;
|
|
23
|
+
/** Programmatically reject the call rendered in this view */
|
|
24
|
+
rejectCall(): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type IncomingCall = HybridView<IncomingCallProps, IncomingCallMethods>;
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { getHostComponent } from 'react-native-nitro-modules';
|
|
2
|
+
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
3
|
+
const IncomingCallConfig = require('../nitrogen/generated/shared/json/IncomingCallConfig.json');
|
|
4
|
+
import type {
|
|
5
|
+
IncomingCallMethods,
|
|
6
|
+
IncomingCallProps,
|
|
7
|
+
} from './IncomingCall.nitro';
|
|
8
|
+
|
|
9
|
+
export const IncomingCallView = getHostComponent<
|
|
10
|
+
IncomingCallProps,
|
|
11
|
+
IncomingCallMethods
|
|
12
|
+
>('IncomingCall', () => IncomingCallConfig);
|
|
13
|
+
|
|
14
|
+
// Types for the API
|
|
15
|
+
export interface IncomingCallDisplayOptions {
|
|
16
|
+
uuid: string;
|
|
17
|
+
callerName: string;
|
|
18
|
+
avatar?: string;
|
|
19
|
+
callType?: 'audio' | 'video';
|
|
20
|
+
backgroundColor?: string;
|
|
21
|
+
timeout?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type IncomingCallEventType = 'onAnswer' | 'onReject' | 'onTimeout';
|
|
25
|
+
|
|
26
|
+
export interface IncomingCallEventData {
|
|
27
|
+
uuid: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Event emitter for handling incoming call events
|
|
32
|
+
class IncomingCallEventManager {
|
|
33
|
+
private eventEmitter: NativeEventEmitter | undefined;
|
|
34
|
+
private listeners: Map<IncomingCallEventType, Set<(data: IncomingCallEventData) => void>> = new Map();
|
|
35
|
+
|
|
36
|
+
constructor() {
|
|
37
|
+
if (Platform.OS === 'android' && NativeModules.IncomingCallModule) {
|
|
38
|
+
this.eventEmitter = new NativeEventEmitter(NativeModules.IncomingCallModule);
|
|
39
|
+
this.setupNativeListeners();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private setupNativeListeners() {
|
|
44
|
+
if (!this.eventEmitter) return;
|
|
45
|
+
|
|
46
|
+
this.eventEmitter.addListener('onAnswer', (data: any) => {
|
|
47
|
+
this.emit('onAnswer', data as IncomingCallEventData);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
this.eventEmitter.addListener('onReject', (data: any) => {
|
|
51
|
+
this.emit('onReject', data as IncomingCallEventData);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
this.eventEmitter.addListener('onTimeout', (data: any) => {
|
|
55
|
+
this.emit('onTimeout', data as IncomingCallEventData);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private emit(event: IncomingCallEventType, data: IncomingCallEventData) {
|
|
60
|
+
const listeners = this.listeners.get(event);
|
|
61
|
+
if (listeners) {
|
|
62
|
+
listeners.forEach(listener => listener(data));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
addEventListener(event: IncomingCallEventType, listener: (data: IncomingCallEventData) => void) {
|
|
67
|
+
if (!this.listeners.has(event)) {
|
|
68
|
+
this.listeners.set(event, new Set());
|
|
69
|
+
}
|
|
70
|
+
this.listeners.get(event)!.add(listener);
|
|
71
|
+
|
|
72
|
+
// Return unsubscribe function
|
|
73
|
+
return () => {
|
|
74
|
+
this.listeners.get(event)?.delete(listener);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
removeEventListener(event: IncomingCallEventType, listener: (data: IncomingCallEventData) => void) {
|
|
79
|
+
this.listeners.get(event)?.delete(listener);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const eventManager = new IncomingCallEventManager();
|
|
84
|
+
|
|
85
|
+
// Main API class
|
|
86
|
+
export class IncomingCall {
|
|
87
|
+
/**
|
|
88
|
+
* Display an incoming call screen
|
|
89
|
+
*/
|
|
90
|
+
static async display(options: IncomingCallDisplayOptions): Promise<void> {
|
|
91
|
+
try {
|
|
92
|
+
if (Platform.OS === 'android' && NativeModules.IncomingCallModule) {
|
|
93
|
+
return await NativeModules.IncomingCallModule.displayIncomingCall(options);
|
|
94
|
+
} else {
|
|
95
|
+
console.warn('IncomingCall: Native module not available');
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error('IncomingCall: Failed to display call', error);
|
|
99
|
+
throw error;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Answer the current incoming call
|
|
105
|
+
*/
|
|
106
|
+
static async answer(uuid: string): Promise<void> {
|
|
107
|
+
try {
|
|
108
|
+
if (Platform.OS === 'android' && NativeModules.IncomingCallModule) {
|
|
109
|
+
return await NativeModules.IncomingCallModule.answerCall(uuid);
|
|
110
|
+
} else {
|
|
111
|
+
console.warn('IncomingCall: Native module not available');
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error('IncomingCall: Failed to answer call', error);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Reject the current incoming call
|
|
121
|
+
*/
|
|
122
|
+
static async reject(uuid: string): Promise<void> {
|
|
123
|
+
try {
|
|
124
|
+
if (Platform.OS === 'android' && NativeModules.IncomingCallModule) {
|
|
125
|
+
return await NativeModules.IncomingCallModule.rejectCall(uuid);
|
|
126
|
+
} else {
|
|
127
|
+
console.warn('IncomingCall: Native module not available');
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('IncomingCall: Failed to reject call', error);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* End an ongoing call
|
|
137
|
+
*/
|
|
138
|
+
static async end(uuid: string): Promise<void> {
|
|
139
|
+
try {
|
|
140
|
+
if (Platform.OS === 'android' && NativeModules.IncomingCallModule) {
|
|
141
|
+
return await NativeModules.IncomingCallModule.endCall(uuid);
|
|
142
|
+
} else {
|
|
143
|
+
console.warn('IncomingCall: Native module not available');
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('IncomingCall: Failed to end call', error);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Add event listener for call events
|
|
153
|
+
*/
|
|
154
|
+
static addEventListener(
|
|
155
|
+
event: IncomingCallEventType,
|
|
156
|
+
listener: (data: IncomingCallEventData) => void
|
|
157
|
+
): () => void {
|
|
158
|
+
return eventManager.addEventListener(event, listener);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Remove event listener for call events
|
|
163
|
+
*/
|
|
164
|
+
static removeEventListener(
|
|
165
|
+
event: IncomingCallEventType,
|
|
166
|
+
listener: (data: IncomingCallEventData) => void
|
|
167
|
+
): void {
|
|
168
|
+
eventManager.removeEventListener(event, listener);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Default export
|
|
173
|
+
export default IncomingCall;
|