@stream-io/react-native-callingx 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/Callingx.podspec +23 -0
  2. package/LICENSE +219 -0
  3. package/README.md +392 -0
  4. package/android/bin/build/generated/source/buildConfig/debug/io/getstream/rn/callingx/BuildConfig.class +0 -0
  5. package/android/bin/build/generated/source/codegen/java/io/getstream/rn/callingx/NativeCallingxSpec.class +0 -0
  6. package/android/bin/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
  7. package/android/bin/build/generated/source/codegen/jni/CallingxSpec-generated.cpp +167 -0
  8. package/android/bin/build/generated/source/codegen/jni/CallingxSpec.h +31 -0
  9. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI-generated.cpp +196 -0
  10. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI.h +283 -0
  11. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.cpp +22 -0
  12. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.h +24 -0
  13. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.cpp +16 -0
  14. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.h +17 -0
  15. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.cpp +19 -0
  16. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.h +18 -0
  17. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.cpp +17 -0
  18. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.h +23 -0
  19. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.cpp +16 -0
  20. package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.h +20 -0
  21. package/android/bin/build/generated/source/codegen/schema.json +1 -0
  22. package/android/bin/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +33 -0
  23. package/android/bin/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  24. package/android/bin/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  25. package/android/bin/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  26. package/android/bin/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  27. package/android/bin/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  28. package/android/bin/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +3 -0
  29. package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_phone_paused_24.xml.flat +0 -0
  30. package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_round_call_24.xml.flat +0 -0
  31. package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_user.xml.flat +0 -0
  32. package/android/bin/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +4 -0
  33. package/android/bin/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  34. package/android/bin/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
  35. package/android/bin/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  36. package/android/bin/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  37. package/android/bin/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
  38. package/android/bin/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +5 -0
  39. package/android/bin/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +60 -0
  40. package/android/bin/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +33 -0
  41. package/android/bin/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  42. package/android/bin/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  43. package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_phone_paused_24.xml +11 -0
  44. package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_round_call_24.xml +11 -0
  45. package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_user.xml +27 -0
  46. package/android/bin/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
  47. package/android/bin/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  48. package/android/bin/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +4 -0
  49. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  50. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  51. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  52. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  53. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  54. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  55. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  56. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  57. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  58. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  59. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  60. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  61. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  62. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  63. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  64. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  65. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  66. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  67. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  68. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  69. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  70. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  71. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  72. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  73. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  74. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  75. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  76. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
  77. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  78. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  79. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  80. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  81. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  82. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  83. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  84. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
  85. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +0 -0
  86. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +0 -0
  87. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +0 -0
  88. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
  89. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +0 -0
  90. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +0 -0
  91. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  92. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  93. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  94. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  95. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
  96. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  97. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
  98. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  99. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  100. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  101. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  102. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  103. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  104. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  105. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  106. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  107. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  108. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  109. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  110. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  111. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  112. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  113. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  114. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  115. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  116. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  117. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  118. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  119. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  120. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  121. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  122. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  123. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  124. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  125. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  126. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  127. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  128. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  129. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  130. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  131. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  132. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  133. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  134. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  135. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  136. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  137. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  138. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  139. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  140. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  141. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  142. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  143. package/android/bin/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  144. package/android/bin/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  145. package/android/bin/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  146. package/android/bin/build/outputs/logs/manifest-merger-debug-report.txt +70 -0
  147. package/android/bin/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  148. package/android/bin/build/tmp/kotlin-classes/debug/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
  149. package/android/bin/build.gradle +81 -0
  150. package/android/bin/gradle.properties +5 -0
  151. package/android/bin/local.properties +8 -0
  152. package/android/bin/src/main/AndroidManifest.xml +30 -0
  153. package/android/bin/src/main/java/io/getstream/rn/callingx/CallService.kt +396 -0
  154. package/android/bin/src/main/java/io/getstream/rn/callingx/CallingxModule.kt +639 -0
  155. package/android/bin/src/main/java/io/getstream/rn/callingx/CallingxPackage.kt +16 -0
  156. package/android/bin/src/main/java/io/getstream/rn/callingx/HeadlessTaskManager.kt +164 -0
  157. package/android/bin/src/main/java/io/getstream/rn/callingx/ResourceUtils.kt +60 -0
  158. package/android/bin/src/main/java/io/getstream/rn/callingx/Utils.kt +23 -0
  159. package/android/bin/src/main/java/io/getstream/rn/callingx/model/Call.kt +57 -0
  160. package/android/bin/src/main/java/io/getstream/rn/callingx/model/CallAction.kt +36 -0
  161. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +215 -0
  162. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt +113 -0
  163. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +105 -0
  164. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +42 -0
  165. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +56 -0
  166. package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationsConfig.kt +116 -0
  167. package/android/bin/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +163 -0
  168. package/android/bin/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +134 -0
  169. package/android/bin/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +438 -0
  170. package/android/bin/src/main/res/drawable/ic_phone_paused_24.xml +11 -0
  171. package/android/bin/src/main/res/drawable/ic_round_call_24.xml +11 -0
  172. package/android/bin/src/main/res/drawable/ic_user.xml +27 -0
  173. package/android/build.gradle +81 -0
  174. package/android/gradle.properties +5 -0
  175. package/android/src/main/AndroidManifest.xml +30 -0
  176. package/android/src/main/java/io/getstream/rn/callingx/CallService.kt +396 -0
  177. package/android/src/main/java/io/getstream/rn/callingx/CallingxModule.kt +639 -0
  178. package/android/src/main/java/io/getstream/rn/callingx/CallingxPackage.kt +16 -0
  179. package/android/src/main/java/io/getstream/rn/callingx/HeadlessTaskManager.kt +164 -0
  180. package/android/src/main/java/io/getstream/rn/callingx/ResourceUtils.kt +60 -0
  181. package/android/src/main/java/io/getstream/rn/callingx/Utils.kt +23 -0
  182. package/android/src/main/java/io/getstream/rn/callingx/model/Call.kt +57 -0
  183. package/android/src/main/java/io/getstream/rn/callingx/model/CallAction.kt +36 -0
  184. package/android/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +215 -0
  185. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt +113 -0
  186. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +105 -0
  187. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +42 -0
  188. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +56 -0
  189. package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationsConfig.kt +116 -0
  190. package/android/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +163 -0
  191. package/android/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +134 -0
  192. package/android/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +438 -0
  193. package/android/src/main/res/drawable/ic_phone_paused_24.xml +11 -0
  194. package/android/src/main/res/drawable/ic_round_call_24.xml +11 -0
  195. package/android/src/main/res/drawable/ic_user.xml +27 -0
  196. package/dist/module/CallingxModule.js +191 -0
  197. package/dist/module/CallingxModule.js.map +1 -0
  198. package/dist/module/EventManager.js +40 -0
  199. package/dist/module/EventManager.js.map +1 -0
  200. package/dist/module/index.js +5 -0
  201. package/dist/module/index.js.map +1 -0
  202. package/dist/module/package.json +1 -0
  203. package/dist/module/spec/NativeCallingx.js +8 -0
  204. package/dist/module/spec/NativeCallingx.js.map +1 -0
  205. package/dist/module/types.js +4 -0
  206. package/dist/module/types.js.map +1 -0
  207. package/dist/module/utils/constants.js +48 -0
  208. package/dist/module/utils/constants.js.map +1 -0
  209. package/dist/module/utils/headlessTask.js +37 -0
  210. package/dist/module/utils/headlessTask.js.map +1 -0
  211. package/dist/module/utils/permissions.js +86 -0
  212. package/dist/module/utils/permissions.js.map +1 -0
  213. package/dist/module/utils/types.js +2 -0
  214. package/dist/module/utils/types.js.map +1 -0
  215. package/dist/module/utils/utils.js +6 -0
  216. package/dist/module/utils/utils.js.map +1 -0
  217. package/dist/typescript/package.json +1 -0
  218. package/dist/typescript/src/CallingxModule.d.ts +44 -0
  219. package/dist/typescript/src/CallingxModule.d.ts.map +1 -0
  220. package/dist/typescript/src/EventManager.d.ts +11 -0
  221. package/dist/typescript/src/EventManager.d.ts.map +1 -0
  222. package/dist/typescript/src/index.d.ts +3 -0
  223. package/dist/typescript/src/index.d.ts.map +1 -0
  224. package/dist/typescript/src/spec/NativeCallingx.d.ts +132 -0
  225. package/dist/typescript/src/spec/NativeCallingx.d.ts.map +1 -0
  226. package/dist/typescript/src/types.d.ts +249 -0
  227. package/dist/typescript/src/types.d.ts.map +1 -0
  228. package/dist/typescript/src/utils/constants.d.ts +8 -0
  229. package/dist/typescript/src/utils/constants.d.ts.map +1 -0
  230. package/dist/typescript/src/utils/headlessTask.d.ts +8 -0
  231. package/dist/typescript/src/utils/headlessTask.d.ts.map +1 -0
  232. package/dist/typescript/src/utils/permissions.d.ts +8 -0
  233. package/dist/typescript/src/utils/permissions.d.ts.map +1 -0
  234. package/dist/typescript/src/utils/types.d.ts +4 -0
  235. package/dist/typescript/src/utils/types.d.ts.map +1 -0
  236. package/dist/typescript/src/utils/utils.d.ts +2 -0
  237. package/dist/typescript/src/utils/utils.d.ts.map +1 -0
  238. package/ios/AudioSessionManager.swift +46 -0
  239. package/ios/Callingx.mm +280 -0
  240. package/ios/CallingxImpl.swift +744 -0
  241. package/ios/CallingxPublic.h +79 -0
  242. package/ios/Settings.swift +108 -0
  243. package/ios/UUIDStorage.swift +124 -0
  244. package/ios/VoipNotificationsManager.swift +180 -0
  245. package/package.json +112 -0
  246. package/react-native.config.js +8 -0
  247. package/src/CallingxModule.ts +321 -0
  248. package/src/EventManager.ts +61 -0
  249. package/src/index.ts +2 -0
  250. package/src/spec/NativeCallingx.ts +176 -0
  251. package/src/types.ts +323 -0
  252. package/src/utils/constants.ts +55 -0
  253. package/src/utils/headlessTask.ts +52 -0
  254. package/src/utils/permissions.ts +111 -0
  255. package/src/utils/types.ts +5 -0
  256. package/src/utils/utils.ts +6 -0
@@ -0,0 +1,164 @@
1
+ package io.getstream.rn.callingx
2
+
3
+ import android.content.Context
4
+ import android.os.Bundle
5
+ import android.util.Log
6
+ import com.facebook.react.ReactApplication
7
+ import com.facebook.react.ReactHost
8
+ import com.facebook.react.ReactInstanceEventListener
9
+ import com.facebook.react.ReactNativeHost
10
+ import com.facebook.react.bridge.Arguments
11
+ import com.facebook.react.bridge.ReactContext
12
+ import com.facebook.react.bridge.UiThreadUtil
13
+ import com.facebook.react.internal.featureflags.ReactNativeNewArchitectureFeatureFlags
14
+ import com.facebook.react.jstasks.HeadlessJsTaskConfig
15
+ import com.facebook.react.jstasks.HeadlessJsTaskContext
16
+ import com.facebook.react.jstasks.HeadlessJsTaskEventListener
17
+
18
+ class HeadlessTaskManager(private val context: Context) : HeadlessJsTaskEventListener {
19
+
20
+ private var activeTaskId: Int? = null
21
+
22
+ companion object {
23
+ private const val TAG = "[Callingx] HeadlessTaskManager"
24
+ }
25
+
26
+ public fun startHeadlessTask(taskName: String, data: Bundle, timeout: Long) {
27
+ debugLog(TAG, "[headless] startHeadlessTask: Starting headless task: $taskName, $data, $timeout")
28
+ if (activeTaskId != null) {
29
+ Log.w(TAG, "[headless] startHeadlessTask: Task already starting or active, ignoring new task request")
30
+ return
31
+ }
32
+
33
+ if (UiThreadUtil.isOnUiThread()) {
34
+ startTask(HeadlessJsTaskConfig(taskName, Arguments.fromBundle(data), timeout, true))
35
+ } else {
36
+ UiThreadUtil.runOnUiThread(
37
+ Runnable {
38
+ startTask(HeadlessJsTaskConfig(taskName, Arguments.fromBundle(data), timeout, true))
39
+ }
40
+ )
41
+ }
42
+ }
43
+
44
+ public fun stopHeadlessTask() {
45
+ debugLog(TAG, "[headless] stopHeadlessTask: Stopping headless task")
46
+ activeTaskId?.let { taskId ->
47
+ if (UiThreadUtil.isOnUiThread()) {
48
+ stopTask(taskId)
49
+ } else {
50
+ UiThreadUtil.runOnUiThread(Runnable { stopTask(taskId) })
51
+ }
52
+ }
53
+ }
54
+
55
+ protected fun startTask(taskConfig: HeadlessJsTaskConfig) {
56
+ UiThreadUtil.assertOnUiThread()
57
+
58
+ val context = reactContext
59
+ if (context == null) {
60
+ createReactContextAndScheduleTask(taskConfig)
61
+ } else {
62
+ invokeStartTask(context, taskConfig)
63
+ }
64
+ }
65
+
66
+ private fun invokeStartTask(reactContext: ReactContext, taskConfig: HeadlessJsTaskConfig) {
67
+ debugLog(TAG, "[headless] invokeStartTask: Invoking start task")
68
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactContext)
69
+ headlessJsTaskContext.addTaskEventListener(this)
70
+
71
+ UiThreadUtil.runOnUiThread {
72
+ val taskId = headlessJsTaskContext.startTask(taskConfig)
73
+ activeTaskId = taskId
74
+ }
75
+ }
76
+
77
+ private fun stopTask(taskId: Int) {
78
+ reactContext?.let { context ->
79
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(context)
80
+ if (headlessJsTaskContext.isTaskRunning(taskId)) {
81
+ headlessJsTaskContext.finishTask(taskId)
82
+ debugLog(TAG, "Stopped task: $taskId")
83
+ }
84
+ }
85
+ }
86
+
87
+ fun release() {
88
+ stopHeadlessTask()
89
+
90
+ reactContext?.let { context ->
91
+ val headlessJsTaskContext = HeadlessJsTaskContext.getInstance(context)
92
+ headlessJsTaskContext.removeTaskEventListener(this)
93
+ }
94
+ }
95
+
96
+ override fun onHeadlessJsTaskStart(taskId: Int) {
97
+ debugLog(TAG, "[headless] onHeadlessJsTaskStart: Task started: $taskId")
98
+ }
99
+
100
+ override fun onHeadlessJsTaskFinish(taskId: Int) {
101
+ debugLog(TAG, "[headless] onHeadlessJsTaskFinish: Task finished: $taskId")
102
+ activeTaskId = null
103
+ }
104
+
105
+ /**
106
+ * Get the [ReactNativeHost] used by this app. By default, assumes [getApplication] is an instance
107
+ * of [ReactApplication] and calls [ReactApplication.reactNativeHost].
108
+ *
109
+ * Override this method if your application class does not implement `ReactApplication` or you
110
+ * simply have a different mechanism for storing a `ReactNativeHost`, e.g. as a static field
111
+ * somewhere.
112
+ */
113
+ @Suppress("DEPRECATION")
114
+ protected open val reactNativeHost: ReactNativeHost
115
+ get() = (context.applicationContext as ReactApplication).reactNativeHost
116
+
117
+ /**
118
+ * Get the [ReactHost] used by this app. By default, assumes [getApplication] is an instance of
119
+ * [ReactApplication] and calls [ReactApplication.reactHost]. This method assumes it is called in
120
+ * new architecture and returns null if not.
121
+ */
122
+ protected open val reactHost: ReactHost?
123
+ get() = (context.applicationContext as ReactApplication).reactHost
124
+
125
+ protected val reactContext: ReactContext?
126
+ get() {
127
+ if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
128
+ val reactHost =
129
+ checkNotNull(reactHost) { "ReactHost is not initialized in New Architecture" }
130
+ return reactHost.currentReactContext
131
+ } else {
132
+ val reactInstanceManager = reactNativeHost.reactInstanceManager
133
+ return reactInstanceManager.currentReactContext
134
+ }
135
+ }
136
+
137
+ private fun createReactContextAndScheduleTask(taskConfig: HeadlessJsTaskConfig) {
138
+ if (ReactNativeNewArchitectureFeatureFlags.enableBridgelessArchitecture()) {
139
+ val reactHost = checkNotNull(reactHost)
140
+ reactHost.addReactInstanceEventListener(
141
+ object : ReactInstanceEventListener {
142
+ override fun onReactContextInitialized(context: ReactContext) {
143
+ debugLog(TAG, "createReactContextAndScheduleTask: React context initialized")
144
+ invokeStartTask(context, taskConfig)
145
+ reactHost.removeReactInstanceEventListener(this)
146
+ }
147
+ }
148
+ )
149
+ reactHost.start()
150
+ } else {
151
+ val reactInstanceManager = reactNativeHost.reactInstanceManager
152
+ reactInstanceManager.addReactInstanceEventListener(
153
+ object : ReactInstanceEventListener {
154
+ override fun onReactContextInitialized(context: ReactContext) {
155
+ debugLog(TAG, "createReactContextAndScheduleTask: React context initialized")
156
+ invokeStartTask(context, taskConfig)
157
+ reactInstanceManager.removeReactInstanceEventListener(this)
158
+ }
159
+ }
160
+ )
161
+ reactInstanceManager.createReactContextInBackground()
162
+ }
163
+ }
164
+ }
@@ -0,0 +1,60 @@
1
+ package io.getstream.rn.callingx
2
+
3
+ import android.content.Context
4
+ import android.media.RingtoneManager
5
+ import android.net.Uri
6
+ import androidx.core.net.toUri
7
+
8
+
9
+ object ResourceUtils {
10
+ private const val TAG = "[Callingx] ResourceUtils"
11
+
12
+ private val resourceIdCache = mutableMapOf<String, Int>()
13
+
14
+ private fun getResourceIdByName(context: Context, name: String?, type: String): Int {
15
+ if (name.isNullOrEmpty()) {
16
+ return 0
17
+ }
18
+
19
+ val normalizedName = name.lowercase().replace("-", "_")
20
+ val key = "${normalizedName}_$type"
21
+
22
+ synchronized(resourceIdCache) {
23
+ resourceIdCache[key]?.let {
24
+ return it
25
+ }
26
+
27
+ val packageName = context.packageName
28
+
29
+ val id = context.resources.getIdentifier(normalizedName, type, packageName)
30
+ resourceIdCache[key] = id
31
+ return id
32
+ }
33
+ }
34
+
35
+ fun getSoundUri(context: Context, sound: String?): Uri? {
36
+ debugLog(TAG, "getSoundUri: Getting sound URI for: $sound")
37
+ return when {
38
+ sound == null -> null
39
+ sound.contains("://") -> sound.toUri()
40
+ sound.equals("default", ignoreCase = true) -> {
41
+ RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
42
+ }
43
+
44
+ else -> {
45
+ // The API user is attempting to set a sound by file name, verify it exists
46
+ var soundResourceId = getResourceIdByName(context, sound, "raw")
47
+ if (soundResourceId == 0 && sound.contains(".")) {
48
+ soundResourceId = getResourceIdByName(context, sound.substringBeforeLast('.'), "raw")
49
+ }
50
+ if (soundResourceId == 0) {
51
+ null
52
+ } else {
53
+ // Use the actual sound name vs the resource ID, to obtain a stable URI, Issue #341
54
+ val soundName = context.resources.getResourceEntryName(soundResourceId)
55
+ "android.resource://${context.packageName}/raw/$soundName".toUri()
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,23 @@
1
+ package io.getstream.rn.callingx
2
+
3
+ import android.telecom.DisconnectCause
4
+ import android.util.Log
5
+
6
+ fun getDisconnectCauseString(cause: DisconnectCause): String {
7
+ return when (cause.code) {
8
+ DisconnectCause.LOCAL -> "local"
9
+ DisconnectCause.REMOTE -> "remote"
10
+ DisconnectCause.REJECTED -> "rejected"
11
+ DisconnectCause.BUSY -> "busy"
12
+ DisconnectCause.ANSWERED_ELSEWHERE -> "answeredElsewhere"
13
+ DisconnectCause.MISSED -> "missed"
14
+ DisconnectCause.ERROR -> "error"
15
+ else -> cause.toString()
16
+ }
17
+ }
18
+
19
+ fun debugLog(tag: String, message: String) {
20
+ if (BuildConfig.DEBUG) {
21
+ Log.d(tag, message)
22
+ }
23
+ }
@@ -0,0 +1,57 @@
1
+ package io.getstream.rn.callingx.model
2
+
3
+ import android.os.Bundle
4
+ import android.telecom.DisconnectCause
5
+ import androidx.core.telecom.CallAttributesCompat
6
+ import androidx.core.telecom.CallEndpointCompat
7
+ import kotlinx.coroutines.channels.Channel
8
+
9
+ /**
10
+ * Custom representation of a call state.
11
+ */
12
+ sealed class Call {
13
+
14
+ /**
15
+ * There is no current or past calls in the stack
16
+ */
17
+ object None : Call()
18
+
19
+ /**
20
+ * Represents a registered call with the telecom stack with the values provided by the
21
+ * Telecom SDK
22
+ */
23
+ data class Registered(
24
+ val id: String,
25
+ val callAttributes: CallAttributesCompat,
26
+ val displayOptions: Bundle?,
27
+ val isActive: Boolean,
28
+ val isOnHold: Boolean,
29
+ val isMuted: Boolean,
30
+ val errorCode: Int?,
31
+ val currentCallEndpoint: CallEndpointCompat?,
32
+ val availableCallEndpoints: List<CallEndpointCompat>,
33
+ internal val actionSource: Channel<CallAction>,
34
+ ) : Call() {
35
+
36
+ /**
37
+ * @return true if it's an incoming registered call, false otherwise
38
+ */
39
+ fun isIncoming() = callAttributes.direction == CallAttributesCompat.DIRECTION_INCOMING
40
+
41
+ /**
42
+ * Sends an action to the call session. It will be processed if it's still registered.
43
+ *
44
+ * @return true if the action was sent, false otherwise
45
+ */
46
+ fun processAction(action: CallAction) = actionSource.trySend(action).isSuccess
47
+ }
48
+
49
+ /**
50
+ * Represent a previously registered call that was disconnected
51
+ */
52
+ data class Unregistered(
53
+ val id: String,
54
+ val callAttributes: CallAttributesCompat,
55
+ val disconnectCause: DisconnectCause,
56
+ ) : Call()
57
+ }
@@ -0,0 +1,36 @@
1
+ package io.getstream.rn.callingx.model
2
+
3
+ import android.os.ParcelUuid
4
+ import android.os.Parcelable
5
+ import android.telecom.DisconnectCause
6
+ import kotlinx.parcelize.Parcelize
7
+
8
+ /**
9
+ * Simple interface to represent related call actions to communicate with the registered call scope
10
+ * in the [TelecomCallRepository.registerCall]
11
+ *
12
+ * Note: we are using [Parcelize] to make the actions parcelable so they can be directly used in the
13
+ * call notification.
14
+ */
15
+ sealed interface CallAction : Parcelable {
16
+ @Parcelize
17
+ data class Answer(val isAudioCall: Boolean) : CallAction
18
+
19
+ @Parcelize
20
+ data class Disconnect(val cause: DisconnectCause) : CallAction
21
+
22
+ @Parcelize
23
+ object Hold : CallAction
24
+
25
+ @Parcelize
26
+ object Activate : CallAction
27
+
28
+ @Parcelize
29
+ data class ToggleMute(val isMute: Boolean) : CallAction
30
+
31
+ @Parcelize
32
+ data class SwitchAudioEndpoint(val endpointId: ParcelUuid) : CallAction
33
+
34
+ @Parcelize
35
+ data class TransferCall(val endpointId: ParcelUuid) : CallAction
36
+ }
@@ -0,0 +1,215 @@
1
+ package io.getstream.rn.callingx.notifications
2
+
3
+ import android.app.Notification
4
+ import android.content.Context
5
+ import android.media.Ringtone
6
+ import android.media.RingtoneManager
7
+ import android.os.Build
8
+ import android.telecom.DisconnectCause
9
+ import android.util.Log
10
+ import androidx.core.app.NotificationCompat
11
+ import androidx.core.app.NotificationManagerCompat
12
+ import androidx.core.app.Person
13
+ import androidx.core.graphics.drawable.IconCompat
14
+ import io.getstream.rn.callingx.CallService
15
+ import io.getstream.rn.callingx.CallingxModule
16
+ import io.getstream.rn.callingx.R
17
+ import io.getstream.rn.callingx.ResourceUtils
18
+ import io.getstream.rn.callingx.debugLog
19
+ import io.getstream.rn.callingx.getDisconnectCauseString
20
+ import io.getstream.rn.callingx.model.Call
21
+ import io.getstream.rn.callingx.repo.CallRepository
22
+
23
+ /**
24
+ * Handles call status changes and updates the notification accordingly. For more guidance around
25
+ * notifications check https://developer.android.com/develop/ui/views/notifications
26
+ *
27
+ * @see updateCallNotification
28
+ */
29
+ class CallNotificationManager(
30
+ private val context: Context,
31
+ private val notificationManager: NotificationManagerCompat =
32
+ NotificationManagerCompat.from(context)
33
+ ) {
34
+
35
+ internal companion object {
36
+ private const val TAG = "[Callingx] CallNotificationManager"
37
+
38
+ const val NOTIFICATION_ID = 200
39
+ }
40
+
41
+ private var notificationsConfig = NotificationsConfig.loadNotificationsConfig(context)
42
+
43
+ private var ringtone: Ringtone? = null
44
+
45
+ private var hasBecameActive = false
46
+
47
+ fun createNotification(call: Call.Registered): Notification {
48
+ debugLog(
49
+ TAG,
50
+ "[notifications] createNotification: Creating notification for call ID: ${call.id}"
51
+ )
52
+
53
+ val contentIntent =
54
+ NotificationIntentFactory.getLaunchActivityIntent(
55
+ context,
56
+ CallingxModule.CALL_ANSWERED_ACTION,
57
+ call.id
58
+ )
59
+ val callStyle = createCallStyle(call)
60
+ val channelId = getChannelId(call)
61
+ debugLog(TAG, "[notifications] createNotification: Channel ID: $channelId")
62
+
63
+ val builder =
64
+ NotificationCompat.Builder(context, channelId)
65
+ .setContentIntent(contentIntent)
66
+ .setFullScreenIntent(contentIntent, true)
67
+ .setStyle(callStyle)
68
+ .setSmallIcon(R.drawable.ic_round_call_24)
69
+ .setCategory(NotificationCompat.CATEGORY_CALL)
70
+ .setPriority(NotificationCompat.PRIORITY_MAX)
71
+ .setOngoing(true)
72
+
73
+ if (!hasBecameActive && call.isActive) {
74
+ debugLog(TAG, "[notifications] createNotification: Setting when to current time")
75
+ builder.setWhen(System.currentTimeMillis())
76
+ builder.setUsesChronometer(true)
77
+ builder.setShowWhen(true)
78
+ hasBecameActive = true
79
+ }
80
+
81
+ call.displayOptions?.let {
82
+ if (it.containsKey(CallService.EXTRA_DISPLAY_SUBTITLE)) {
83
+ builder.setContentText(it.getString(CallService.EXTRA_DISPLAY_SUBTITLE))
84
+ }
85
+ }
86
+
87
+ return builder.build()
88
+ }
89
+
90
+ fun updateCallNotification(call: Call) {
91
+ when (call) {
92
+ Call.None, is Call.Unregistered -> {
93
+ debugLog(
94
+ TAG,
95
+ "[notifications] updateCallNotification: Dismissing notification (call is None or Unregistered)"
96
+ )
97
+ notificationManager.cancel(NOTIFICATION_ID)
98
+ }
99
+ is Call.Registered -> {
100
+ val notification = createNotification(call)
101
+ notificationManager.notify(NOTIFICATION_ID, notification)
102
+ debugLog(
103
+ TAG,
104
+ "[notifications] updateCallNotification: Notification posted successfully"
105
+ )
106
+ }
107
+ }
108
+ }
109
+
110
+ fun cancelNotifications() {
111
+ notificationManager.cancel(NOTIFICATION_ID)
112
+ hasBecameActive = false
113
+ }
114
+
115
+ fun startRingtone() {
116
+ if (ringtone?.isPlaying == true) {
117
+ debugLog(TAG, "[notifications] startRingtone: Ringtone already playing")
118
+ return
119
+ }
120
+
121
+ try {
122
+ val soundUri =
123
+ ResourceUtils.getSoundUri(context, notificationsConfig.incomingChannel.sound)
124
+ ?: RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
125
+
126
+ ringtone = RingtoneManager.getRingtone(context, soundUri)
127
+ } catch (e: Exception) {
128
+ Log.e(TAG, "[notifications] startRingtone: Error starting ringtone: ${e.message}")
129
+ return
130
+ }
131
+
132
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
133
+ ringtone?.isLooping = true
134
+ }
135
+
136
+ ringtone?.play()
137
+ debugLog(TAG, "[notifications] startRingtone: Ringtone started")
138
+ }
139
+
140
+ fun stopRingtone() {
141
+ if (ringtone?.isPlaying == true) {
142
+ ringtone?.stop()
143
+ debugLog(TAG, "[notifications] stopRingtone: Ringtone stopped")
144
+ }
145
+ ringtone = null
146
+ }
147
+
148
+ private fun getChannelId(call: Call.Registered): String {
149
+ return if (call.isIncoming() && !call.isActive) {
150
+ notificationsConfig.incomingChannel.id
151
+ } else {
152
+ notificationsConfig.ongoingChannel.id
153
+ }
154
+ }
155
+
156
+ private fun createCallStyle(call: Call.Registered): NotificationCompat.CallStyle {
157
+ val caller = createPerson(call)
158
+
159
+ if (call.isIncoming() && !call.isActive) {
160
+ return NotificationCompat.CallStyle.forIncomingCall(
161
+ caller,
162
+ NotificationIntentFactory.getPendingBroadcastIntent(
163
+ context,
164
+ CallingxModule.CALL_END_ACTION,
165
+ call.id
166
+ ) {
167
+ putExtra(
168
+ CallingxModule.EXTRA_DISCONNECT_CAUSE,
169
+ getDisconnectCauseString(DisconnectCause(DisconnectCause.REJECTED))
170
+ )
171
+ putExtra(
172
+ CallingxModule.EXTRA_SOURCE,
173
+ CallRepository.EventSource.SYS.name.lowercase()
174
+ )
175
+ },
176
+ NotificationIntentFactory.getPendingNotificationIntent(
177
+ context,
178
+ CallingxModule.CALL_ANSWERED_ACTION,
179
+ call.id,
180
+ CallRepository.EventSource.SYS.name.lowercase()
181
+ )
182
+ )
183
+ }
184
+
185
+ return NotificationCompat.CallStyle.forOngoingCall(
186
+ caller,
187
+ NotificationIntentFactory.getPendingBroadcastIntent(
188
+ context,
189
+ CallingxModule.CALL_END_ACTION,
190
+ call.id
191
+ ) {
192
+ putExtra(
193
+ CallingxModule.EXTRA_DISCONNECT_CAUSE,
194
+ getDisconnectCauseString(DisconnectCause(DisconnectCause.LOCAL))
195
+ )
196
+ putExtra(
197
+ CallingxModule.EXTRA_SOURCE,
198
+ CallRepository.EventSource.SYS.name.lowercase()
199
+ )
200
+ },
201
+ )
202
+ }
203
+
204
+ private fun createPerson(call: Call.Registered): Person {
205
+ val displayCallerName = call.displayOptions?.getString(CallService.EXTRA_DISPLAY_TITLE)
206
+ val address = call.callAttributes.address.toString()
207
+
208
+ return Person.Builder()
209
+ .setName(displayCallerName ?: call.callAttributes.displayName)
210
+ .setUri(address)
211
+ .setIcon(IconCompat.createWithResource(context, R.drawable.ic_user))
212
+ .setImportant(true)
213
+ .build()
214
+ }
215
+ }
@@ -0,0 +1,113 @@
1
+ package io.getstream.rn.callingx.notifications
2
+
3
+ import android.Manifest
4
+ import android.content.Context
5
+ import android.os.Build
6
+ import androidx.core.app.NotificationChannelCompat
7
+ import androidx.core.app.NotificationManagerCompat
8
+ import androidx.core.content.PermissionChecker
9
+ import io.getstream.rn.callingx.debugLog
10
+
11
+ class NotificationChannelsManager(
12
+ private val context: Context,
13
+ private val notificationManager: NotificationManagerCompat =
14
+ NotificationManagerCompat.from(context)
15
+ ) {
16
+
17
+ private var notificationsConfig: NotificationsConfig.Channels? = null
18
+
19
+ companion object {
20
+ private const val TAG = "[Callingx] NotificationChannelsManager"
21
+ }
22
+
23
+ data class NotificationStatus(
24
+ val canPost: Boolean,
25
+ val hasPermissions: Boolean,
26
+ val areNotificationsEnabled: Boolean,
27
+ val isIncomingChannelEnabled: Boolean,
28
+ val isOngoingChannelEnabled: Boolean,
29
+ )
30
+
31
+ fun setNotificationsConfig(notificationsConfig: NotificationsConfig.Channels) {
32
+ this.notificationsConfig = notificationsConfig
33
+ }
34
+
35
+ fun createNotificationChannels() {
36
+ notificationsConfig?.let {
37
+ val incomingChannel = createNotificationChannel(it.incomingChannel)
38
+ val ongoingChannel = createNotificationChannel(it.ongoingChannel)
39
+
40
+ notificationManager.createNotificationChannelsCompat(
41
+ listOf(
42
+ incomingChannel,
43
+ ongoingChannel,
44
+ ),
45
+ )
46
+ debugLog(TAG, "createNotificationChannels: Notification channels registered")
47
+ }
48
+ }
49
+
50
+ fun getNotificationStatus(): NotificationStatus {
51
+ val areNotificationsEnabled = areNotificationsEnabled()
52
+ val hasPermissions = hasNotificationPermissions()
53
+ val isIncomingChannelEnabled = isChannelEnabled(notificationsConfig?.incomingChannel?.id)
54
+ val isOngoingChannelEnabled = isChannelEnabled(notificationsConfig?.ongoingChannel?.id)
55
+
56
+ val canPost =
57
+ areNotificationsEnabled &&
58
+ hasPermissions &&
59
+ isIncomingChannelEnabled &&
60
+ isOngoingChannelEnabled
61
+
62
+ return NotificationStatus(
63
+ canPost,
64
+ hasPermissions,
65
+ areNotificationsEnabled,
66
+ isIncomingChannelEnabled,
67
+ isOngoingChannelEnabled
68
+ )
69
+ }
70
+
71
+ private fun createNotificationChannel(
72
+ config: NotificationsConfig.ChannelParams
73
+ ): NotificationChannelCompat {
74
+ return NotificationChannelCompat.Builder(config.id, config.importance)
75
+ .apply {
76
+ setName(config.name)
77
+ setVibrationEnabled(config.vibration)
78
+ setSound(null, null)
79
+ }
80
+ .build()
81
+ }
82
+
83
+ private fun areNotificationsEnabled(): Boolean {
84
+ return notificationManager.areNotificationsEnabled()
85
+ }
86
+
87
+ private fun hasNotificationPermissions(): Boolean {
88
+ // POST_NOTIFICATIONS permission is only required on Android 13+
89
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
90
+ return true
91
+ }
92
+
93
+ val permission =
94
+ PermissionChecker.checkSelfPermission(
95
+ context,
96
+ Manifest.permission.POST_NOTIFICATIONS,
97
+ )
98
+ return permission == PermissionChecker.PERMISSION_GRANTED
99
+ }
100
+
101
+ private fun isChannelEnabled(channelId: String?): Boolean {
102
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
103
+ return true
104
+ }
105
+
106
+ if (channelId == null) {
107
+ return false
108
+ }
109
+
110
+ val channel = notificationManager.getNotificationChannel(channelId)
111
+ return channel != null && channel.importance != NotificationManagerCompat.IMPORTANCE_NONE
112
+ }
113
+ }