Commit 4e255409 authored by Wei Han's avatar Wei Han

outgoing call bug fixed

parent a6be43fa
import React, { useEffect, useState, useCallback } from 'react'; import React, { useEffect, useState, useCallback } from 'react';
import { View, Text, Button, StyleSheet, Alert, Linking, Platform, NativeModules } from 'react-native'; import { View, Text, Button, StyleSheet, Alert, Linking, Platform, NativeModules } from 'react-native';
import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'; import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions';
import AsyncStorage from '@react-native-async-storage/async-storage'; // import AsyncStorage from '@react-native-async-storage/async-storage';
import DeviceInfo from 'react-native-device-info'; import DeviceInfo from 'react-native-device-info';
const permissionsList = [ const permissionsList = Platform.select({
{ key: 'READ_PHONE_STATE', android: PERMISSIONS.ANDROID.READ_PHONE_STATE }, android: [
{ key: 'READ_CALL_LOG', android: PERMISSIONS.ANDROID.READ_CALL_LOG }, { key: 'READ_PHONE_STATE', android: PERMISSIONS.ANDROID.READ_PHONE_STATE },
{ key: 'Display Over Other Apps', android: null }, // overlay special case { key: 'READ_CALL_LOG', android: PERMISSIONS.ANDROID.READ_CALL_LOG },
]; { key: 'Display Over Other Apps', android: null }, // overlay special case
],
async function saveVIPNumber(name: string, number: string) { ios: [{ key: 'Call Directory Extension', ios: true }],
try { })!;
await AsyncStorage.setItem('vipName', name); const { OverlayPermission } = NativeModules;
await AsyncStorage.setItem('vipNumber', number);
const {VIPStorage} = NativeModules; type CallDirectoryManagerType = {
if (!VIPStorage) { getEnabledStatusForExtension(identifier: string): Promise<number>;
console.error("❌ VIPStorage is undefined. Did you register StoragePackage in MainApplication?"); reloadExtension(identifier: string): Promise<boolean>;
return; };
const CallDirectoryManager: CallDirectoryManagerType | undefined = NativeModules.CallDirectoryManager;
// async function saveVIPNumber(name: string, number: string) {
// try {
// await AsyncStorage.setItem('vipName', name);
// await AsyncStorage.setItem('vipNumber', number);
// const {VIPStorage} = NativeModules;
// if (!VIPStorage) {
// console.error("❌ VIPStorage is undefined. Did you register StoragePackage in MainApplication?");
// return;
// }
// await VIPStorage.saveVIP(name, number);
// console.log('VIPStorage from NativeModules:', NativeModules.VIPStorage);
// } catch (error) {
// console.error('Failed to save VIP info:', error);
// }
// }
async function checkOverlayPermission() {
if (Platform.OS === 'android') {
try {
const granted: boolean = await OverlayPermission.hasPermission();
if (!granted) {
Alert.alert(
'Overlay Permission Required',
'This app needs permission to display over other apps.',
[{ text: 'Open Settings', onPress: openOverlaySettings }]
);
}
return granted;
} catch (e) {
console.error('Error checking overlay permission:', e);
return false;
} }
await VIPStorage.saveVIP(name, number); } else {
console.log('VIPStorage from NativeModules:', NativeModules.VIPStorage); return true; // iOS doesn't require this
} catch (error) {
console.error('Failed to save VIP info:', error);
} }
} }
const openOverlaySettings = async () => {
if (Platform.OS === 'android') {
const pkg = DeviceInfo.getBundleId(); // gets your app package name
try {
await Linking.openSettings(); // fallback
await Linking.openURL(`package:${pkg}`);
} catch (err) {
console.warn('Failed to open overlay settings:', err);
}
}
};
export default function App() { export default function App() {
const [statuses, setStatuses] = useState<Record<string, string>>({}); const [statuses, setStatuses] = useState<Record<string, string>>({});
const checkAllPermissions = useCallback(async () => { const checkAllPermissions = useCallback(async () => {
const newStatuses: Record<string, string> = {}; const newStatuses: Record<string, string> = {};
if (Platform.OS === 'ios') {
try {
if (CallDirectoryManager) {
const status = await CallDirectoryManager.getEnabledStatusForExtension(
"com.whoscall.app.CallDirectoryExtension"
);
newStatuses['Call Directory Extension'] = status === 2 ? RESULTS.GRANTED : RESULTS.DENIED;
} else {
console.warn("⚠️ CallDirectoryManager native module not available");
newStatuses['Call Directory Extension'] = RESULTS.DENIED;
}
} catch (e) {
console.error("Error checking Call Directory extension:", e);
newStatuses['Call Directory Extension'] = RESULTS.DENIED;
}
} else {
for (const perm of permissionsList) { for (const perm of permissionsList) {
if (perm.key === 'Display Over Other Apps') { if (perm.key === 'Display Over Other Apps') {
// Overlay not checkable in RN const granted = await checkOverlayPermission();
newStatuses[perm.key] = RESULTS.DENIED; newStatuses[perm.key] = granted ? RESULTS.GRANTED : RESULTS.DENIED;
continue; continue;
} }
const result = await check(perm.android!); if ('android' in perm && perm.android) {
newStatuses[perm.key] = result; const result = await check(perm.android);
newStatuses[perm.key] = result;
}
} }
setStatuses(newStatuses); setStatuses(newStatuses);
...@@ -53,43 +114,37 @@ export default function App() { ...@@ -53,43 +114,37 @@ export default function App() {
'This app needs permission to display over other apps.', 'This app needs permission to display over other apps.',
[{ text: 'Open Settings', onPress: openOverlaySettings }] [{ text: 'Open Settings', onPress: openOverlaySettings }]
); );
} else { } else if ('android' in perm && perm.android) {
const result = await request(perm.android!); const result = await request(perm.android);
setStatuses(prev => ({ ...prev, [perm.key]: result })); setStatuses(prev => ({ ...prev, [perm.key]: result }));
} }
} }
if (Platform.OS as string === 'ios') {
Alert.alert(
"Enable Caller ID",
"Go to Settings → Phone → Call Blocking & Identification and enable [Your App] to see caller ID labels."
);
}
} }
},[]); }
}, []);
useEffect(() => { useEffect(() => {
console.log("PermissionsScreen mounted"); console.log("PermissionsScreen mounted");
console.log("All NativeModules keys:", Object.keys(NativeModules)); console.log("All NativeModules keys:", Object.keys(NativeModules));
console.log("VIPStorage:", NativeModules.VIPStorage); // console.log("VIPStorage:", NativeModules.VIPStorage);
saveVIPNumber('VIP User', '+60123456789'); // saveVIPNumber('VIP User', '+60123456789');
checkAllPermissions(); checkAllPermissions();
},[checkAllPermissions]); },[checkAllPermissions]);
// Open Overlay Settings
const openOverlaySettings = async () => {
if (Platform.OS === 'android') {
const pkg = DeviceInfo.getBundleId(); // gets your app package name
const url = `package:${pkg}`;
try {
await Linking.openSettings(); // fallback
await Linking.openURL(`android.settings.action.MANAGE_OVERLAY_PERMISSION/${url}`);
} catch (err) {
console.warn('Failed to open overlay settings:', err);
}
}
};
const allGranted = Object.values(statuses).every(s => s === RESULTS.GRANTED); const allGranted = Object.values(statuses).every(s => s === RESULTS.GRANTED);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.title}>Permissions Status</Text> <Text style={styles.title}>Permissions Status</Text>
{permissionsList.map(perm => ( {(permissionsList ?? []).map(perm => (
<View key={perm.key} style={styles.row}> <View key={perm.key} style={styles.row}>
<Text style={styles.text}>{perm.key}</Text> <Text style={styles.text}>{perm.key}</Text>
<Text <Text
......
...@@ -13,10 +13,16 @@ import android.content.SharedPreferences ...@@ -13,10 +13,16 @@ import android.content.SharedPreferences
class IncomingCallService : CallScreeningService() { class IncomingCallService : CallScreeningService() {
override fun onScreenCall(callDetails: Details) { override fun onScreenCall(callDetails: Details) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (callDetails.callDirection != Details.DIRECTION_INCOMING) {
// Not an incoming call, ignore
return
}
}
val number = callDetails.handle?.schemeSpecificPart ?: "Unknown" val number = callDetails.handle?.schemeSpecificPart ?: "Unknown"
// Lookup VIPs // Lookup VIPs
val prefs = getSharedPreferences("WhoscallPrefs", MODE_PRIVATE) // val prefs = getSharedPreferences("WhoscallPrefs", MODE_PRIVATE)
val vipNumber = "+60108222562" val vipNumber = "+60108222562"
val vipName = "Arvin" val vipName = "Arvin"
......
...@@ -19,7 +19,7 @@ class MainApplication : Application(), ReactApplication { ...@@ -19,7 +19,7 @@ class MainApplication : Application(), ReactApplication {
// Packages that cannot be autolinked yet can be added manually here, for example: // Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage()) // add(MyReactNativePackage())
add(StoragePackage()) add(StoragePackage())
add(MyAppPackage())
} }
override fun getJSMainModuleName(): String = "index" override fun getJSMainModuleName(): String = "index"
......
// MyAppPackage.kt
package com.whoscall
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
class MyAppPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(OverlayPermissionModule(reactContext))
}
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
// OverlayPermissionModule.kt
package com.whoscall
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Promise
import android.os.Build
import android.provider.Settings
class OverlayPermissionModule(reactContext: ReactApplicationContext) :
ReactContextBaseJavaModule(reactContext) {
override fun getName(): String {
return "OverlayPermission"
}
@ReactMethod
fun hasPermission(promise: Promise) {
val canDraw = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Settings.canDrawOverlays(reactApplicationContext)
} else {
true
}
promise.resolve(canDraw)
}
}
...@@ -32,10 +32,4 @@ target 'whoscall' do ...@@ -32,10 +32,4 @@ target 'whoscall' do
# :ccache_enabled => true # :ccache_enabled => true
) )
end end
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts.podspec"
pod 'Permission-Phone', :path => "#{permissions_path}/Phone.podspec"
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications.podspec"
end end
...@@ -2645,7 +2645,7 @@ SPEC CHECKSUMS: ...@@ -2645,7 +2645,7 @@ SPEC CHECKSUMS:
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: 4f8246b1f6d79f625e0d99472d1f3a71da4d28ca hermes-engine: 4f8246b1f6d79f625e0d99472d1f3a71da4d28ca
RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077 RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077
RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a
RCTTypeSafety: 720403058b7c1380c6a3ae5706981d6362962c89 RCTTypeSafety: 720403058b7c1380c6a3ae5706981d6362962c89
......
...@@ -3,48 +3,22 @@ ...@@ -3,48 +3,22 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 70; objectVersion = 54;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
0C80B921A6F3F58F76C31292 /* libPods-whoscall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-whoscall.a */; }; 0C80B921A6F3F58F76C31292 /* libPods-whoscall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-whoscall.a */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
2F60E0202E66CCEF00C504BE /* whoscallDirectoryExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2F60E0192E66CCEF00C504BE /* whoscallDirectoryExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
3C68549A1AFF3687BD1D58DA /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
A3AA3DDDD267D1DE50433D9E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
2F60E01E2E66CCEF00C504BE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 2F60E0182E66CCEF00C504BE;
remoteInfo = whoscallDirectoryExtension;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
2F60E0212E66CCEF00C504BE /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
2F60E0202E66CCEF00C504BE /* whoscallDirectoryExtension.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
13B07F961A680F5B00A75B9A /* whoscall.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = whoscall.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* whoscall.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = whoscall.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = whoscall/Images.xcassets; sourceTree = "<group>"; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = whoscall/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = whoscall/Info.plist; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = whoscall/Info.plist; sourceTree = "<group>"; };
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = whoscall/PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = whoscall/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
2F60E0192E66CCEF00C504BE /* whoscallDirectoryExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = whoscallDirectoryExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
3B4392A12AC88292D35C810B /* Pods-whoscall.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-whoscall.debug.xcconfig"; path = "Target Support Files/Pods-whoscall/Pods-whoscall.debug.xcconfig"; sourceTree = "<group>"; }; 3B4392A12AC88292D35C810B /* Pods-whoscall.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-whoscall.debug.xcconfig"; path = "Target Support Files/Pods-whoscall/Pods-whoscall.debug.xcconfig"; sourceTree = "<group>"; };
5709B34CF0A7D63546082F79 /* Pods-whoscall.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-whoscall.release.xcconfig"; path = "Target Support Files/Pods-whoscall/Pods-whoscall.release.xcconfig"; sourceTree = "<group>"; }; 5709B34CF0A7D63546082F79 /* Pods-whoscall.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-whoscall.release.xcconfig"; path = "Target Support Files/Pods-whoscall/Pods-whoscall.release.xcconfig"; sourceTree = "<group>"; };
5DCACB8F33CDC322A6C60F78 /* libPods-whoscall.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-whoscall.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 5DCACB8F33CDC322A6C60F78 /* libPods-whoscall.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-whoscall.a"; sourceTree = BUILT_PRODUCTS_DIR; };
...@@ -53,20 +27,6 @@ ...@@ -53,20 +27,6 @@
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
2F60E0242E66CCEF00C504BE /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
);
target = 2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */;
};
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
2F60E01A2E66CCEF00C504BE /* whoscallDirectoryExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (2F60E0242E66CCEF00C504BE /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = whoscallDirectoryExtension; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
...@@ -76,13 +36,6 @@ ...@@ -76,13 +36,6 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
2F60E0162E66CCEF00C504BE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
...@@ -119,7 +72,6 @@ ...@@ -119,7 +72,6 @@
children = ( children = (
13B07FAE1A68108700A75B9A /* whoscall */, 13B07FAE1A68108700A75B9A /* whoscall */,
832341AE1AAA6A7D00B99B32 /* Libraries */, 832341AE1AAA6A7D00B99B32 /* Libraries */,
2F60E01A2E66CCEF00C504BE /* whoscallDirectoryExtension */,
83CBBA001A601CBA00E9B192 /* Products */, 83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */, 2D16E6871FA4F8E400B85C8A /* Frameworks */,
BBD78D7AC51CEA395F1C20DB /* Pods */, BBD78D7AC51CEA395F1C20DB /* Pods */,
...@@ -133,7 +85,6 @@ ...@@ -133,7 +85,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
13B07F961A680F5B00A75B9A /* whoscall.app */, 13B07F961A680F5B00A75B9A /* whoscall.app */,
2F60E0192E66CCEF00C504BE /* whoscallDirectoryExtension.appex */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -161,55 +112,27 @@ ...@@ -161,55 +112,27 @@
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
2F60E0212E66CCEF00C504BE /* Embed Foundation Extensions */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
2F60E01F2E66CCEF00C504BE /* PBXTargetDependency */,
); );
name = whoscall; name = whoscall;
productName = whoscall; productName = whoscall;
productReference = 13B07F961A680F5B00A75B9A /* whoscall.app */; productReference = 13B07F961A680F5B00A75B9A /* whoscall.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
}; };
2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2F60E0252E66CCEF00C504BE /* Build configuration list for PBXNativeTarget "whoscallDirectoryExtension" */;
buildPhases = (
2F60E0152E66CCEF00C504BE /* Sources */,
2F60E0162E66CCEF00C504BE /* Frameworks */,
2F60E0172E66CCEF00C504BE /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
2F60E01A2E66CCEF00C504BE /* whoscallDirectoryExtension */,
);
name = whoscallDirectoryExtension;
packageProductDependencies = (
);
productName = whoscallDirectoryExtension;
productReference = 2F60E0192E66CCEF00C504BE /* whoscallDirectoryExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = { 83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1210; LastUpgradeCheck = 1210;
TargetAttributes = { TargetAttributes = {
13B07F861A680F5B00A75B9A = { 13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1120; LastSwiftMigration = 1120;
}; };
2F60E0182E66CCEF00C504BE = {
CreatedOnToolsVersion = 16.4;
};
}; };
}; };
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "whoscall" */; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "whoscall" */;
...@@ -226,7 +149,6 @@ ...@@ -226,7 +149,6 @@
projectRoot = ""; projectRoot = "";
targets = ( targets = (
13B07F861A680F5B00A75B9A /* whoscall */, 13B07F861A680F5B00A75B9A /* whoscall */,
2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
...@@ -238,14 +160,7 @@ ...@@ -238,14 +160,7 @@
files = ( files = (
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
3C68549A1AFF3687BD1D58DA /* PrivacyInfo.xcprivacy in Resources */, A3AA3DDDD267D1DE50433D9E /* PrivacyInfo.xcprivacy in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2F60E0172E66CCEF00C504BE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -276,14 +191,10 @@ ...@@ -276,14 +191,10 @@
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = (
);
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-output-files.xcfilelist",
); );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks.sh\"\n";
...@@ -319,14 +230,10 @@ ...@@ -319,14 +230,10 @@
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = (
);
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-output-files.xcfilelist",
); );
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources.sh\"\n";
...@@ -343,23 +250,8 @@ ...@@ -343,23 +250,8 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
2F60E0152E66CCEF00C504BE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
2F60E01F2E66CCEF00C504BE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */;
targetProxy = 2F60E01E2E66CCEF00C504BE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
...@@ -415,87 +307,6 @@ ...@@ -415,87 +307,6 @@
}; };
name = Release; name = Release;
}; };
2F60E0222E66CCEF00C504BE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = whoscallDirectoryExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = whoscallDirectoryExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.whoscall.whoscallDirectoryExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
2F60E0232E66CCEF00C504BE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = whoscallDirectoryExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = whoscallDirectoryExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.reactjs.native.example.whoscall.whoscallDirectoryExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = { 83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
...@@ -652,15 +463,6 @@ ...@@ -652,15 +463,6 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
2F60E0252E66CCEF00C504BE /* Build configuration list for PBXNativeTarget "whoscallDirectoryExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2F60E0222E66CCEF00C504BE /* Debug */,
2F60E0232E66CCEF00C504BE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "whoscall" */ = { 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "whoscall" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
......
...@@ -31,11 +31,6 @@ ...@@ -31,11 +31,6 @@
<key>NSAllowsLocalNetworking</key> <key>NSAllowsLocalNetworking</key>
<true/> <true/>
</dict> </dict>
<key>NSUserActivityTypes</key>
<array>
<string>INStartAudioCallIntent</string>
<string>INStartVideoCallIntent</string>
</array>
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
<string></string> <string></string>
<key>RCTNewArchEnabled</key> <key>RCTNewArchEnabled</key>
......
#if os(iOS)
import Foundation import Foundation
import CallKit import CallKit
...@@ -18,7 +19,7 @@ class CallDirectoryHandler: CXCallDirectoryProvider { ...@@ -18,7 +19,7 @@ class CallDirectoryHandler: CXCallDirectoryProvider {
// Example: add VIP numbers // Example: add VIP numbers
// Numbers must be E.164 format (+60 for Malaysia) // Numbers must be E.164 format (+60 for Malaysia)
let vipNumbers: [(number: Int64, label: String)] = [ let vipNumbers: [(number: Int64, label: String)] = [
(60189884118, "VIP: Wei Yi"), (60189884118, "Wei Yi"),
(60123456789, "Spam Caller"), (60123456789, "Spam Caller"),
] ]
...@@ -46,3 +47,4 @@ extension CallDirectoryHandler: CXCallDirectoryExtensionContextDelegate { ...@@ -46,3 +47,4 @@ extension CallDirectoryHandler: CXCallDirectoryExtensionContextDelegate {
NSLog("Call Directory extension error: \(error.localizedDescription)") NSLog("Call Directory extension error: \(error.localizedDescription)")
} }
} }
#endif
\ No newline at end of file
...@@ -4,25 +4,20 @@ ...@@ -4,25 +4,20 @@
<dict> <dict>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionAttributes</key>
<dict>
<key>CXCallDirectoryExtensionAttributes</key>
<dict>
<key>CXCallDirectoryExtensionIdentifier</key>
<string>com.yourapp.callid</string>
</dict>
</dict>
<key>NSExtensionPointIdentifier</key> <key>NSExtensionPointIdentifier</key>
<string>com.apple.callkit.call-directory</string> <string>com.apple.callkit.call-directory</string>
<key>NSExtensionPrincipalClass</key> <key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).CallDirectoryHandler</string> <string>$(PRODUCT_MODULE_NAME).CallDirectoryHandler</string>
</dict> </dict>
<key>NSExtension</key> <key>RCTNewArchEnabled</key>
<dict> <true/>
<key>NSExtensionAttributes</key>
<dict>
<key>CXCallDirectoryExtensionAttributes</key>
<dict>
<key>CXCallDirectoryExtensionIdentifier</key>
<string>com.yourapp.callid</string>
</dict>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.callkit.call-directory</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).CallDirectoryHandler</string>
</dict>
</dict> </dict>
</plist> </plist>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment