@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.
- package/Callingx.podspec +23 -0
- package/LICENSE +219 -0
- package/README.md +392 -0
- package/android/bin/build/generated/source/buildConfig/debug/io/getstream/rn/callingx/BuildConfig.class +0 -0
- package/android/bin/build/generated/source/codegen/java/io/getstream/rn/callingx/NativeCallingxSpec.class +0 -0
- package/android/bin/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
- package/android/bin/build/generated/source/codegen/jni/CallingxSpec-generated.cpp +167 -0
- package/android/bin/build/generated/source/codegen/jni/CallingxSpec.h +31 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI-generated.cpp +196 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/CallingxSpecJSI.h +283 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.cpp +22 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ComponentDescriptors.h +24 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.cpp +16 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/EventEmitters.h +17 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.cpp +19 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/Props.h +18 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.cpp +17 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/ShadowNodes.h +23 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.cpp +16 -0
- package/android/bin/build/generated/source/codegen/jni/react/renderer/components/CallingxSpec/States.h +20 -0
- package/android/bin/build/generated/source/codegen/schema.json +1 -0
- package/android/bin/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +33 -0
- package/android/bin/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
- package/android/bin/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
- package/android/bin/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
- package/android/bin/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/bin/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/bin/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +3 -0
- package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_phone_paused_24.xml.flat +0 -0
- package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_round_call_24.xml.flat +0 -0
- package/android/bin/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/drawable_ic_user.xml.flat +0 -0
- package/android/bin/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +4 -0
- package/android/bin/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
- package/android/bin/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
- package/android/bin/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
- package/android/bin/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
- package/android/bin/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
- package/android/bin/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +5 -0
- package/android/bin/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +60 -0
- package/android/bin/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +33 -0
- package/android/bin/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
- package/android/bin/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
- package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_phone_paused_24.xml +11 -0
- package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_round_call_24.xml +11 -0
- package/android/bin/build/intermediates/packaged_res/debug/packageDebugResources/drawable/ic_user.xml +27 -0
- package/android/bin/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
- package/android/bin/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/bin/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +4 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/bin/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/bin/build/outputs/logs/manifest-merger-debug-report.txt +70 -0
- package/android/bin/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/bin/build/tmp/kotlin-classes/debug/META-INF/stream-io_react-native-callingx_debug.kotlin_module +0 -0
- package/android/bin/build.gradle +81 -0
- package/android/bin/gradle.properties +5 -0
- package/android/bin/local.properties +8 -0
- package/android/bin/src/main/AndroidManifest.xml +30 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/CallService.kt +396 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/CallingxModule.kt +639 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/CallingxPackage.kt +16 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/HeadlessTaskManager.kt +164 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/ResourceUtils.kt +60 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/Utils.kt +23 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/model/Call.kt +57 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/model/CallAction.kt +36 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +215 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt +113 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +105 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +42 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +56 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/notifications/NotificationsConfig.kt +116 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +163 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +134 -0
- package/android/bin/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +438 -0
- package/android/bin/src/main/res/drawable/ic_phone_paused_24.xml +11 -0
- package/android/bin/src/main/res/drawable/ic_round_call_24.xml +11 -0
- package/android/bin/src/main/res/drawable/ic_user.xml +27 -0
- package/android/build.gradle +81 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +30 -0
- package/android/src/main/java/io/getstream/rn/callingx/CallService.kt +396 -0
- package/android/src/main/java/io/getstream/rn/callingx/CallingxModule.kt +639 -0
- package/android/src/main/java/io/getstream/rn/callingx/CallingxPackage.kt +16 -0
- package/android/src/main/java/io/getstream/rn/callingx/HeadlessTaskManager.kt +164 -0
- package/android/src/main/java/io/getstream/rn/callingx/ResourceUtils.kt +60 -0
- package/android/src/main/java/io/getstream/rn/callingx/Utils.kt +23 -0
- package/android/src/main/java/io/getstream/rn/callingx/model/Call.kt +57 -0
- package/android/src/main/java/io/getstream/rn/callingx/model/CallAction.kt +36 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt +215 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt +113 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationIntentFactory.kt +105 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverActivity.kt +42 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationReceiverService.kt +56 -0
- package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationsConfig.kt +116 -0
- package/android/src/main/java/io/getstream/rn/callingx/repo/CallRepository.kt +163 -0
- package/android/src/main/java/io/getstream/rn/callingx/repo/LegacyCallRepository.kt +134 -0
- package/android/src/main/java/io/getstream/rn/callingx/repo/TelecomCallRepository.kt +438 -0
- package/android/src/main/res/drawable/ic_phone_paused_24.xml +11 -0
- package/android/src/main/res/drawable/ic_round_call_24.xml +11 -0
- package/android/src/main/res/drawable/ic_user.xml +27 -0
- package/dist/module/CallingxModule.js +191 -0
- package/dist/module/CallingxModule.js.map +1 -0
- package/dist/module/EventManager.js +40 -0
- package/dist/module/EventManager.js.map +1 -0
- package/dist/module/index.js +5 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/package.json +1 -0
- package/dist/module/spec/NativeCallingx.js +8 -0
- package/dist/module/spec/NativeCallingx.js.map +1 -0
- package/dist/module/types.js +4 -0
- package/dist/module/types.js.map +1 -0
- package/dist/module/utils/constants.js +48 -0
- package/dist/module/utils/constants.js.map +1 -0
- package/dist/module/utils/headlessTask.js +37 -0
- package/dist/module/utils/headlessTask.js.map +1 -0
- package/dist/module/utils/permissions.js +86 -0
- package/dist/module/utils/permissions.js.map +1 -0
- package/dist/module/utils/types.js +2 -0
- package/dist/module/utils/types.js.map +1 -0
- package/dist/module/utils/utils.js +6 -0
- package/dist/module/utils/utils.js.map +1 -0
- package/dist/typescript/package.json +1 -0
- package/dist/typescript/src/CallingxModule.d.ts +44 -0
- package/dist/typescript/src/CallingxModule.d.ts.map +1 -0
- package/dist/typescript/src/EventManager.d.ts +11 -0
- package/dist/typescript/src/EventManager.d.ts.map +1 -0
- package/dist/typescript/src/index.d.ts +3 -0
- package/dist/typescript/src/index.d.ts.map +1 -0
- package/dist/typescript/src/spec/NativeCallingx.d.ts +132 -0
- package/dist/typescript/src/spec/NativeCallingx.d.ts.map +1 -0
- package/dist/typescript/src/types.d.ts +249 -0
- package/dist/typescript/src/types.d.ts.map +1 -0
- package/dist/typescript/src/utils/constants.d.ts +8 -0
- package/dist/typescript/src/utils/constants.d.ts.map +1 -0
- package/dist/typescript/src/utils/headlessTask.d.ts +8 -0
- package/dist/typescript/src/utils/headlessTask.d.ts.map +1 -0
- package/dist/typescript/src/utils/permissions.d.ts +8 -0
- package/dist/typescript/src/utils/permissions.d.ts.map +1 -0
- package/dist/typescript/src/utils/types.d.ts +4 -0
- package/dist/typescript/src/utils/types.d.ts.map +1 -0
- package/dist/typescript/src/utils/utils.d.ts +2 -0
- package/dist/typescript/src/utils/utils.d.ts.map +1 -0
- package/ios/AudioSessionManager.swift +46 -0
- package/ios/Callingx.mm +280 -0
- package/ios/CallingxImpl.swift +744 -0
- package/ios/CallingxPublic.h +79 -0
- package/ios/Settings.swift +108 -0
- package/ios/UUIDStorage.swift +124 -0
- package/ios/VoipNotificationsManager.swift +180 -0
- package/package.json +112 -0
- package/react-native.config.js +8 -0
- package/src/CallingxModule.ts +321 -0
- package/src/EventManager.ts +61 -0
- package/src/index.ts +2 -0
- package/src/spec/NativeCallingx.ts +176 -0
- package/src/types.ts +323 -0
- package/src/utils/constants.ts +55 -0
- package/src/utils/headlessTask.ts +52 -0
- package/src/utils/permissions.ts +111 -0
- package/src/utils/types.ts +5 -0
- 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
|
+
}
|
package/android/src/main/java/io/getstream/rn/callingx/notifications/CallNotificationManager.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/io/getstream/rn/callingx/notifications/NotificationChannelsManager.kt
ADDED
|
@@ -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
|
+
}
|