@qusaieilouti99/call-manager 0.1.146 → 0.1.147

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.
@@ -44,7 +44,6 @@ object CallEngine {
44
44
  fun onCallEnded(callId: String)
45
45
  }
46
46
 
47
- // --- NEW: Restored LockScreenBypassCallback interface ---
48
47
  interface LockScreenBypassCallback {
49
48
  fun onLockScreenBypassChanged(shouldBypass: Boolean)
50
49
  }
@@ -80,11 +79,9 @@ object CallEngine {
80
79
  private var eventHandler: ((CallEventType, String) -> Unit)? = null
81
80
  private val cachedEvents = mutableListOf<Pair<CallEventType, String>>()
82
81
 
83
- // --- Modern Audio Management State ---
84
82
  private var userSelectedAudioRoute: String? = null
85
83
  private val audioStateLock = Any()
86
84
 
87
- // --- NEW: Restored Lock Screen Bypass State ---
88
85
  private var lockScreenBypassActive = false
89
86
  private val lockScreenBypassCallbacks = mutableSetOf<LockScreenBypassCallback>()
90
87
 
@@ -93,7 +90,7 @@ object CallEngine {
93
90
  if (isInitialized.compareAndSet(false, true)) {
94
91
  appContext = context.applicationContext
95
92
  audioManager = appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
96
- registerAudioDeviceCallback() // Register callback on init
93
+ registerAudioDeviceCallback()
97
94
  Log.d(TAG, "CallEngine initialized successfully")
98
95
  }
99
96
  }
@@ -144,7 +141,6 @@ object CallEngine {
144
141
  stopRingtone()
145
142
  }
146
143
 
147
- // --- NEW: Restored Lock Screen Bypass Functions ---
148
144
  fun registerLockScreenBypassCallback(callback: LockScreenBypassCallback) {
149
145
  lockScreenBypassCallbacks.add(callback)
150
146
  }
@@ -341,11 +337,9 @@ object CallEngine {
341
337
  startForegroundService()
342
338
  keepScreenAwake(true)
343
339
 
344
- // Set initial audio route using the new robust system
345
340
  synchronized(audioStateLock) {
346
- userSelectedAudioRoute = null // Reset any previous user selection
341
+ userSelectedAudioRoute = null
347
342
  }
348
- // Give the audio system a moment to initialize after the call becomes active
349
343
  mainHandler.postDelayed({
350
344
  updateAndApplyAudioRoute()
351
345
  }, 300)
@@ -466,10 +460,6 @@ object CallEngine {
466
460
  it.value.state == CallState.HELD
467
461
  }
468
462
 
469
- /**
470
- * Sets the user's desired audio route. This will be respected until a
471
- * higher-priority device connects or this route becomes unavailable.
472
- */
473
463
  fun setAudioRoute(route: String) {
474
464
  synchronized(audioStateLock) {
475
465
  Log.d(TAG, "User requested audio route: $route")
@@ -478,12 +468,16 @@ object CallEngine {
478
468
  updateAndApplyAudioRoute()
479
469
  }
480
470
 
481
- /**
482
- * Central function to determine and apply the correct audio route.
483
- * This is the single source of truth for audio routing decisions.
484
- */
485
471
  private fun updateAndApplyAudioRoute() {
486
- val call = activeCalls[currentCallId]
472
+ // *** CRITICAL FIX ***
473
+ // Check for null currentCallId *before* using it as a key.
474
+ val callId = currentCallId
475
+ if (callId == null) {
476
+ Log.d(TAG, "Skipping audio route update: currentCallId is null.")
477
+ return
478
+ }
479
+
480
+ val call = activeCalls[callId]
487
481
  if (call == null || call.state != CallState.ACTIVE) {
488
482
  Log.d(TAG, "Skipping audio route update: No active call.")
489
483
  return
@@ -493,11 +487,9 @@ object CallEngine {
493
487
  val am = audioManager ?: return
494
488
  val availableDevices = getAvailableAudioDevices()
495
489
 
496
- // Determine the target route based on priority
497
490
  val targetRoute = if (userSelectedAudioRoute != null && availableDevices.contains(userSelectedAudioRoute)) {
498
- userSelectedAudioRoute!! // Respect user's choice if available
491
+ userSelectedAudioRoute!!
499
492
  } else {
500
- // Auto-select based on priority
501
493
  when {
502
494
  availableDevices.contains("Bluetooth") -> "Bluetooth"
503
495
  availableDevices.contains("Headset") -> "Headset"
@@ -508,7 +500,6 @@ object CallEngine {
508
500
 
509
501
  Log.d(TAG, "Updating audio route. Available: $availableDevices, User Pref: $userSelectedAudioRoute, Target: $targetRoute")
510
502
 
511
- // Apply the target route
512
503
  am.mode = AudioManager.MODE_IN_COMMUNICATION
513
504
 
514
505
  when (targetRoute) {
@@ -534,7 +525,6 @@ object CallEngine {
534
525
  }
535
526
  }
536
527
 
537
- // After applying, emit the result
538
528
  mainHandler.postDelayed({ emitAudioRouteChanged() }, 100)
539
529
  }
540
530
  }
@@ -542,8 +532,8 @@ object CallEngine {
542
532
  private fun getAvailableAudioDevices(): Set<String> {
543
533
  val am = audioManager ?: return emptySet()
544
534
  val devices = mutableSetOf<String>()
545
- devices.add("Earpiece") // Always available
546
- devices.add("Speaker") // Always available
535
+ devices.add("Earpiece")
536
+ devices.add("Speaker")
547
537
 
548
538
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
549
539
  val audioDevices = am.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
@@ -591,7 +581,6 @@ object CallEngine {
591
581
  private val audioDeviceCallback = object : AudioDeviceCallback() {
592
582
  override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>) {
593
583
  Log.d(TAG, "Audio devices added. Triggering audio route update.")
594
- // A new device was added, reset user preference to allow auto-switch to higher priority device
595
584
  synchronized(audioStateLock) {
596
585
  userSelectedAudioRoute = null
597
586
  }
@@ -599,7 +588,6 @@ object CallEngine {
599
588
  }
600
589
  override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>) {
601
590
  Log.d(TAG, "Audio devices removed. Triggering audio route update.")
602
- // A device was removed, if it was the user's selection, clear it
603
591
  synchronized(audioStateLock) {
604
592
  val removedDeviceTypes = removedDevices.map {
605
593
  when(it.type) {
@@ -624,7 +612,6 @@ object CallEngine {
624
612
  Log.d(TAG, "Performing cleanup")
625
613
  stopForegroundService()
626
614
  keepScreenAwake(false)
627
- // Reset audio state
628
615
  synchronized(audioStateLock) {
629
616
  userSelectedAudioRoute = null
630
617
  }
@@ -644,7 +631,6 @@ object CallEngine {
644
631
  description = "Notifications for incoming calls"
645
632
  setBypassDnd(true)
646
633
  lockscreenVisibility = Notification.VISIBILITY_PUBLIC
647
- // **CRITICAL FIX**: Set sound to null. We will manage the ringtone manually.
648
634
  setSound(null, null)
649
635
  }
650
636
  val manager = context.getSystemService(NotificationManager::class.java)
@@ -655,7 +641,7 @@ object CallEngine {
655
641
  private fun showIncomingCallUI(callId: String, callerName: String, callType: String, callerPicUrl: String?) {
656
642
  val context = requireContext()
657
643
  Log.d(TAG, "Showing incoming call UI for $callId")
658
- createNotificationChannel() // Ensure channel is created with correct settings
644
+ createNotificationChannel()
659
645
 
660
646
  showCallActivityOverlay(context, callId, callerName, callType, callerPicUrl)
661
647
  showStandardNotification(context, callId, callerName, callType, callerPicUrl)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.146",
3
+ "version": "0.1.147",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",