react-native-telecom 0.0.0-stage → 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.
Files changed (57) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +309 -2
  3. package/Telecom.podspec +20 -0
  4. package/android/build.gradle +58 -0
  5. package/android/src/main/AndroidManifest.xml +43 -0
  6. package/android/src/main/java/com/telecom/CallSession.kt +37 -0
  7. package/android/src/main/java/com/telecom/CallSessionManager.kt +486 -0
  8. package/android/src/main/java/com/telecom/TelecomAudioRouter.kt +227 -0
  9. package/android/src/main/java/com/telecom/TelecomAvatarLoader.kt +77 -0
  10. package/android/src/main/java/com/telecom/TelecomCallService.kt +395 -0
  11. package/android/src/main/java/com/telecom/TelecomCallUi.kt +65 -0
  12. package/android/src/main/java/com/telecom/TelecomInCallActivity.kt +285 -0
  13. package/android/src/main/java/com/telecom/TelecomIncomingCallActivity.kt +171 -0
  14. package/android/src/main/java/com/telecom/TelecomModule.kt +189 -0
  15. package/android/src/main/java/com/telecom/TelecomPackage.kt +31 -0
  16. package/android/src/main/java/com/telecom/TelecomPushBridge.kt +82 -0
  17. package/android/src/main/java/com/telecom/TelecomRingtonePlayer.kt +109 -0
  18. package/android/src/main/java/com/telecom/TelecomUiConfig.kt +27 -0
  19. package/android/src/main/res/drawable/rn_telecom_action_pill.xml +6 -0
  20. package/android/src/main/res/drawable/rn_telecom_answer_circle.xml +8 -0
  21. package/android/src/main/res/drawable/rn_telecom_answer_circle_green.xml +8 -0
  22. package/android/src/main/res/drawable/rn_telecom_avatar_bg.xml +6 -0
  23. package/android/src/main/res/drawable/rn_telecom_avatar_circle.xml +12 -0
  24. package/android/src/main/res/drawable/rn_telecom_btn_answer.xml +6 -0
  25. package/android/src/main/res/drawable/rn_telecom_btn_decline.xml +6 -0
  26. package/android/src/main/res/drawable/rn_telecom_btn_message.xml +9 -0
  27. package/android/src/main/res/drawable/rn_telecom_btn_secondary.xml +6 -0
  28. package/android/src/main/res/drawable/rn_telecom_control_circle.xml +8 -0
  29. package/android/src/main/res/drawable/rn_telecom_control_circle_on.xml +8 -0
  30. package/android/src/main/res/drawable/rn_telecom_decline_circle.xml +8 -0
  31. package/android/src/main/res/drawable/rn_telecom_ic_call.xml +10 -0
  32. package/android/src/main/res/drawable/rn_telecom_ic_call_end.xml +16 -0
  33. package/android/src/main/res/drawable/rn_telecom_ic_call_white.xml +10 -0
  34. package/android/src/main/res/drawable/rn_telecom_ic_dialpad.xml +13 -0
  35. package/android/src/main/res/drawable/rn_telecom_ic_hold.xml +10 -0
  36. package/android/src/main/res/drawable/rn_telecom_ic_message.xml +10 -0
  37. package/android/src/main/res/drawable/rn_telecom_ic_mic.xml +10 -0
  38. package/android/src/main/res/drawable/rn_telecom_ic_mic_off.xml +10 -0
  39. package/android/src/main/res/drawable/rn_telecom_ic_speaker.xml +10 -0
  40. package/android/src/main/res/layout/rn_telecom_control_item.xml +36 -0
  41. package/android/src/main/res/layout/rn_telecom_incall.xml +168 -0
  42. package/android/src/main/res/layout/rn_telecom_incoming_call.xml +188 -0
  43. package/ios/Telecom.h +5 -0
  44. package/ios/Telecom.mm +66 -0
  45. package/lib/module/NativeTelecom.js +5 -0
  46. package/lib/module/NativeTelecom.js.map +1 -0
  47. package/lib/module/index.js +102 -0
  48. package/lib/module/index.js.map +1 -0
  49. package/lib/module/package.json +1 -0
  50. package/lib/typescript/package.json +1 -0
  51. package/lib/typescript/src/NativeTelecom.d.ts +40 -0
  52. package/lib/typescript/src/NativeTelecom.d.ts.map +1 -0
  53. package/lib/typescript/src/index.d.ts +104 -0
  54. package/lib/typescript/src/index.d.ts.map +1 -0
  55. package/package.json +153 -4
  56. package/src/NativeTelecom.ts +55 -0
  57. package/src/index.tsx +220 -0
package/package.json CHANGED
@@ -1,6 +1,155 @@
1
1
  {
2
2
  "name": "react-native-telecom",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Modern react-native-callkeep alternative for React Native New Architecture. Android Jetpack Core-Telecom, CallStyle notifications, lock-screen incoming call UI, VoIP ringtone, mute, hold, DTMF, Bluetooth audio routes, FCM wake. TurboModule. Works with Telnyx, WebRTC, LiveKit.",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./lib/typescript/src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "react-native-telecom-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
+ "*.podspec",
22
+ "react-native.config.js",
23
+ "!ios/build",
24
+ "!android/build",
25
+ "!android/gradle",
26
+ "!android/gradlew",
27
+ "!android/gradlew.bat",
28
+ "!android/local.properties",
29
+ "!**/__tests__",
30
+ "!**/__fixtures__",
31
+ "!**/__mocks__",
32
+ "!**/.*"
33
+ ],
34
+ "scripts": {
35
+ "example": "yarn workspace react-native-telecom-example",
36
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
37
+ "prepare": "bob build",
38
+ "typecheck": "tsc",
39
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
40
+ },
41
+ "keywords": [
42
+ "react-native",
43
+ "react-native-callkeep",
44
+ "callkeep",
45
+ "callkeep-alternative",
46
+ "voip",
47
+ "telecom",
48
+ "core-telecom",
49
+ "connection-service",
50
+ "callstyle",
51
+ "incoming-call",
52
+ "outgoing-call",
53
+ "call-notification",
54
+ "full-screen-intent",
55
+ "lock-screen",
56
+ "ringtone",
57
+ "webrtc",
58
+ "telnyx",
59
+ "livekit",
60
+ "twilio",
61
+ "sip",
62
+ "dtmf",
63
+ "bluetooth",
64
+ "fcm",
65
+ "push-notification",
66
+ "turbomodule",
67
+ "new-architecture",
68
+ "fabric",
69
+ "android",
70
+ "kotlin",
71
+ "calls",
72
+ "phone-call-ui"
73
+ ],
74
+ "repository": {
75
+ "type": "git",
76
+ "url": "git+https://github.com/itxmoizdev/react-native-telecom.git"
77
+ },
78
+ "author": "Abdul Moiz <princemoiz664@gmail.com> (https://github.com/itxmoizdev)",
79
+ "license": "MIT",
80
+ "bugs": {
81
+ "url": "https://github.com/itxmoizdev/react-native-telecom/issues"
82
+ },
83
+ "homepage": "https://github.com/itxmoizdev/react-native-telecom#readme",
84
+ "publishConfig": {
85
+ "registry": "https://registry.npmjs.org/"
86
+ },
87
+ "devDependencies": {
88
+ "@eslint/compat": "^2.1.0",
89
+ "@eslint/eslintrc": "^3.3.6",
90
+ "@eslint/js": "^9.39.5",
91
+ "@react-native/babel-preset": "0.87.1",
92
+ "@react-native/eslint-config": "0.86.2",
93
+ "@types/react": "^19.2.0",
94
+ "del-cli": "^7.0.0",
95
+ "eslint": "^9.39.5",
96
+ "eslint-config-prettier": "^10.1.8",
97
+ "eslint-plugin-ft-flow": "^3.0.11",
98
+ "eslint-plugin-prettier": "^5.5.6",
99
+ "prettier": "^3.9.6",
100
+ "react": "19.2.3",
101
+ "react-native": "0.87.1",
102
+ "react-native-builder-bob": "^0.43.0",
103
+ "turbo": "^2.10.8",
104
+ "typescript": "^6.0.3"
105
+ },
106
+ "peerDependencies": {
107
+ "react": "*",
108
+ "react-native": "*"
109
+ },
110
+ "workspaces": [
111
+ "example"
112
+ ],
113
+ "packageManager": "yarn@4.11.0",
114
+ "react-native-builder-bob": {
115
+ "source": "src",
116
+ "output": "lib",
117
+ "targets": [
118
+ [
119
+ "module",
120
+ {
121
+ "esm": true
122
+ }
123
+ ],
124
+ [
125
+ "typescript",
126
+ {
127
+ "project": "tsconfig.build.json"
128
+ }
129
+ ]
130
+ ]
131
+ },
132
+ "codegenConfig": {
133
+ "name": "TelecomSpec",
134
+ "type": "modules",
135
+ "jsSrcsDir": "src",
136
+ "android": {
137
+ "javaPackageName": "com.telecom"
138
+ }
139
+ },
140
+ "prettier": {
141
+ "quoteProps": "consistent",
142
+ "singleQuote": true,
143
+ "tabWidth": 2,
144
+ "trailingComma": "es5",
145
+ "useTabs": false
146
+ },
147
+ "create-react-native-library": {
148
+ "type": "turbo-module",
149
+ "languages": "kotlin-objc",
150
+ "tools": [
151
+ "eslint"
152
+ ],
153
+ "version": "0.63.1"
154
+ }
155
+ }
@@ -0,0 +1,55 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export type TelecomSetupOptions = {
4
+ appName?: string;
5
+ supportsVideo?: boolean;
6
+ /** Customize the full-screen incoming host Activity (not the CallStyle notification). */
7
+ ui?: {
8
+ incomingTitle?: string;
9
+ answerLabel?: string;
10
+ declineLabel?: string;
11
+ /** Hex colors e.g. `#000000`, `#43A047` */
12
+ backgroundColor?: string;
13
+ titleColor?: string;
14
+ nameColor?: string;
15
+ handleColor?: string;
16
+ answerColor?: string;
17
+ declineColor?: string;
18
+ /** Default true. Set false for notification-only (native CallStyle). */
19
+ launchFullScreenOnIncoming?: boolean;
20
+ };
21
+ };
22
+
23
+ export type TelecomAudioRoute = 'earpiece' | 'speaker' | 'bluetooth';
24
+
25
+ export interface Spec extends TurboModule {
26
+ setup(options: Object): Promise<boolean>;
27
+ displayIncomingCall(
28
+ uuid: string,
29
+ handle: string,
30
+ callerName: string,
31
+ hasVideo: boolean,
32
+ autoAnswer: boolean,
33
+ avatarUrl: string
34
+ ): void;
35
+ startCall(
36
+ uuid: string,
37
+ handle: string,
38
+ callerName: string,
39
+ hasVideo: boolean,
40
+ avatarUrl: string
41
+ ): void;
42
+ answerCall(uuid: string): void;
43
+ endCall(uuid: string): void;
44
+ endAllCalls(): void;
45
+ setMuted(uuid: string, muted: boolean): void;
46
+ setOnHold(uuid: string, hold: boolean): void;
47
+ setAudioRoute(uuid: string, route: string): void;
48
+ getAvailableAudioRoutes(): Promise<Object>;
49
+ sendDtmf(uuid: string, digits: string): void;
50
+ handlePushMessage(data: Object): Promise<boolean>;
51
+ addListener(eventName: string): void;
52
+ removeListeners(count: number): void;
53
+ }
54
+
55
+ export default TurboModuleRegistry.getEnforcing<Spec>('Telecom');
package/src/index.tsx ADDED
@@ -0,0 +1,220 @@
1
+ import {
2
+ NativeEventEmitter,
3
+ NativeModules,
4
+ Platform,
5
+ type EmitterSubscription,
6
+ } from 'react-native';
7
+ import NativeTelecom, {
8
+ type TelecomAudioRoute,
9
+ type TelecomSetupOptions,
10
+ } from './NativeTelecom';
11
+
12
+ export type { TelecomAudioRoute, TelecomSetupOptions };
13
+
14
+ export type TelecomAudioRouteInfo = {
15
+ id: TelecomAudioRoute;
16
+ name: string;
17
+ available: boolean;
18
+ selected: boolean;
19
+ };
20
+
21
+ export type TelecomEvents = {
22
+ answerCall: { callUUID: string };
23
+ endCall: { callUUID: string };
24
+ didDisplayIncomingCall: {
25
+ callUUID: string;
26
+ handle: string;
27
+ callerName: string;
28
+ hasVideo: boolean;
29
+ direction: 'incoming' | 'outgoing';
30
+ avatarUrl?: string;
31
+ };
32
+ didChangeHoldState: { callUUID: string; hold: boolean };
33
+ didChangeMuteState: { callUUID: string; muted: boolean };
34
+ didChangeSpeaker: { callUUID: string; speakerOn: boolean };
35
+ didChangeAudioRoute: { callUUID: string; route: TelecomAudioRoute };
36
+ didActivateAudioSession: { callUUID: string; route: TelecomAudioRoute };
37
+ didDeactivateAudioSession: { callUUID?: string };
38
+ dtmfTone: { callUUID: string; digit: string };
39
+ };
40
+
41
+ export type TelecomEventName = keyof TelecomEvents;
42
+
43
+ export type TelecomPushPayload = {
44
+ uuid?: string;
45
+ callUUID?: string;
46
+ handle?: string;
47
+ number?: string;
48
+ callerName?: string;
49
+ name?: string;
50
+ hasVideo?: boolean | string;
51
+ autoAnswer?: boolean | string;
52
+ avatarUrl?: string;
53
+ avatar?: string;
54
+ type?: string;
55
+ [key: string]: unknown;
56
+ };
57
+
58
+ const isAndroid = Platform.OS === 'android';
59
+
60
+ const emitter = new NativeEventEmitter(
61
+ (NativeModules.Telecom ?? NativeTelecom) as never
62
+ );
63
+
64
+ function assertAndroid(): void {
65
+ if (!isAndroid) {
66
+ throw new Error(
67
+ 'react-native-telecom: Android Jetpack Core-Telecom only in v0.x. iOS CallKit support is coming later.'
68
+ );
69
+ }
70
+ }
71
+
72
+ export async function setup(
73
+ options: TelecomSetupOptions = {}
74
+ ): Promise<boolean> {
75
+ assertAndroid();
76
+ return NativeTelecom.setup({
77
+ appName: options.appName ?? 'App',
78
+ supportsVideo: options.supportsVideo ?? true,
79
+ ui: options.ui,
80
+ });
81
+ }
82
+
83
+ export function displayIncomingCall(
84
+ uuid: string,
85
+ handle: string,
86
+ callerName: string,
87
+ hasVideo: boolean = false,
88
+ autoAnswer: boolean = false,
89
+ avatarUrl: string = ''
90
+ ): void {
91
+ assertAndroid();
92
+ NativeTelecom.displayIncomingCall(
93
+ uuid,
94
+ handle,
95
+ callerName,
96
+ hasVideo,
97
+ autoAnswer,
98
+ avatarUrl
99
+ );
100
+ }
101
+
102
+ export function startCall(
103
+ uuid: string,
104
+ handle: string,
105
+ callerName: string,
106
+ hasVideo: boolean = false,
107
+ avatarUrl: string = ''
108
+ ): void {
109
+ assertAndroid();
110
+ NativeTelecom.startCall(uuid, handle, callerName, hasVideo, avatarUrl);
111
+ }
112
+
113
+ export function answerCall(uuid: string): void {
114
+ assertAndroid();
115
+ NativeTelecom.answerCall(uuid);
116
+ }
117
+
118
+ export function endCall(uuid: string): void {
119
+ assertAndroid();
120
+ NativeTelecom.endCall(uuid);
121
+ }
122
+
123
+ export function endAllCalls(): void {
124
+ assertAndroid();
125
+ NativeTelecom.endAllCalls();
126
+ }
127
+
128
+ export function setMuted(uuid: string, muted: boolean): void {
129
+ assertAndroid();
130
+ NativeTelecom.setMuted(uuid, muted);
131
+ }
132
+
133
+ export function setOnHold(uuid: string, hold: boolean): void {
134
+ assertAndroid();
135
+ NativeTelecom.setOnHold(uuid, hold);
136
+ }
137
+
138
+ export function setAudioRoute(
139
+ uuid: string,
140
+ route: TelecomAudioRoute
141
+ ): void {
142
+ assertAndroid();
143
+ NativeTelecom.setAudioRoute(uuid, route);
144
+ }
145
+
146
+ export async function getAvailableAudioRoutes(): Promise<
147
+ TelecomAudioRouteInfo[]
148
+ > {
149
+ assertAndroid();
150
+ const routes = await NativeTelecom.getAvailableAudioRoutes();
151
+ return routes as TelecomAudioRouteInfo[];
152
+ }
153
+
154
+ /** Local DTMF beep + `dtmfTone` event — forward digits in your signaling/WebRTC. */
155
+ export function sendDtmf(uuid: string, digits: string): void {
156
+ assertAndroid();
157
+ NativeTelecom.sendDtmf(uuid, digits);
158
+ }
159
+
160
+ /**
161
+ * Handle an FCM / push data map from JS (foreground).
162
+ * For killed-state, call `TelecomPushBridge` from your native MessagingService.
163
+ */
164
+ export async function handlePushMessage(
165
+ data: TelecomPushPayload
166
+ ): Promise<boolean> {
167
+ assertAndroid();
168
+ return NativeTelecom.handlePushMessage(data);
169
+ }
170
+
171
+ export function addEventListener<E extends TelecomEventName>(
172
+ eventName: E,
173
+ listener: (event: TelecomEvents[E]) => void
174
+ ): EmitterSubscription {
175
+ assertAndroid();
176
+ return emitter.addListener(eventName, (event) => {
177
+ listener(event as TelecomEvents[E]);
178
+ });
179
+ }
180
+
181
+ export function removeAllListeners(eventName?: TelecomEventName): void {
182
+ if (eventName) {
183
+ emitter.removeAllListeners(eventName);
184
+ return;
185
+ }
186
+
187
+ (
188
+ [
189
+ 'answerCall',
190
+ 'endCall',
191
+ 'didDisplayIncomingCall',
192
+ 'didChangeHoldState',
193
+ 'didChangeMuteState',
194
+ 'didChangeSpeaker',
195
+ 'didChangeAudioRoute',
196
+ 'didActivateAudioSession',
197
+ 'didDeactivateAudioSession',
198
+ 'dtmfTone',
199
+ ] as TelecomEventName[]
200
+ ).forEach((name) => emitter.removeAllListeners(name));
201
+ }
202
+
203
+ const Telecom = {
204
+ setup,
205
+ displayIncomingCall,
206
+ startCall,
207
+ answerCall,
208
+ endCall,
209
+ endAllCalls,
210
+ setMuted,
211
+ setOnHold,
212
+ setAudioRoute,
213
+ getAvailableAudioRoutes,
214
+ sendDtmf,
215
+ handlePushMessage,
216
+ addEventListener,
217
+ removeAllListeners,
218
+ };
219
+
220
+ export default Telecom;