Commit a6be43fa authored by Wei Han's avatar Wei Han

ios progress

parent 33bf9979
......@@ -103,25 +103,6 @@ export default function App() {
))}
{allGranted && <Text style={styles.granted}>All permissions granted ✅</Text>}
<Button title="Check Again" onPress={checkAllPermissions} />
<Button
title="Simulate VIP Call"
onPress={async () => {
const number = '+60123456789';
const name = 'VIP User';
// Save VIP info in AsyncStorage + native storage
await saveVIPNumber(name, number);
// Call native module to start OverlayService (simulate incoming call)
if (NativeModules.VIPStorage?.simulateVipCall) {
NativeModules.VIPStorage.simulateVipCall(number, name);
} else {
console.warn('simulateVipCall not implemented in NativeModules.');
}
Alert.alert('Simulated VIP call', `${name} (${number})`);
}}
/>
</View>
);
}
......
......@@ -25,11 +25,11 @@ Please follow this installation instruction.
> :information_source: **Note:** If you hit error permission denied, please execute `chmod +x gradlew`
<!-- 4. Pod install for iOS :
4. Pod install for iOS :
- Go into iOS directory: `cd ios`
- Install pod: `pod install`
- After completion, return to main directory: `cd ../` -->
- After completion, return to main directory: `cd ../`
5. Finish installation :clap:
......@@ -41,12 +41,12 @@ Below is all command that use to execute react native project for android and iO
1. Run : `npx react-native run-android`
<!-- ## iOS
## iOS
1. go to iOS directory by execute : `cd ios` <br>
2. open xCode workspace by execute : `Runner.xcworkspace` <br>
3. clean app by go to Product > Clean Build Folder...
4. run app by go to Product > Build -->
4. run app by go to Product > Build
## Expected behavior
- When user's phone is called, alert shows up showing the caller number + who the caller is
......
......@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<application
android:name=".MainApplication"
......
......@@ -4,30 +4,21 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.app.role.RoleManager
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import com.whoscall.databinding.ActivityMainBinding
import android.content.SharedPreferences
import android.util.Log
import com.facebook.react.ReactActivity
class MainActivity : ComponentActivity() {
private lateinit var binding: ActivityMainBinding
class MainActivity : ReactActivity() {
private val roleLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { /* no-op */ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnOverlay.setOnClickListener { requestOverlay() }
binding.btnRole.setOnClickListener { requestCallScreeningRoleIfNeeded() }
override fun getMainComponentName(): String {
// 👇 must match what you registered in index.js
return "whoscall"
}
private fun requestOverlay() {
......@@ -50,19 +41,16 @@ class MainActivity : ComponentActivity() {
}
private fun simulateVipCall() {
// Example VIP number and name
val vipNumber = "+60189884118"
val vipName = "Wei Yi"
val vipNumber = "+60189884118"
val vipName = "Wei Yi"
// Save to SharedPreferences
val prefs = getSharedPreferences("WhoscallPrefs", MODE_PRIVATE)
prefs.edit().putString(vipNumber, vipName).apply()
val prefs = getSharedPreferences("WhoscallPrefs", MODE_PRIVATE)
prefs.edit().putString(vipNumber, vipName).apply()
// Start overlay service directly
val overlayIntent = Intent(this, OverlayService::class.java).apply {
putExtra("number", vipNumber)
putExtra("displayName", vipName)
}
startService(overlayIntent)
val overlayIntent = Intent(this, OverlayService::class.java).apply {
putExtra("number", vipNumber)
putExtra("displayName", vipName)
}
startService(overlayIntent)
}
}
......@@ -19,6 +19,7 @@ class MainApplication : Application(), ReactApplication {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
add(StoragePackage())
}
override fun getJSMainModuleName(): String = "index"
......
package com.whoscall
import android.content.Context
import android.os.Build
import android.provider.Settings
object OverlayPermissionChecker {
/**
* Returns true if the app has permission to draw over other apps
*/
fun hasOverlayPermission(context: Context): Boolean{
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Settings.canDrawOverlays(context)
} else {
true //Automaticallt allowed on older android versions
}
}
}
\ No newline at end of file
......@@ -25,21 +25,4 @@ class StorageModule(reactContext: ReactApplicationContext) :
promise.reject("SAVE_ERROR", e)
}
}
@ReactMethod
fun simulateVipCall(number: String, name: String) {
Log.d("VIPStorage", "Simulating VIP call: $name ($number)")
val context = reactApplicationContext
// Save VIP first
prefs.edit().putString(number, name).apply()
// Start OverlayService
val intent = Intent(context, OverlayService::class.java).apply {
putExtra("number", number)
putExtra("displayName", name)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startService(intent)
}
}
......@@ -4,3 +4,7 @@ extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autoli
rootProject.name = 'whoscall'
include ':app'
includeBuild('../node_modules/@react-native/gradle-plugin')
include ':rn-android-overlay-permission'
project(':rn-android-overlay-permission').projectDir = new File(
rootProject.projectDir, '../node_modules/rn-android-overlay-permission/android'
)
\ No newline at end of file
......@@ -32,4 +32,10 @@ target 'whoscall' do
# :ccache_enabled => true
)
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
......@@ -1749,7 +1749,92 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- react-native-safe-area-context (5.6.1):
- boost
- DoubleConversion
- fast_float
- fmt
- glog
- hermes-engine
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- react-native-safe-area-context/common (= 5.6.1)
- react-native-safe-area-context/fabric (= 5.6.1)
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- react-native-safe-area-context/common (5.6.1):
- boost
- DoubleConversion
- fast_float
- fmt
- glog
- hermes-engine
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- react-native-safe-area-context/fabric (5.6.1):
- boost
- DoubleConversion
- fast_float
- fmt
- glog
- hermes-engine
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- react-native-safe-area-context/common
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- React-NativeModulesApple (0.81.1):
- boost
- DoubleConversion
......@@ -2255,6 +2340,64 @@ PODS:
- React-perflogger (= 0.81.1)
- React-utils (= 0.81.1)
- SocketRocket
- RNCAsyncStorage (2.2.0):
- boost
- DoubleConversion
- fast_float
- fmt
- glog
- hermes-engine
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- RNDeviceInfo (14.0.4):
- React-Core
- RNPermissions (5.4.2):
- boost
- DoubleConversion
- fast_float
- fmt
- glog
- hermes-engine
- RCT-Folly
- RCT-Folly/Fabric
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- SocketRocket (0.7.1)
- Yoga (0.0.0)
......@@ -2331,6 +2474,9 @@ DEPENDENCIES:
- ReactAppDependencyProvider (from `build/generated/ios`)
- ReactCodegen (from `build/generated/ios`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNPermissions (from `../node_modules/react-native-permissions`)
- SocketRocket (~> 0.7.1)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
......@@ -2482,6 +2628,12 @@ EXTERNAL SOURCES:
:path: build/generated/ios
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNPermissions:
:path: "../node_modules/react-native-permissions"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
......@@ -2499,67 +2651,70 @@ SPEC CHECKSUMS:
RCTTypeSafety: 720403058b7c1380c6a3ae5706981d6362962c89
React: f1486d005993b0af01943af1850d3d4f3b597545
React-callinvoker: 133f69368c8559e744efa345223625d412f5dfbe
React-Core: d6d8c1fd33697cec596d33b820456505ee305686
React-CoreModules: 81ab751a7668ba161440f9623b994e1a6a3019fe
React-cxxreact: 16f2a2751d0dce8b569f23c1914edc90f655b01b
React-Core: 559823921b4f294c2840fa8238ca958a29ddc211
React-CoreModules: c41e7bbfabbc420783bb926f45837a0d5e53341e
React-cxxreact: 9cb9fa738274a1b36b97ede09c8a6717dec1a20b
React-debug: e01581e1589f329e61c95b332bf7f4969b10564b
React-defaultsnativemodule: e956b1d8fe15cc79d23061db229bf88170565f2f
React-domnativemodule: a18b0f7a31b9c75f12fa369baece5542d1265b36
React-Fabric: c0237a32c3c0dbea2d2b294c8e95605e1dfe2f57
React-FabricComponents: 65b03884bd5d9f24c79a631d7d26f0fa079bc4aa
React-FabricImage: de1ea2f2a0b32ad02e5cbb64827d1eec0439cf0d
React-featureflags: 02de9c35256cc624269b01d670d99e1fd706ea8d
React-featureflagsnativemodule: 8b84e67edbaa7b9318390c5bd3ae19790a74f356
React-graphics: 004b40c1b236ea3bb8de6693439bef9797922ba9
React-hermes: 2179a018b2f86652f6f33ef23efd9e5ac284b247
React-idlecallbacksnativemodule: f54ea68f984b12e42feed1e7110623b2c38df4d1
React-ImageManager: 9dd04b7b62bc5397f876ca5fb1b712e700ce390c
React-jserrorhandler: 2f90bf50fffea1d012e7f3d717c6adf748b1813d
React-jsi: b27208f8866e53238534f65f304903e4eff25e05
React-jsiexecutor: 1d3e827797f592c393860dea91aaa6d53c7715e7
React-jsinspector: bda319277ae779bc476b736fe3a497c6aed304cd
React-jsinspectorcdp: 69e1736edfd5420037680b7b4557fa748c3c8216
React-jsinspectornetwork: 7aa707b057c6129b4af59e0c9160436bbab25022
React-jsinspectortracing: b4a8a328ad2697f9638daa4b7cc054e0303fa47f
React-jsitooling: a6c7e2829437b28665e97a398b3374d443125e24
React-jsitracing: d87ae17dd0eef7844e605945da926c5433fe2b51
React-logger: d27dd2000f520bf891d24f6e141cde34df41f0ee
React-Mapbuffer: 0746ffab5ac0f49b7c9347338e3d0c1d9dd634c8
React-microtasksnativemodule: b0fb3f97372df39bda3e657536039f1af227cc29
react-native-safe-area-context: aac2745e96999c8633d2f6119e4e39b499c2ac8b
React-NativeModulesApple: 9ec9240159974c94886ebbe4caec18e3395f6aef
React-defaultsnativemodule: bbb39447caa6b6cf9405fa0099f828c083640faa
React-domnativemodule: 03744d12b6d56d098531a933730bf1d4cb79bdfb
React-Fabric: 530b3993a12a96e8a7cdb9f0ef48e605277b572e
React-FabricComponents: 271ec2a9b2c00ac66fd6d1fd24e9e964d907751d
React-FabricImage: d0af66e976dbab7f8b81e36dd369fc70727d2695
React-featureflags: 269704c8eff86e0485c9d384e286350fcda6eb70
React-featureflagsnativemodule: db1e5d88a912fb08a5ece33fcf64e1b732da8467
React-graphics: b19d03a01b0722b4dc82f47acb56dc3ed41937e7
React-hermes: 811606c0aca5a3f9c6fa8e4994e02ca8f677e68e
React-idlecallbacksnativemodule: 3a3df629cd50046c7e4354f9025aefe8f2c84601
React-ImageManager: 0d53866c63132791e37bb2373f93044fdef14aa3
React-jserrorhandler: d5700d6ab7162fd575287502a3c5d601d98e7f09
React-jsi: ece95417fedbed0e7153a855cb8342b7c72ab75e
React-jsiexecutor: 2b0bb644b533df2f5c0cd6ade9a4560d0bf1dd84
React-jsinspector: 0c160f8510a8852bdf2dac12f0b1949efc18200b
React-jsinspectorcdp: f4b84409f453f61ddd8614ad45139bc594ec6bb5
React-jsinspectornetwork: 8f2f0ca8c871ca19b571f426002c0012e7fb2aee
React-jsinspectortracing: 33f6b977eb8a4bc1e3d1a4b948809aca083143f9
React-jsitooling: 2c61529b589e17229a9f0a4a4fc35aa7ad495850
React-jsitracing: 838a7b0c013c4aff7d382d7fdc78cf442013ba1d
React-logger: 7aef4d74123e5e3d267e5af1fbf5135b5a0d8381
React-Mapbuffer: 91e0eab42a6ae7f3e34091a126d70fc53bd3823e
React-microtasksnativemodule: 1ead4fe154df3b1ba34b5a9e35ef3c4bdfa72ccb
react-native-safe-area-context: c6e2edd1c1da07bdce287fa9d9e60c5f7b514616
React-NativeModulesApple: eff2eba56030eb0d107b1642b8f853bc36a833ac
React-oscompat: b12c633e9c00f1f99467b1e0e0b8038895dae436
React-perflogger: ccf4fd2664b00818645e588623c7531a8b32d114
React-performancetimeline: a866ba759d8e06e9ba174b4421677edcae487baf
React-perflogger: 58d12c4e5df1403030c97b9c621375c312cca454
React-performancetimeline: 0ee0a3236c77a4ee6d8a6189089e41e4003d292e
React-RCTActionSheet: 3f741a3712653611a6bfc5abceb8260af9d0b218
React-RCTAnimation: 2edeebfba175cc2e937e2752209ab605d3c48f21
React-RCTAppDelegate: a99ef112d5f199aba910c14e046e9dbc7fe89f75
React-RCTBlob: 8dfb24b6dd4a5af45e1e59e2fd925b2df1e44d08
React-RCTFabric: 2cb67c67e545c6ec76a853861aa275983fe5aca4
React-RCTFBReactNativeSpec: 174272d8db878578a7d282b137ccc2da4776877c
React-RCTImage: c7fe8c2f2ae8bad98ab4d944d5d50a889da4b652
React-RCTLinking: 9ac21ce9f1af914bb01c06af3752db2ec840d0ee
React-RCTNetwork: 09a5de71d757dbad4b3fe3615839290200b932aa
React-RCTRuntime: 5072e1dbb1ff6d455f0013db6f25d1fdba5f1844
React-RCTSettings: fee112652ac7569ea9abe910206e1685f5f9adba
React-RCTText: 7ee9d0bc16b3a8149f8df6d70c48e724d0db1d89
React-RCTVibration: 619d613abaeb05f6fbc2b2e5e33f724f05df8eb8
React-RCTAnimation: 408ad69ea136e99a463dd33eadecc29e586b3d72
React-RCTAppDelegate: f03b46e80b8a3dbfa84b35abfe123e02f3ceef83
React-RCTBlob: bd42e92a00ad22eaab92ffe5c137e7a2f725887a
React-RCTFabric: b99ab638c73cf2d57b886eafdbfb2e4909b0eb9a
React-RCTFBReactNativeSpec: 7ad9aba0e0655e3f29be0a1c3fd4a888fab04dcf
React-RCTImage: 0f1c74f7cd20027f8c34976a211b35d4263a0add
React-RCTLinking: 6d7dfc3a74110df56c3a73cc7626bf4415656542
React-RCTNetwork: 6a25d8645a80d5b86098675ca39bf8fcf1afa08b
React-RCTRuntime: 38bfe9766565ae3293ca230bc51c9c020a8bc98a
React-RCTSettings: 651d9ae2cdd32f547ad0d225a2c13886d6ad2358
React-RCTText: 9bc66cd288478e23195e01f5cb45eba79986b2b4
React-RCTVibration: 371226f5667a00c76d792dcdb5c2e0fcbcde0c3b
React-rendererconsistency: a05f6c37f9389c53213d1e28798e441fa6fbdbcd
React-renderercss: 3decb27a81648fcdee837c59994b51fff5be5a67
React-rendererdebug: 3b9a92d36932af52e1b473f2a89ea4b05dbdecdf
React-RuntimeApple: 4e35fb74be4b721c2e1fd6d54ec66456fa7043e9
React-RuntimeCore: 0fd7ac6e3e9dd20cb47e87c6b9f35832dd445d5e
React-runtimeexecutor: 7680156c9f3a5a49c688bc33f9ec5ea1b00527f5
React-RuntimeHermes: 435b7104a3c749af6251353dcb7317a8e53cbd73
React-runtimescheduler: 8056b916168e446ea44531883928034e62e76a81
React-timing: 36da85e32e53008ce73f87528818191e7f2508ba
React-utils: 71e53d55ce778c6e7c7c9db4b1b9d63ef8f55289
ReactAppDependencyProvider: 448b422f8af1dedf81374eacc90a15439a0ed7f5
ReactCodegen: 3baedb0c33f963250c866151b825a3c5194b12f1
ReactCommon: e897f9a1b4afab370cfefaaf5fb3c80371bc3937
React-renderercss: 6e4febfa014b0f53bc171a62b0f713ddbdbb9860
React-rendererdebug: e94bf27b9d55ef2795caa8e43aa92abc4a373b8b
React-RuntimeApple: 723be5159519eba1cd92449acb29436d21571b82
React-RuntimeCore: f58eb0f01065c9d27d91de10b2e4ab4c76d83b0e
React-runtimeexecutor: f615ec8742d0b5820170f7c8b4d2c7cb75d93ac9
React-RuntimeHermes: fddb258e03d330d1132bb19e78fe51ac2f3f41ac
React-runtimescheduler: e92a31460e654ced8587debeec37553315e1b6a5
React-timing: 97ada2c47b4c5932e7f773c7d239c52b90d6ca68
React-utils: f0949d247a46b4c09f03e5a3cb1167602d0b729a
ReactAppDependencyProvider: 3eb9096cb139eb433965693bbe541d96eb3d3ec9
ReactCodegen: 4d203eddf6f977caa324640a20f92e70408d648b
ReactCommon: ce5d4226dfaf9d5dacbef57b4528819e39d3a120
RNCAsyncStorage: 29f0230e1a25f36c20b05f65e2eb8958d6526e82
RNDeviceInfo: d863506092aef7e7af3a1c350c913d867d795047
RNPermissions: 56d8a958b1d8cf7f4c30a732619b7b6b6b92bfda
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: fa23995c18b65978347b096d0836f4f5093df545
Yoga: 11c9686a21e2cd82a094a723649d9f4507200fb0
PODFILE CHECKSUM: fc09e4987141cdbdb9225f2448b4fa7d29d3c937
COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
......@@ -3,22 +3,48 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 70;
objects = {
/* Begin PBXBuildFile section */
0C80B921A6F3F58F76C31292 /* libPods-whoscall.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-whoscall.a */; };
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 */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
/* 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 */
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>"; };
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>"; };
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>"; };
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; };
......@@ -27,6 +53,20 @@
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* 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 */
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
......@@ -36,6 +76,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
2F60E0162E66CCEF00C504BE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
......@@ -72,6 +119,7 @@
children = (
13B07FAE1A68108700A75B9A /* whoscall */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
2F60E01A2E66CCEF00C504BE /* whoscallDirectoryExtension */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
BBD78D7AC51CEA395F1C20DB /* Pods */,
......@@ -85,6 +133,7 @@
isa = PBXGroup;
children = (
13B07F961A680F5B00A75B9A /* whoscall.app */,
2F60E0192E66CCEF00C504BE /* whoscallDirectoryExtension.appex */,
);
name = Products;
sourceTree = "<group>";
......@@ -112,27 +161,55 @@
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
2F60E0212E66CCEF00C504BE /* Embed Foundation Extensions */,
);
buildRules = (
);
dependencies = (
2F60E01F2E66CCEF00C504BE /* PBXTargetDependency */,
);
name = whoscall;
productName = whoscall;
productReference = 13B07F961A680F5B00A75B9A /* whoscall.app */;
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 */
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1210;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
LastSwiftMigration = 1120;
};
2F60E0182E66CCEF00C504BE = {
CreatedOnToolsVersion = 16.4;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "whoscall" */;
......@@ -149,6 +226,7 @@
projectRoot = "";
targets = (
13B07F861A680F5B00A75B9A /* whoscall */,
2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */,
);
};
/* End PBXProject section */
......@@ -164,6 +242,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
2F60E0172E66CCEF00C504BE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
......@@ -191,10 +276,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-frameworks.sh\"\n";
......@@ -230,10 +319,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-whoscall/Pods-whoscall-resources.sh\"\n";
......@@ -250,8 +343,23 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
2F60E0152E66CCEF00C504BE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
2F60E01F2E66CCEF00C504BE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2F60E0182E66CCEF00C504BE /* whoscallDirectoryExtension */;
targetProxy = 2F60E01E2E66CCEF00C504BE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
......@@ -307,6 +415,87 @@
};
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 */ = {
isa = XCBuildConfiguration;
buildSettings = {
......@@ -463,6 +652,15 @@
defaultConfigurationIsVisible = 0;
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" */ = {
isa = XCConfigurationList;
buildConfigurations = (
......
......@@ -31,10 +31,15 @@
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
<key>NSUserActivityTypes</key>
<array>
<string>INStartAudioCallIntent</string>
<string>INStartVideoCallIntent</string>
</array>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>RCTNewArchEnabled</key>
<false/>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
......
......@@ -14,6 +14,14 @@
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
......@@ -22,10 +30,10 @@
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
<string>85F4.1</string>
</array>
</dict>
</array>
......
import Foundation
import CallKit
class CallDirectoryHandler: CXCallDirectoryProvider {
override func beginRequest(with context: CXCallDirectoryExtensionContext) {
context.delegate = self
// Add numbers to identify (VIPs, spam, etc.)
addIdentificationNumbers(to: context)
// Add numbers to block (if you want)
// addBlockingNumbers(to: context)
context.completeRequest()
}
private func addIdentificationNumbers(to context: CXCallDirectoryExtensionContext) {
// Example: add VIP numbers
// Numbers must be E.164 format (+60 for Malaysia)
let vipNumbers: [(number: Int64, label: String)] = [
(60189884118, "VIP: Wei Yi"),
(60123456789, "Spam Caller"),
]
for entry in vipNumbers {
context.addIdentificationEntry(withNextSequentialPhoneNumber: entry.number,
label: entry.label)
}
}
private func addBlockingNumbers(to context: CXCallDirectoryExtensionContext) {
// Example: block a number
let blockedNumbers: [Int64] = [
60199998888
]
for number in blockedNumbers {
context.addBlockingEntry(withNextSequentialPhoneNumber: number)
}
}
}
// Optional: log errors
extension CallDirectoryHandler: CXCallDirectoryExtensionContextDelegate {
func requestFailed(for extensionContext: CXCallDirectoryExtensionContext, withError error: Error) {
NSLog("Call Directory extension error: \(error.localizedDescription)")
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.callkit.call-directory</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).CallDirectoryHandler</string>
</dict>
<key>NSExtension</key>
<dict>
<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>
</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