Browse Source

FEATURE | Calls

master
Vitalik 7 months ago
parent
commit
62bd56bbff
  1. 5
      android/app/build.gradle
  2. 39
      android/app/google-services.json
  3. 2
      android/app/src/main/AndroidManifest.xml
  4. 1
      android/build.gradle
  5. 25
      ios/CallKitEventHandler.swift
  6. 4
      ios/OneSignalNotificationServiceExtension/NotificationService.swift
  7. 28
      ios/Podfile
  8. 286
      ios/Podfile.lock
  9. 12
      ios/taskme2-Bridging-Header.h
  10. 506
      ios/taskme2.xcodeproj/project.pbxproj
  11. 5
      ios/taskme2.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  12. 17
      ios/taskme2/taskme2Stage.Debug.entitlements
  13. 17
      package-lock.json
  14. 3
      package.json
  15. 18
      src/App.tsx
  16. 9
      src/api/calls/requests.ts
  17. 2
      src/api/notifications/requests.interfaces.ts
  18. 1
      src/config/index.ts
  19. 2
      src/modules/calls/hooks/use-call-data.hook.ts
  20. 10
      src/modules/calls/hooks/use-call-status.hook.ts
  21. 68
      src/modules/calls/hooks/use-call-streams.hook.ts
  22. 12
      src/modules/calls/screens/call/index.tsx
  23. 3
      src/modules/calls/services/call.service.ts
  24. 52
      src/modules/calls/services/callkeep-notifications-android.service.ts
  25. 91
      src/modules/calls/services/callkeep.service.ts
  26. 18
      src/modules/calls/services/callkeep/callkeep-android.service.ts
  27. 3
      src/modules/calls/services/callkeep/callkeep-ios.service.ts
  28. 149
      src/modules/calls/services/callkeep/callkeep-root.service.ts
  29. 9
      src/modules/calls/services/callkeep/callkeep.ts
  30. 1
      src/modules/calls/services/callkeep/index.ts
  31. 20
      src/modules/calls/services/calls-events.service.ts
  32. 2
      src/modules/calls/services/index.ts
  33. 57
      src/modules/calls/services/peer-connection.service.ts
  34. 4
      src/modules/root/index.tsx
  35. 18
      src/modules/root/navigation-groups/users.group.tsx
  36. 3
      src/services/domain/account.service.ts
  37. 9
      src/services/domain/auth.service.ts
  38. 43
      src/services/system/firebas-messaging.service.ts
  39. 4
      src/services/system/notification.service.ts
  40. 6
      src/services/system/real-time.service.ts
  41. 6
      src/services/system/voip-notification.service.ts
  42. 10
      src/shared/events/index.ts

5
android/app/build.gradle

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
apply plugin: "com.android.application"
apply plugin: "com.facebook.react"
apply plugin: 'com.google.gms.google-services'
apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle"
import com.android.build.OutputFile
@ -25,7 +26,7 @@ android { @@ -25,7 +26,7 @@ android {
applicationId "com.app.task_me"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 227
versionCode 228
versionName "2.3"
resValue "string", "build_config_package", "com.app.task_me"
}
@ -87,7 +88,7 @@ dependencies { @@ -87,7 +88,7 @@ dependencies {
implementation("com.facebook.react:react-android")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
implementation project(':react-native-view-pdf')
implementation project(':react-native-view-pdf')\
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {

39
android/app/google-services.json

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
{
"project_info": {
"project_number": "129356575548",
"project_id": "taskme-dae7e",
"storage_bucket": "taskme-dae7e.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:129356575548:android:0d83a97ad1276b3ff26439",
"android_client_info": {
"package_name": "com.app.task_me"
}
},
"oauth_client": [
{
"client_id": "129356575548-iv9mo7k86o4rpgupn67s1gs67se8vioe.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyCigUJBly47PVRbCHItRMwVfxqXct2H8U4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "129356575548-iv9mo7k86o4rpgupn67s1gs67se8vioe.apps.googleusercontent.com",
"client_type": 3
}
]
}
}
}
],
"configuration_version": "1"
}

2
android/app/src/main/AndroidManifest.xml

@ -108,6 +108,8 @@ @@ -108,6 +108,8 @@
</intent-filter>
</service>
<service android:name="io.wazo.callkeep.RNCallKeepBackgroundMessagingService" />
</application>
<queries>

1
android/build.gradle

@ -24,6 +24,7 @@ buildscript { @@ -24,6 +24,7 @@ buildscript {
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath 'com.google.gms:google-services:4.4.1'
}
subprojects { subproject ->
afterEvaluate{

25
ios/CallKitEventHandler.swift

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
import CallKit
class CallObserver: NSObject, CXCallObserverDelegate {
let callObserver = CXCallObserver()
override init() {
super.init()
callObserver.setDelegate(self, queue: nil)
}
func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
if call.hasEnded {
print("Call ended")
} else if call.isOutgoing {
print("Outgoing call")
} else if call.isOnHold {
print("Call on hold")
} else if callObserver.calls.contains(where: { $0.isMuted }) {
print("Call muted")
} else {
print("Call status changed")
}
}
}

4
ios/OneSignalNotificationServiceExtension/NotificationService.swift

@ -13,6 +13,8 @@ class NotificationService: UNNotificationServiceExtension { @@ -13,6 +13,8 @@ class NotificationService: UNNotificationServiceExtension {
self.contentHandler = contentHandler
self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
print("Received silent push notification with type: silent")
if let bestAttemptContent = bestAttemptContent {
//If your SDK version is < 3.5.0 uncomment and use this code:
/*
@ -26,6 +28,8 @@ class NotificationService: UNNotificationServiceExtension { @@ -26,6 +28,8 @@ class NotificationService: UNNotificationServiceExtension {
//OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
//bestAttemptContent.body = "[Modified] " + bestAttemptContent.body
print("Received silent push notification with type: silent")
OneSignal.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
}
}

28
ios/Podfile

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
@ -8,16 +7,6 @@ require Pod::Executable.execute_command('node', ['-p', @@ -8,16 +7,6 @@ require Pod::Executable.execute_command('node', ['-p',
platform :ios, min_ios_version_supported
prepare_react_native_project!
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
#
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
# ```js
# module.exports = {
# dependencies: {
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
# ```
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
@ -32,23 +21,19 @@ target 'taskme2' do @@ -32,23 +21,19 @@ target 'taskme2' do
pod 'react-native-sqlite-storage', :path => '../node_modules/react-native-sqlite-storage'
pod 'react-native-config/Extension', :path => '../node_modules/react-native-config'
pod 'RNCallKeep', :path => '../node_modules/react-native-callkeep'
pod 'ReactNativeIncallManager', :path => '../node_modules/react-native-incall-manager'
# Flags change depending on the env values.
flags = get_default_flags()
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
use_react_native!(
:path => config[:reactNativePath],
# Hermes is now enabled by default. Disable by setting this flag to false.
# Upcoming versions of React Native may rely on get_default_flags(), but
# we make it explicit here to aid in the React Native upgrade process.
:hermes_enabled => flags[:hermes_enabled],
:fabric_enabled => flags[:fabric_enabled],
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable the next line.
:flipper_configuration => flipper_config,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
@ -71,7 +56,6 @@ target 'taskme2' do @@ -71,7 +56,6 @@ target 'taskme2' do
end
end
# Set the preprocessing macro for the whole Pods project
existing_flags = config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
existing_flags << '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = existing_flags

286
ios/Podfile.lock

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
PODS:
- boost (1.76.0)
- CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6)
- FBLazyVector (0.72.10)
- FBReactNativeSpec (0.72.10):
@ -14,66 +13,126 @@ PODS: @@ -14,66 +13,126 @@ PODS:
- ffmpeg-kit-react-native/audio (5.1.0):
- ffmpeg-kit-ios-audio (= 5.1)
- React-Core
- Flipper (0.182.0):
- Flipper-Folly (~> 2.6)
- Flipper-Boost-iOSX (1.76.0.1.11)
- Flipper-DoubleConversion (3.2.0.1)
- Flipper-Fmt (7.1.7)
- Flipper-Folly (2.6.10):
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt (= 7.1.7)
- Flipper-Glog
- libevent (~> 2.1.12)
- OpenSSL-Universal (= 1.1.1100)
- Flipper-Glog (0.5.0.5)
- Flipper-PeerTalk (0.0.4)
- FlipperKit (0.182.0):
- FlipperKit/Core (= 0.182.0)
- FlipperKit/Core (0.182.0):
- Flipper (~> 0.182.0)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- SocketRocket (~> 0.6.0)
- FlipperKit/CppBridge (0.182.0):
- Flipper (~> 0.182.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.182.0):
- Flipper-Folly (~> 2.6)
- FlipperKit/FBDefines (0.182.0)
- FlipperKit/FKPortForwarding (0.182.0):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.182.0)
- FlipperKit/FlipperKitLayoutHelpers (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutPlugin (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutHelpers
- FlipperKit/FlipperKitLayoutIOSDescriptors
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.182.0)
- FlipperKit/FlipperKitNetworkPlugin (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.182.0):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Firebase (10.23.1):
- Firebase/Core (= 10.23.1)
- Firebase/Core (10.23.1):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 10.23.1)
- Firebase/CoreOnly (10.23.1):
- FirebaseCore (= 10.23.1)
- Firebase/Messaging (10.23.1):
- Firebase/CoreOnly
- FirebaseMessaging (~> 10.23.0)
- FirebaseAnalytics (10.23.1):
- FirebaseAnalytics/AdIdSupport (= 10.23.1)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.23.1):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.23.1)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- FirebaseCore (10.23.1):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.12)
- GoogleUtilities/Logger (~> 7.12)
- FirebaseCoreExtension (10.23.0):
- FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.23.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseInstallations (10.23.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.23.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.3)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30911.0, >= 2.30908.0)
- fmt (6.2.1)
- glog (0.3.5)
- GoogleAppMeasurement (10.23.1):
- GoogleAppMeasurement/AdIdSupport (= 10.23.1)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.23.1):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.23.1)
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.23.1):
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
- GoogleUtilities/MethodSwizzler (~> 7.11)
- GoogleUtilities/Network (~> 7.11)
- "GoogleUtilities/NSData+zlib (~> 7.11)"
- nanopb (< 2.30911.0, >= 2.30908.0)
- GoogleDataTransport (9.4.1):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30911.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities (7.13.0):
- GoogleUtilities/AppDelegateSwizzler (= 7.13.0)
- GoogleUtilities/Environment (= 7.13.0)
- GoogleUtilities/ISASwizzler (= 7.13.0)
- GoogleUtilities/Logger (= 7.13.0)
- GoogleUtilities/MethodSwizzler (= 7.13.0)
- GoogleUtilities/Network (= 7.13.0)
- "GoogleUtilities/NSData+zlib (= 7.13.0)"
- GoogleUtilities/Privacy (= 7.13.0)
- GoogleUtilities/Reachability (= 7.13.0)
- GoogleUtilities/SwizzlerTestHelpers (= 7.13.0)
- GoogleUtilities/UserDefaults (= 7.13.0)
- GoogleUtilities/AppDelegateSwizzler (7.13.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Privacy
- GoogleUtilities/Environment (7.13.0):
- GoogleUtilities/Privacy
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/ISASwizzler (7.13.0):
- GoogleUtilities/Privacy
- GoogleUtilities/Logger (7.13.0):
- GoogleUtilities/Environment
- GoogleUtilities/Privacy
- GoogleUtilities/MethodSwizzler (7.13.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/Network (7.13.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Privacy
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.13.0)":
- GoogleUtilities/Privacy
- GoogleUtilities/Privacy (7.13.0)
- GoogleUtilities/Reachability (7.13.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- GoogleUtilities/SwizzlerTestHelpers (7.13.0):
- GoogleUtilities/MethodSwizzler
- GoogleUtilities/UserDefaults (7.13.0):
- GoogleUtilities/Logger
- GoogleUtilities/Privacy
- hermes-engine (0.72.10):
- hermes-engine/Pre-built (= 0.72.10)
- hermes-engine/Pre-built (0.72.10)
@ -91,6 +150,11 @@ PODS: @@ -91,6 +150,11 @@ PODS:
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- nanopb (2.30910.0):
- nanopb/decode (= 2.30910.0)
- nanopb/encode (= 2.30910.0)
- nanopb/decode (2.30910.0)
- nanopb/encode (2.30910.0)
- OneSignalXCFramework (3.12.6):
- OneSignalXCFramework/OneSignalCore (= 3.12.6)
- OneSignalXCFramework/OneSignalExtension (= 3.12.6)
@ -101,7 +165,7 @@ PODS: @@ -101,7 +165,7 @@ PODS:
- OneSignalXCFramework/OneSignalOutcomes
- OneSignalXCFramework/OneSignalOutcomes (3.12.6):
- OneSignalXCFramework/OneSignalCore
- OpenSSL-Universal (1.1.1100)
- PromisesObjC (2.4.0)
- RCT-Folly (2021.07.22.00):
- boost
- DoubleConversion
@ -560,6 +624,8 @@ PODS: @@ -560,6 +624,8 @@ PODS:
- React-perflogger (= 0.72.10)
- ReactNativeExceptionHandler (2.10.10):
- React-Core
- ReactNativeIncallManager (4.2.0):
- React-Core
- rn-fetch-blob (0.12.0):
- React-Core
- RNAudioRecorderPlayer (3.6.6):
@ -580,6 +646,14 @@ PODS: @@ -580,6 +646,14 @@ PODS:
- React-Core
- SDWebImage (~> 5.11.1)
- SDWebImageWebPCoder (~> 0.8.4)
- RNFBApp (19.1.2):
- Firebase/CoreOnly (= 10.23.1)
- React-Core
- RNFBMessaging (19.1.2):
- Firebase/Messaging (= 10.23.1)
- FirebaseCoreExtension
- React-Core
- RNFBApp
- RNFileViewer (2.1.5):
- React-Core
- RNFS (2.20.0):
@ -630,10 +704,8 @@ PODS: @@ -630,10 +704,8 @@ PODS:
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.10)
- SocketRocket (0.6.1)
- TOCropViewController (2.6.1)
- TOCropViewController (2.7.2)
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
@ -641,31 +713,14 @@ DEPENDENCIES: @@ -641,31 +713,14 @@ DEPENDENCIES:
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
- ffmpeg-kit-react-native/audio (from `../node_modules/ffmpeg-kit-react-native/ffmpeg-kit-react-native.podspec`)
- Flipper (= 0.182.0)
- Flipper-Boost-iOSX (= 1.76.0.1.11)
- Flipper-DoubleConversion (= 3.2.0.1)
- Flipper-Fmt (= 7.1.7)
- Flipper-Folly (= 2.6.10)
- Flipper-Glog (= 0.5.0.5)
- Flipper-PeerTalk (= 0.0.4)
- FlipperKit (= 0.182.0)
- FlipperKit/Core (= 0.182.0)
- FlipperKit/CppBridge (= 0.182.0)
- FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0)
- FlipperKit/FBDefines (= 0.182.0)
- FlipperKit/FKPortForwarding (= 0.182.0)
- FlipperKit/FlipperKitHighlightOverlay (= 0.182.0)
- FlipperKit/FlipperKitLayoutPlugin (= 0.182.0)
- FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0)
- FlipperKit/FlipperKitNetworkPlugin (= 0.182.0)
- FlipperKit/FlipperKitReactPlugin (= 0.182.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0)
- FlipperKit/SKIOSNetworkPlugin (= 0.182.0)
- Firebase
- FirebaseCore
- FirebaseCoreInternal
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- GoogleUtilities
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
- libevent (~> 2.1.12)
- OneSignalXCFramework (< 4.0, >= 3.0)
- OpenSSL-Universal (= 1.1.1100)
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
@ -673,7 +728,6 @@ DEPENDENCIES: @@ -673,7 +728,6 @@ DEPENDENCIES:
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Codegen (from `build/generated/ios`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
@ -720,6 +774,7 @@ DEPENDENCIES: @@ -720,6 +774,7 @@ DEPENDENCIES:
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- ReactNativeExceptionHandler (from `../node_modules/react-native-exception-handler`)
- ReactNativeIncallManager (from `../node_modules/react-native-incall-manager`)
- rn-fetch-blob (from `../node_modules/rn-fetch-blob`)
- RNAudioRecorderPlayer (from `../node_modules/react-native-audio-recorder-player`)
- RNCallKeep (from `../node_modules/react-native-callkeep`)
@ -729,6 +784,8 @@ DEPENDENCIES: @@ -729,6 +784,8 @@ DEPENDENCIES:
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFastImage (from `../node_modules/react-native-fast-image`)
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
- RNFS (from `../node_modules/react-native-fs`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
@ -747,27 +804,28 @@ DEPENDENCIES: @@ -747,27 +804,28 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- CocoaAsyncSocket
- ffmpeg-kit-ios-audio
- Flipper
- Flipper-Boost-iOSX
- Flipper-DoubleConversion
- Flipper-Fmt
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- FlipperKit
- Firebase
- FirebaseAnalytics
- FirebaseCore
- FirebaseCoreExtension
- FirebaseCoreInternal
- FirebaseInstallations
- FirebaseMessaging
- fmt
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleUtilities
- JitsiWebRTC
- libevent
- libwebp
- nanopb
- OneSignalXCFramework
- OpenSSL-Universal
- PromisesObjC
- SDWebImage
- SDWebImageWebPCoder
- SocketRocket
- TOCropViewController
- YogaKit
EXTERNAL SOURCES:
boost:
@ -886,6 +944,8 @@ EXTERNAL SOURCES: @@ -886,6 +944,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
ReactNativeExceptionHandler:
:path: "../node_modules/react-native-exception-handler"
ReactNativeIncallManager:
:path: "../node_modules/react-native-incall-manager"
rn-fetch-blob:
:path: "../node_modules/rn-fetch-blob"
RNAudioRecorderPlayer:
@ -904,6 +964,10 @@ EXTERNAL SOURCES: @@ -904,6 +964,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-device-info"
RNFastImage:
:path: "../node_modules/react-native-fast-image"
RNFBApp:
:path: "../node_modules/@react-native-firebase/app"
RNFBMessaging:
:path: "../node_modules/@react-native-firebase/messaging"
RNFileViewer:
:path: "../node_modules/react-native-file-viewer"
RNFS:
@ -937,28 +1001,30 @@ EXTERNAL SOURCES: @@ -937,28 +1001,30 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: 7dcd2de282d72e344012f7d6564d024930a6a440
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
FBLazyVector: f91d538f197fa71a7d5b77ec2069d49550c0eb96
FBReactNativeSpec: b13d1c23d6ed82d6b66aad7a253edf8ba76c4a4c
ffmpeg-kit-ios-audio: 6eaf5a3c4249b767328502747a08bfd901a86d3d
ffmpeg-kit-react-native: 56ecfcd21536379dd123eade87c3b6fd55f12030
Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30
Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b
Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3
Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6
Firebase: cf09623f98ae25a3ad484e23c7e0e5f464152d80
FirebaseAnalytics: fd35d51e6da86ef1aa2c3fe1f64ab2482cc01ba5
FirebaseCore: c43f9f0437b50a965e930cac4ad243200d12a984
FirebaseCoreExtension: cb88851781a24e031d1b58e0bd01eb1f46b044b5
FirebaseCoreInternal: 6a292e6f0bece1243a737e81556e56e5e19282e3
FirebaseInstallations: 42d6ead4605d6eafb3b6683674e80e18eb6f2c35
FirebaseMessaging: 1b2270e66c81bbf184f70184db1d6a736ad0def5
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
GoogleAppMeasurement: 794d1d2f71fdf77a077a3986258a5c2dac0f9d48
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152
hermes-engine: 90e4033deb00bee33330a9f15eff0f874bd82f6d
JitsiWebRTC: 3a41671ef65a51d7204323814b055a2690b921c7
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
nanopb: 438bc412db1928dac798aa6fd75726007be04262
OneSignalXCFramework: ff1c970b7aeb4ac0fe48fb35393eb5d8bf378135
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
RCTRequired: b4d3068afa6f52ec5260a8417053b1f1b421483d
RCTTypeSafety: a4551b3d338c96435f63bf06d564055c1d3cc0ac
@ -1010,6 +1076,7 @@ SPEC CHECKSUMS: @@ -1010,6 +1076,7 @@ SPEC CHECKSUMS:
React-utils: 372b83030a74347331636909278bf0a60ec30d59
ReactCommon: 38824bfffaf4c51fbe03a2730b4fd874ef34d67b
ReactNativeExceptionHandler: b11ff67c78802b2f62eed0e10e75cb1ef7947c60
ReactNativeIncallManager: bfc9c67358cd524882a7c4116dcb311ac2293d4b
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
RNAudioRecorderPlayer: f790fc1afb118552ae6285d60adde52ee6b5d9ef
RNCallKeep: aa9b1f9286f8f60d7b7d41ee5de47de564356aac
@ -1019,6 +1086,8 @@ SPEC CHECKSUMS: @@ -1019,6 +1086,8 @@ SPEC CHECKSUMS:
RNDateTimePicker: fc2e4f2795877d45e84d85659bebe627eba5c931
RNDeviceInfo: db5c64a060e66e5db3102d041ebe3ef307a85120
RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8
RNFBApp: 5cbbb49393dc840f46b227ae483d11d502ed36a8
RNFBMessaging: f5ed5b4ef1b17f946b785cb7fa0d8d555a5e12b2
RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
RNGestureHandler: 7909c50383a18f0cb10ce1db7262b9a6da504c03
@ -1036,10 +1105,9 @@ SPEC CHECKSUMS: @@ -1036,10 +1105,9 @@ SPEC CHECKSUMS:
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
TOCropViewController: bf38459e9da6efe414de22087ebd5c530640f4bd
Yoga: d0003f849d2b5224c072cef6568b540d8bb15cd3
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: cfc20c55adde2f7a0a48df5c2ebe42052a891ffa
PODFILE CHECKSUM: 3a44448b547a3316bb952755f0a413dd0086c662
COCOAPODS: 1.15.2

12
ios/taskme2-Bridging-Header.h

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
//
// taskme2-Bridging-Header.h
// taskme2
//
// Created by mac on 14.04.2024.
//
#ifndef taskme2_Bridging_Header_h
#define taskme2_Bridging_Header_h
#endif /* taskme2_Bridging_Header_h */

506
ios/taskme2.xcodeproj/project.pbxproj

File diff suppressed because one or more lines are too long

5
ios/taskme2.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
<?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/>
</plist>

17
ios/taskme2/taskme2Stage.Debug.entitlements

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
<?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>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:example.com</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.app.taskme</string>
<string>group.com.app.taskme.stage.onesignal</string>
</array>
</dict>
</plist>

17
package-lock.json generated

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/datetimepicker": "^7.6.2",
"@react-native-community/netinfo": "^9.3.10",
"@react-native-firebase/app": "^19.1.2",
"@react-native-firebase/messaging": "^19.1.2",
"@react-native-picker/picker": "^2.4.10",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.11",
@ -63,6 +65,7 @@ @@ -63,6 +65,7 @@
"react-native-html-to-pdf": "^0.12.0",
"react-native-image-crop-picker": "^0.40.0",
"react-native-image-picker": "^5.6.0",
"react-native-incall-manager": "^4.2.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-masked-text": "^1.13.0",
"react-native-modal": "^13.0.1",
@ -12351,6 +12354,14 @@ @@ -12351,6 +12354,14 @@
"react-native": "*"
}
},
"node_modules/react-native-incall-manager": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-native-incall-manager/-/react-native-incall-manager-4.2.0.tgz",
"integrity": "sha512-DC5XRQVAwNgNA6YZ3ILF6ttWXv/MUQ4omzmVDh/uHc0TW0v4f8QIdt6D9GHZhGKb3+qB7XKUxpXVBrLH+9zqfQ==",
"peerDependencies": {
"react-native": ">=0.40.0"
}
},
"node_modules/react-native-iphone-x-helper": {
"version": "1.3.1",
"license": "MIT",
@ -22177,6 +22188,12 @@ @@ -22177,6 +22188,12 @@
"version": "5.7.0",
"requires": {}
},
"react-native-incall-manager": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/react-native-incall-manager/-/react-native-incall-manager-4.2.0.tgz",
"integrity": "sha512-DC5XRQVAwNgNA6YZ3ILF6ttWXv/MUQ4omzmVDh/uHc0TW0v4f8QIdt6D9GHZhGKb3+qB7XKUxpXVBrLH+9zqfQ==",
"requires": {}
},
"react-native-iphone-x-helper": {
"version": "1.3.1",
"requires": {}

3
package.json

@ -28,6 +28,8 @@ @@ -28,6 +28,8 @@
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/datetimepicker": "^7.6.2",
"@react-native-community/netinfo": "^9.3.10",
"@react-native-firebase/app": "^19.1.2",
"@react-native-firebase/messaging": "^19.1.2",
"@react-native-picker/picker": "^2.4.10",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.11",
@ -73,6 +75,7 @@ @@ -73,6 +75,7 @@
"react-native-html-to-pdf": "^0.12.0",
"react-native-image-crop-picker": "^0.40.0",
"react-native-image-picker": "^5.6.0",
"react-native-incall-manager": "^4.2.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-masked-text": "^1.13.0",
"react-native-modal": "^13.0.1",

18
src/App.tsx

@ -7,7 +7,7 @@ if (__DEV__) { @@ -7,7 +7,7 @@ if (__DEV__) {
}
import { ThemeProvider } from './shared/themes'
import { AppState, LogBox, Platform } from 'react-native'
import { Alert, AppState, LogBox, Platform } from 'react-native'
import { appService } from './services/app.service'
import 'react-native-gesture-handler'
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'
@ -19,12 +19,18 @@ import Toast from 'react-native-toast-message' @@ -19,12 +19,18 @@ import Toast from 'react-native-toast-message'
import { toastConfig } from './config/toast.config'
import { VoipNotificationsService } from './services/system'
import { callKeepService } from './modules/calls/services/callkeep.service'
import './modules/calls/services/calls-events.service'
import { callKeepService } from './modules/calls/services/callkeep/callkeep'
LogBox.ignoreLogs(['Warning: ...', 'Require cycle: ...'])
LogBox.ignoreAllLogs()
if (Platform.OS === 'android') {
require('./modules/calls/services/callkeep-notifications-android.service')
}
callKeepService.register()
const App: FC = () => {
useEffect(() => {
appService.initApp()
@ -47,14 +53,6 @@ const App: FC = () => { @@ -47,14 +53,6 @@ const App: FC = () => {
}
}, [])
useEffect(() => {
// console.log(callsEventsService)
callKeepService.register()
return () => {
callKeepService.unregister()
}
}, [])
useEffect(() => {
if (Platform.OS === 'ios') {
VoipNotificationsService.getInstance().initListeners()

9
src/api/calls/requests.ts

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
import { ICall } from '@/shared'
import api from '../http.service'
import {
IAnswerCallPayload,
@ -37,3 +38,11 @@ export const deleteCallHistoryReq = (callId: number) => { @@ -37,3 +38,11 @@ export const deleteCallHistoryReq = (callId: number) => {
export const getIncomeDataReq = (callId: string, targetDeviceId: string) => {
return api.post(`calls/income/${callId}`, { targetDeviceId }, {}, '')
}
export const sendNegotiationReq = (callId: string, payload: any) => {
return api.post(`calls/negotiation/${callId}`, payload, null, '')
}
export const getCallReq = (callId: string) => {
return api.get<ICall>(`calls/${callId}`, {}, '')
}

2
src/api/notifications/requests.interfaces.ts

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
export interface ISaveDevicePayload {
deviceUuid: string
notificationUserId: string
isVoip?: boolean
type?: string
isDev?: boolean
}

1
src/config/index.ts

@ -7,6 +7,7 @@ export const dynamicConfig = { @@ -7,6 +7,7 @@ export const dynamicConfig = {
baseUrl: Config.API_URL,
socketUrl: Config.SOCKET_URL,
oneSignalKey: Config.ONE_SIGNAL_KEY,
appStoreUrl: 'https://apps.apple.com/ua/app/task-me/id1482240685?l=uk',
googlePlayUrl:
'https://play.google.com/store/apps/details?id=com.app.task_me',

2
src/modules/calls/hooks/use-call-data.hook.ts

@ -17,6 +17,7 @@ export interface CallDataStore { @@ -17,6 +17,7 @@ export interface CallDataStore {
remoteRTCMessage?: any
icecandidates: any[]
connectedStatus: RTCIceConnectionState
isIncomeCall?: boolean // true if device answering, false if device calling
changeMod: (mod: CallMod) => void
startCall: (targetUserId: number, peerConnection: RTCPeerConnection) => void
@ -67,6 +68,7 @@ export const useCallDataStore = create<CallDataStore>()(set => ({ @@ -67,6 +68,7 @@ export const useCallDataStore = create<CallDataStore>()(set => ({
remoteRTCMessage,
mod: CallMod.Incoming,
peerConnection,
isIncomeCall: true,
})
},

10
src/modules/calls/hooks/use-call-status.hook.ts

@ -1,16 +1,6 @@ @@ -1,16 +1,6 @@
import { useMemo } from 'react'
import { useCallDataStore } from './use-call-data.hook'
const rtcStatusLabel: Record<RTCIceConnectionState, string> = {
new: "З'єднання",
checking: '',
closed: '',
completed: '',
disconnected: '',
failed: '',
connected: '',
}
export const useCallStatus = () => {
const connectedStatus = useCallDataStore(s => s.connectedStatus)

68
src/modules/calls/hooks/use-call-streams.hook.ts

@ -2,13 +2,16 @@ import { useEffect, useMemo, useState } from 'react' @@ -2,13 +2,16 @@ import { useEffect, useMemo, useState } from 'react'
import { MediaStream, mediaDevices } from 'react-native-webrtc'
import { create } from 'zustand'
import { peerConnectionService } from '../services'
import { useEventsListener } from '@/shared'
import { appEvents, useEventsListener } from '@/shared'
import InCallManager from 'react-native-incall-manager'
import RNCallKeep from 'react-native-callkeep'
import { useCallDataStore } from './use-call-data.hook'
export interface ICallStreamsStore {
localStream: MediaStream
remoteStream: MediaStream
isMicOn: boolean
isCameraOn: boolean
isSpeakerOn: boolean
remoteVideoOn: boolean
@ -17,6 +20,7 @@ export interface ICallStreamsStore { @@ -17,6 +20,7 @@ export interface ICallStreamsStore {
setMicOn: (isMicOn: boolean) => void
setCameraOn: (isCameraOn: boolean) => void
setRemoveVideoOn: (removeVideoOn: boolean) => void
setSpeakerOn: (isSpeakerOn: boolean) => void
}
const callsStreamStore = create<ICallStreamsStore>()(set => ({
@ -25,6 +29,7 @@ const callsStreamStore = create<ICallStreamsStore>()(set => ({ @@ -25,6 +29,7 @@ const callsStreamStore = create<ICallStreamsStore>()(set => ({
isMicOn: true,
isCameraOn: true,
remoteVideoOn: true,
isSpeakerOn: true,
setLocalStream(localStream) {
set({ localStream })
@ -44,6 +49,10 @@ const callsStreamStore = create<ICallStreamsStore>()(set => ({ @@ -44,6 +49,10 @@ const callsStreamStore = create<ICallStreamsStore>()(set => ({
setRemoveVideoOn(remoteVideoOn) {
set({ remoteVideoOn })
},
setSpeakerOn(isSpeakerOn) {
set({ isSpeakerOn })
},
}))
export const useCallsStream = callsStreamStore
@ -70,30 +79,39 @@ export const initCallsMediaDevices = async (peerConnection: any) => { @@ -70,30 +79,39 @@ export const initCallsMediaDevices = async (peerConnection: any) => {
}
export const useLocalStream = () => {
const localMicOn = callsStreamsCtr().isMicOn
const isCameraOn = callsStreamsCtr().isCameraOn
const localStream = callsStreamsCtr().localStream
function toogleMic() {
callsStreamsCtr().setMicOn(!localMicOn)
const localMicOn = callsStreamStore(s => s.isMicOn)
const isCameraOn = callsStreamStore(s => s.isCameraOn)
const localStream = callsStreamStore(s => s.localStream)
function toogleMic(value?: boolean, slientChange = false) {
const isOn = value ? value : !localMicOn
callsStreamsCtr().setMicOn(isOn)
console.log('isOne', isOn)
localStream.getAudioTracks().forEach(track => {
localMicOn ? (track.enabled = false) : (track.enabled = true)
!isOn ? (track.enabled = false) : (track.enabled = true)
})
peerConnectionService.sendMessage({
type: 'changeMicro',
value: !localMicOn,
})
// if (!slientChange) {
// appEvents.emit('callSettingUpdated', {})
// }
}
function toogleCamera() {
callsStreamsCtr().setCameraOn(!isCameraOn)
function toogleCamera(value?: boolean, slientChange = false) {
const isOn = value ? value : !isCameraOn
callsStreamsCtr().setCameraOn(isOn)
localStream.getVideoTracks().forEach(track => {
isCameraOn ? (track.enabled = false) : (track.enabled = true)
!isOn ? (track.enabled = false) : (track.enabled = true)
})
peerConnectionService.sendMessage({
type: 'changeVideo',
value: !isCameraOn,
})
// if (!slientChange) {
// appEvents.emit('callSettingUpdated', {})
// }
}
return {
@ -110,9 +128,33 @@ export const useRemoteStream = () => { @@ -110,9 +128,33 @@ export const useRemoteStream = () => {
const remoteVideoOn = callsStreamStore(s => s.remoteVideoOn)
useEventsListener('call-channel/changeVideo', ({ value }) => {
console.log('value', value)
callsStreamsCtr().setRemoveVideoOn(value)
})
return { isRemoteCameraOn: remoteVideoOn }
}
export const useAudioOutput = () => {
const isSpeakerOn = callsStreamStore(s => s.isSpeakerOn)
useEffect(() => {
InCallManager.setForceSpeakerphoneOn(isSpeakerOn)
}, [])
const toggleSpeaker = async () => {
try {
callsStreamsCtr().setSpeakerOn(!isSpeakerOn)
InCallManager.setForceSpeakerphoneOn(!isSpeakerOn)
appEvents.emit('callSettingUpdated', {})
} catch (error) {
console.error('Error setting speaker mode:', error)
}
}
return {
isSpeakerOn,
toggleSpeaker,
}
}

12
src/modules/calls/screens/call/index.tsx

@ -3,6 +3,7 @@ import { CallingAtom, OutgoingcallAtom } from './atoms' @@ -3,6 +3,7 @@ import { CallingAtom, OutgoingcallAtom } from './atoms'
import { Button } from '@/shared'
import {
CallMod,
useAudioOutput,
useCallDataStore,
useCallFromStore,
useCallStatus,
@ -22,13 +23,12 @@ export const CallScreen = () => { @@ -22,13 +23,12 @@ export const CallScreen = () => {
const { title, avatarImageUrl } = useCallFromStore()
const { label } = useCallStatus()
const { toogleMic, localMicOn, isCameraOn, toogleCamera } = useLocalStream()
const { isSpeakerOn, toggleSpeaker } = useAudioOutput()
const { isRemoteCameraOn } = useRemoteStream()
const stopCall = () => {
callService.stop()
}
console.log('isRemoteCameraOn', isRemoteCameraOn)
const templates = {
[CallMod.Speaking]: (
<CallBackground
@ -48,9 +48,9 @@ export const CallScreen = () => { @@ -48,9 +48,9 @@ export const CallScreen = () => {
<View style={styles.callRow}>
<CallBtn
iconName="speakerhigh"
bgColor="#fff"
bgColor={isSpeakerOn ? '#fff' : 'grey'}
isAnimated={false}
onPress={stopCall}
onPress={() => toggleSpeaker()}
iconColor="#000"
style={styles.callBtn}
/>
@ -61,7 +61,7 @@ export const CallScreen = () => { @@ -61,7 +61,7 @@ export const CallScreen = () => {
}
bgColor="#fff"
isAnimated={false}
onPress={toogleCamera}
onPress={() => toogleCamera()}
iconColor="#000"
style={styles.callBtn}
/>
@ -69,7 +69,7 @@ export const CallScreen = () => { @@ -69,7 +69,7 @@ export const CallScreen = () => {
iconName={localMicOn ? 'microphone' : 'microphoneslash'}
bgColor="#fff"
isAnimated={false}
onPress={toogleMic}
onPress={() => toogleMic()}
iconColor="#000"
style={styles.callBtn}
/>

3
src/modules/calls/services/call.service.ts

@ -7,8 +7,7 @@ import { RouteKey } from '@/shared' @@ -7,8 +7,7 @@ import { RouteKey } from '@/shared'
import { StopCall } from '../core/stop-call'
import { cancelCallReq } from '@/api/calls/requests'
import { RTCSessionDescription } from 'react-native-webrtc'
import { callKeepService } from './callkeep.service'
import { callKeepService } from './callkeep'
class CallService extends CallRoot {
public async proccesIncome(data: any) {
const peerConnection = await peerConnectionService.createIns()

52
src/modules/calls/services/callkeep-notifications-android.service.ts

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
import messaging from '@react-native-firebase/messaging'
import RNCallKeep from 'react-native-callkeep'
messaging().setBackgroundMessageHandler(async message => {
const data = message.data as any
if (!data) {
return
}
if (data?.type === 'callAnswered') {
RNCallKeep.endAllCalls()
return
}
if (data?.uuid) {
RNCallKeep.displayIncomingCall(
data.uuid,
data.handle,
data.callerName,
'number',
false,
)
}
})
messaging().onMessage(async message => {
try {
const data = message.data as any
if (!data) {
return
}
if (data?.type === 'callAnswered') {
RNCallKeep.endAllCalls()
return
}
if (data?.uuid) {
RNCallKeep.displayIncomingCall(
data.uuid,
data.handle,
data.callerName,
'number',
false,
)
}
} catch (e) {
console.log(e)
}
})

91
src/modules/calls/services/callkeep.service.ts

@ -1,91 +0,0 @@ @@ -1,91 +0,0 @@
import { getIncomeDataReq } from '@/api/calls/requests'
import RNCallKeep from 'react-native-callkeep'
import { CallRoot } from './call-root.service'
import { Platform } from 'react-native'
import { appEvents } from '@/shared'
import { DeviceInfoService } from '@/services/system'
class CallKeepService extends CallRoot {
public register() {
this.init()
this.initListeners()
}
public unregister() {
this.removeListeners()
}
private async init() {
RNCallKeep.endAllCalls()
RNCallKeep.setup({
ios: {
appName: 'TaskMe',
includesCallsInRecents: false,
maximumCallGroups: '1',
supportsVideo: false,
},
android: {
alertTitle: 'Permissions required',
alertDescription:
'This application needs to access your phone accounts',
cancelButton: 'Cancel',
okButton: 'ok',
imageName: 'phone_account_icon',
additionalPermissions: [],
foregroundService: {
channelId: 'com.company.my',
channelName: 'Foreground service for my app',
notificationTitle: 'My app is running on background',
notificationIcon:
'Path to the resource icon of the notification',
},
},
})
}
private initListeners() {
RNCallKeep.addEventListener('answerCall', this.onAnswer.bind(this))
RNCallKeep.addEventListener('endCall', this.onEnd.bind(this))
RNCallKeep.addEventListener(
'didPerformSetMutedCallAction',
this.changeMuted.bind(this),
)
}
private removeListeners() {
RNCallKeep.clearInitialEvents()
RNCallKeep.removeEventListener('answerCall')
RNCallKeep.removeEventListener('endCall')
RNCallKeep.removeEventListener('didPerformSetMutedCallAction')
}
private async onAnswer(data: any) {
try {
appEvents.emit('closeConfirmModal', {})
const id = await DeviceInfoService.getDeviceUniqueId()
getIncomeDataReq(data.callUUID, id)
} catch (e) {
console.log('Error on answer', e)
}
}
private async onEnd() {
console.log('onend')
}
private async changeMuted() {
console.log('changemuted')
}
public async stop() {
RNCallKeep.endCall(this.store.callId)
RNCallKeep.endAllCalls()
}
public async handleAcceptedIncomeInOtherDevice(uuid: string) {
RNCallKeep.rejectCall(uuid)
RNCallKeep.endAllCalls()
}
}
export const callKeepService = new CallKeepService()

18
src/modules/calls/services/callkeep/callkeep-android.service.ts

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
import RNCallKeep from 'react-native-callkeep'
import { CallKeepRootService } from './callkeep-root.service'
export class CallkeepAndroidService extends CallKeepRootService {
protected async onAnswer(data: any) {
RNCallKeep.backToForeground()
RNCallKeep.setConnectionState(data.callUUID, 128)
await delay(100)
RNCallKeep.endAllCalls()
RNCallKeep.endCall(data.callUUID)
super.onAnswer(data)
}
}
function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}

3
src/modules/calls/services/callkeep/callkeep-ios.service.ts

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
import { CallKeepRootService } from './callkeep-root.service'
export class CallkeepIosService extends CallKeepRootService {}

149
src/modules/calls/services/callkeep/callkeep-root.service.ts

@ -0,0 +1,149 @@ @@ -0,0 +1,149 @@
import { getCallReq, getIncomeDataReq } from '@/api/calls/requests'
import RNCallKeep from 'react-native-callkeep'
import { CallStatus, appEvents } from '@/shared'
import { DeviceInfoService } from '@/services/system'
import { CallRoot } from '../call-root.service'
import { useLocalStream } from '../../hooks'
export class CallKeepRootService extends CallRoot {
protected accountInited = false
protected waitingToAnswerData?: any
public register() {
this.init()
this.initListeners()
}
public unregister() {
this.removeListeners()
}
protected async init() {
RNCallKeep.setup({
ios: {
appName: 'TaskMe',
includesCallsInRecents: false,
maximumCallGroups: '1',
supportsVideo: false,
},
android: {
alertTitle: 'Permissions required',
alertDescription:
'This application needs to access your phone accounts',
cancelButton: 'Cancel',
okButton: 'ok',
imageName: 'phone_account_icon',
additionalPermissions: [],
foregroundService: {
channelId: 'com.company.my',
channelName: 'Foreground service for my app',
notificationTitle: 'My app is running on background',
notificationIcon:
'Path to the resource icon of the notification',
},
},
})
RNCallKeep.endAllCalls()
}
protected async initListeners() {
RNCallKeep.addEventListener('answerCall', this.onAnswer.bind(this))
RNCallKeep.addEventListener('endCall', this.onEnd.bind(this))
RNCallKeep.addEventListener(
'didPerformSetMutedCallAction',
this.changeMuted.bind(this),
)
RNCallKeep.addEventListener(
'didDisplayIncomingCall',
this.onDisplayIncomingCal.bind(this),
)
appEvents.on('onAccountWasLoaded', () => {
this.accountInited = true
})
appEvents.on(
'callSettingUpdated',
this.onCallSettingsUpdateByApp.bind(this),
)
}
protected removeListeners() {
RNCallKeep.removeEventListener('answerCall')
RNCallKeep.removeEventListener('endCall')
RNCallKeep.removeEventListener('didPerformSetMutedCallAction')
}
protected async onDisplayIncomingCal(data) {
const { data: call } = await getCallReq(data.callUUID)
if (call.status !== CallStatus.New) {
RNCallKeep.endCall(data.callUUID)
}
}
protected async onAnswer(data: any) {
const { data: call } = await getCallReq(data.callUUID)
if (call.status !== CallStatus.New) {
appEvents.emit('openInfoModal', {
title: 'Звінок вже завершився',
message:
'Ініціатор скасував виклик або виклик був прийнятий на іншому девайсі',
})
RNCallKeep.endAllCalls()
return
}
if (!this.accountInited) {
this.waitingToAnswerData = data
} else {
await this.startAnswering(data)
}
}
public async startAnswering(data?: any) {
const payload = data ? data : this.waitingToAnswerData
appEvents.emit('closeConfirmModal', {})
const id = await DeviceInfoService.getDeviceUniqueId()
await getIncomeDataReq(payload.callUUID, id)
}
protected async onEnd() {
console.log('onend')
}
protected async changeMuted({ muted }) {
console.log('changemuted', muted)
// useLocalStream().toogleMic()
}
protected async onCallSettingsUpdateByApp() {
console.log('UPDATED')
const from = this.storeFrom.title
const callId = this.store.callId
RNCallKeep.updateDisplay(callId, from, 'generic', {
hasVideo: this.streamsStore.isCameraOn,
})
RNCallKeep.setMutedCall(callId, this.streamsStore.isMicOn)
}
public async stop() {
RNCallKeep.endCall(this.store.callId)
RNCallKeep.endAllCalls()
}
public async handleAcceptedIncomeInOtherDevice(uuid: string) {
RNCallKeep.rejectCall(uuid)
RNCallKeep.endAllCalls()
}
}
function delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}

9
src/modules/calls/services/callkeep/callkeep.ts

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
import { Platform } from 'react-native'
import { CallkeepIosService } from './callkeep-ios.service'
import { CallkeepAndroidService } from './callkeep-android.service'
import { CallKeepRootService } from './callkeep-root.service'
export const callKeepService = Platform.select<CallKeepRootService>({
ios: new CallkeepIosService(),
android: new CallkeepAndroidService(),
})

1
src/modules/calls/services/callkeep/index.ts

@ -0,0 +1 @@ @@ -0,0 +1 @@
export * from './callkeep'

20
src/modules/calls/services/calls-events.service.ts

@ -3,9 +3,10 @@ import { CallRoot } from './call-root.service' @@ -3,9 +3,10 @@ import { CallRoot } from './call-root.service'
import { CallMod } from '../hooks'
import { callService } from './call.service'
import { DeviceInfoService, NavigationService } from '@/services/system'
import { Alert } from 'react-native'
import { RTCIceCandidate, RTCSessionDescription } from 'react-native-webrtc'
import { callKeepService } from './callkeep.service'
import { callKeepService } from './callkeep'
import { peerConnectionService } from './peer-connection.service'
import RNCallKeep from 'react-native-callkeep'
class CallsEventsService extends CallRoot {
constructor() {
@ -15,9 +16,12 @@ class CallsEventsService extends CallRoot { @@ -15,9 +16,12 @@ class CallsEventsService extends CallRoot {
private init() {
socketEvents.on('call/answered', data => {
console.log('[answered]')
this.store.peerConnection.setRemoteDescription(
new RTCSessionDescription(data.rtcMessage),
)
peerConnectionService.sendIcecandidates()
this.store.changeMod(CallMod.Speaking)
this.proccessIceCandidates()
})
@ -26,6 +30,17 @@ class CallsEventsService extends CallRoot { @@ -26,6 +30,17 @@ class CallsEventsService extends CallRoot {
'call/ICEcandidate',
this.proccessIceCandidateEvent.bind(this),
)
socketEvents.on('call/negotiation', async data => {
this.store.peerConnection.setRemoteDescription(data.rtcMessage)
})
socketEvents.on('calls/answered-by-another-device', async data => {
console.log('calls/answered-by-another-device', data)
const deviceId = await DeviceInfoService.getDeviceUniqueId()
if (deviceId !== data.deviceUuid) {
RNCallKeep.endAllCalls()
}
})
}
private proccessIceCandidates() {
@ -40,7 +55,6 @@ class CallsEventsService extends CallRoot { @@ -40,7 +55,6 @@ class CallsEventsService extends CallRoot {
}
private async proccessNewCall(data) {
console.log('procces new call', data)
const id = await DeviceInfoService.getDeviceUniqueId()
if (data.targetUserDeviceId !== id) {
callKeepService.handleAcceptedIncomeInOtherDevice(data.callId)

2
src/modules/calls/services/index.ts

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
export * from './call-root.service'
export * from './call-utility.service'
export * from './call.service'
export * from './callkeep.service'
export * from './callkeep'
export * from './calls-events.service'
export * from './peer-connection.service'

57
src/modules/calls/services/peer-connection.service.ts

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
import { MediaStream, RTCPeerConnection } from 'react-native-webrtc'
import { iceServers } from '../configs'
import { CallRoot } from './call-root.service'
import { iceCandidateReq } from '@/api/calls/requests'
import { iceCandidateReq, sendNegotiationReq } from '@/api/calls/requests'
import {
CallMod,
callsStreamsCtr,
@ -14,10 +14,14 @@ import { Alert } from 'react-native' @@ -14,10 +14,14 @@ import { Alert } from 'react-native'
import { appEvents } from '@/shared'
class PeerConnectionService extends CallRoot {
private icecandidates: any[]
private dataChannel: RTCDataChannel
private remoteDataChannel: RTCDataChannel
public async createIns() {
this.icecandidates = []
const peerConnection = new RTCPeerConnection({
iceServers: iceServers,
})
@ -45,18 +49,25 @@ class PeerConnectionService extends CallRoot { @@ -45,18 +49,25 @@ class PeerConnectionService extends CallRoot {
peerConnection.addEventListener('icecandidate', event => {
if (event.candidate === null) {
if (this.store.isIncomeCall) {
this.sendIcecandidates()
}
return
}
iceCandidateReq({
targetUserId: this.store.targetUserId,
candidates: [event.candidate],
})
// iceCandidateReq({
// targetUserId: this.store.targetUserId,
// candidates: [event.candidate],
// })
this.icecandidates.push(event.candidate)
})
peerConnection.addEventListener('iceconnectionstatechange', event => {
this.store.setConnectedStatus(peerConnection.iceConnectionState)
console.log('ICESTATUS', peerConnection.iceConnectionState)
if (
['completed', 'connected'].includes(
peerConnection.iceConnectionState,
@ -76,6 +87,33 @@ class PeerConnectionService extends CallRoot { @@ -76,6 +87,33 @@ class PeerConnectionService extends CallRoot {
new StopCall(useCallDataStore.getState, callsStreamsCtr).stop()
}
})
peerConnection.addEventListener('negotiationneeded', async () => {
try {
console.log('Negotiation needed', peerConnection.signalingState)
if (peerConnection.signalingState === 'stable') {
const offer = await peerConnection.createOffer({})
await peerConnection.setLocalDescription(offer)
console.log('offer')
sendNegotiationReq(this.store.callId, {
type: 'offer',
description: offer,
})
} else {
const answer = await peerConnection.createAnswer()
await peerConnection.setLocalDescription(answer)
console.log('answer')
sendNegotiationReq(this.store.callId, {
type: 'answer',
description: answer,
})
}
} catch (error) {
console.error('Error creating offer/answer:', error)
}
})
}
private createDataChannel(peerConnection: RTCPeerConnection) {
@ -114,6 +152,15 @@ class PeerConnectionService extends CallRoot { @@ -114,6 +152,15 @@ class PeerConnectionService extends CallRoot {
}
}
}
public async sendIcecandidates() {
console.log('sendice')
await iceCandidateReq({
targetUserId: this.store.targetUserId,
candidates: [...this.icecandidates],
})
this.icecandidates = []
}
}
export const peerConnectionService = new PeerConnectionService()

4
src/modules/root/index.tsx

@ -50,9 +50,6 @@ export const Navigation: FC = () => { @@ -50,9 +50,6 @@ export const Navigation: FC = () => {
const { isConnected, status } = useNetConnect()
// const isConnected = true
// const status = 'online'
useSharedFiles()
useAppSocketListener()
useAppBadge()
@ -71,7 +68,6 @@ export const Navigation: FC = () => { @@ -71,7 +68,6 @@ export const Navigation: FC = () => {
if (!isAppReady && !_.isNull(isConnected)) {
handleAutoAuth()
}
// if (isConnected && !isAppReady) handleAutoAuth()
}, [isConnected])
const modules = {

18
src/modules/root/navigation-groups/users.group.tsx

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import React, { FC } from 'react'
import React, { FC, useEffect } from 'react'
import { RouteKey } from '@/shared'
import { SelectChatBgScreen } from '@/modules/settings'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
@ -28,10 +28,18 @@ import { @@ -28,10 +28,18 @@ import {
SendSharedFilesScreen,
} from '@/modules/chats'
import { CallScreen } from '@/modules/calls/screens/call'
import { callKeepService } from '@/modules/calls/services'
import { Platform } from 'react-native'
const Stack = createNativeStackNavigator()
export const UsersGroup: FC = () => (
export const UsersGroup: FC = () => {
useEffect(() => {
if (Platform.OS === 'android') {
callKeepService.startAnswering()
}
}, [])
return (
<Stack.Navigator
screenOptions={{ headerShown: false }}
initialRouteName={RouteKey.Tab}>
@ -138,8 +146,12 @@ export const UsersGroup: FC = () => ( @@ -138,8 +146,12 @@ export const UsersGroup: FC = () => (
<Stack.Screen name={RouteKey.Group} component={GroupScreen} />
{/* --- Executors --- */}
<Stack.Screen name={RouteKey.Executors} component={ExecutorsScreen} />
<Stack.Screen
name={RouteKey.Executors}
component={ExecutorsScreen}
/>
<Stack.Screen name={RouteKey.Call} component={CallScreen} />
</Stack.Navigator>
)
}

3
src/services/domain/account.service.ts

@ -3,6 +3,7 @@ import { SetLoadingAccount, SaveAccount } from '@/store/account' @@ -3,6 +3,7 @@ import { SetLoadingAccount, SaveAccount } from '@/store/account'
import { IUser } from '@/shared/interfaces'
import { Service } from '@/shared/abstract'
import { accountManagerInstance } from '@/managers'
import { appEvents } from '@/shared'
class AccountService extends Service {
protected prefix = 'account'
@ -14,6 +15,8 @@ class AccountService extends Service { @@ -14,6 +15,8 @@ class AccountService extends Service {
try {
const account = await this.accountManager.loadAccount()
simpleDispatch(new SaveAccount({ account }))
appEvents.emit('onAccountWasLoaded', {})
} catch (e) {
} finally {
simpleDispatch(new SetLoadingAccount({ isLoading: false }))

9
src/services/domain/auth.service.ts

@ -32,6 +32,8 @@ import { appEvents } from '@/shared' @@ -32,6 +32,8 @@ import { appEvents } from '@/shared'
import { accountManagerInstance as accManager } from '@/managers'
import { getErrorCode } from '@/shared/helpers'
import { configsService } from './configs.service'
import { Platform } from 'react-native'
import { FirebaseMessagingService } from '../system/firebas-messaging.service'
let phoneNumber: string
@ -93,7 +95,14 @@ const loadDataAfterAuth = async ( @@ -93,7 +95,14 @@ const loadDataAfterAuth = async (
) => {
await accountService.loadAccount(cacheInfo.accountV)
await permissionsService.loadPermissionsForUsers(cacheInfo.permissionsV)
if (Platform.OS === 'android') {
FirebaseMessagingService.getInstance().init()
}
if (Platform.OS === 'ios') {
VoipNotificationsService.getInstance().saveUser()
}
setAppIsReady()
}

43
src/services/system/firebas-messaging.service.ts

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
import messaging from '@react-native-firebase/messaging'
import { DeviceInfoService } from './device-info.service'
import { saveUserDeviceReq } from '@/api'
export class FirebaseMessagingService {
static instance: FirebaseMessagingService
static getInstance() {
if (!this.instance) {
this.instance = new FirebaseMessagingService()
}
return this.instance
}
public async init() {
const token = await this.getDeviceToken()
if (token) {
await this.saveToken(token)
}
}
private async getDeviceToken() {
try {
const token = await messaging().getToken()
return token
} catch (error) {
console.error('Error getting device token:', error)
}
}
private async saveToken(token: string) {
const deviceUuid = await DeviceInfoService.getDeviceUniqueId()
saveUserDeviceReq({
deviceUuid,
notificationUserId: token,
type: 'f',
isDev: __DEV__,
})
}
}

4
src/services/system/notification.service.ts

@ -11,6 +11,8 @@ import { navigate } from './navigation.service' @@ -11,6 +11,8 @@ import { navigate } from './navigation.service'
import store from '@/store'
import { selectAccount } from '@/store/account'
import { SocketIo } from './real-time.service'
import RNCallKeep from 'react-native-callkeep'
import { getBundleId } from 'react-native-device-info'
export const needRedirect = {
to: null,
@ -172,6 +174,8 @@ export const initAndSaveDevice = async () => { @@ -172,6 +174,8 @@ export const initAndSaveDevice = async () => {
const pushNotificationsDevice: any = await init()
const deviceUuid = await DeviceInfoService.getDeviceUniqueId()
const bundleId = await getBundleId()
console.log(bundleId)
if (pushNotificationsDevice) {
await saveUserDeviceReq({

6
src/services/system/real-time.service.ts

@ -4,6 +4,7 @@ import io from 'socket.io-client' @@ -4,6 +4,7 @@ import io from 'socket.io-client'
import { authService } from '../domain'
import { GlobalContainerService } from './global-container.service'
import { Alert } from 'react-native'
import RNCallKeep from 'react-native-callkeep'
const store = () => GlobalContainerService.get('store')
@ -123,15 +124,12 @@ export class SocketIo { @@ -123,15 +124,12 @@ export class SocketIo {
this._onSocketSendEvent('call/new')
this._onSocketSendEvent('call/ICEcandidate')
this._onSocketSendEvent('call/canceled')
this._onSocketSendEvent('calls/answered-by-another-device')
this._on('error/join-user', async () => {
await authService.refreshSession()
this.emit('join-user')
})
// this._on('reconnect_attempt', error => {
// console.log('SOCKET reconnect_attempt', error)
// })
}
static instance: SocketIo = null

6
src/services/system/voip-notification.service.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import { saveUserDeviceReq } from '@/api'
import VoipPushNotification from 'react-native-voip-push-notification'
import { DeviceInfoService } from './device-info.service'
export class VoipNotificationsService {
static instance: VoipNotificationsService
@ -20,6 +21,9 @@ export class VoipNotificationsService { @@ -20,6 +21,9 @@ export class VoipNotificationsService {
'register',
this.handleRegister.bind(this),
)
// VoipPushNotification.addEventListener('notification', data => {
// console.log('data')
// })
VoipPushNotification.registerVoipToken()
} catch (e) {
@ -47,7 +51,7 @@ export class VoipNotificationsService { @@ -47,7 +51,7 @@ export class VoipNotificationsService {
saveUserDeviceReq({
deviceUuid,
notificationUserId: this.voipToken,
isVoip: true,
type: 'v',
isDev: __DEV__,
})
}, 150)

10
src/shared/events/index.ts

@ -157,6 +157,8 @@ export type AppEvents = { @@ -157,6 +157,8 @@ export type AppEvents = {
'call-channel/changeVideo': {
value: boolean
}
onAccountWasLoaded: {}
callSettingUpdated: {}
}
export type SocketEvents = {
@ -244,6 +246,14 @@ export type SocketEvents = { @@ -244,6 +246,14 @@ export type SocketEvents = {
'call/canceled': {
callId: number
}
'call/negotiation': {
callId: string
type: 'answer' | 'offer'
rtcMessage: any
}
'calls/answered-by-another-device': {
deviceUuid: string
}
}
export const appEvents = new Events<AppEvents>()

Loading…
Cancel
Save