expo-notifications 0.24.2 → 0.25.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 (76) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/android/build.gradle +49 -30
  3. package/android/src/main/java/expo/modules/notifications/Exceptions.kt +22 -0
  4. package/android/src/main/java/expo/modules/notifications/NotificationsPackage.java +3 -33
  5. package/android/src/main/java/expo/modules/notifications/Utils.kt +19 -0
  6. package/android/src/main/java/expo/modules/notifications/badge/BadgeModule.kt +15 -13
  7. package/android/src/main/java/expo/modules/notifications/notifications/background/BackgroundRemoteNotificationTaskConsumer.java +2 -6
  8. package/android/src/main/java/expo/modules/notifications/notifications/background/ExpoBackgroundNotificationTasksModule.kt +12 -23
  9. package/android/src/main/java/expo/modules/notifications/notifications/categories/ExpoNotificationCategoriesModule.kt +149 -0
  10. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelGroupManagerModule.kt +42 -49
  11. package/android/src/main/java/expo/modules/notifications/notifications/channels/NotificationChannelManagerModule.kt +45 -51
  12. package/android/src/main/java/expo/modules/notifications/notifications/emitting/NotificationsEmitter.kt +21 -20
  13. package/android/src/main/java/expo/modules/notifications/notifications/handling/NotificationsHandler.kt +51 -37
  14. package/android/src/main/java/expo/modules/notifications/notifications/presentation/ExpoNotificationPresentationModule.kt +113 -0
  15. package/android/src/main/java/expo/modules/notifications/notifications/presentation/builders/ExpoNotificationBuilder.java +1 -5
  16. package/android/src/main/java/expo/modules/notifications/notifications/scheduling/NotificationScheduler.kt +235 -0
  17. package/android/src/main/java/expo/modules/notifications/permissions/NotificationPermissionsModule.kt +36 -56
  18. package/android/src/main/java/expo/modules/notifications/serverregistration/ServerRegistrationModule.kt +21 -18
  19. package/android/src/main/java/expo/modules/notifications/service/NotificationsService.kt +1 -0
  20. package/android/src/main/java/expo/modules/notifications/service/delegates/ExpoPresentationDelegate.kt +0 -6
  21. package/android/src/main/java/expo/modules/notifications/tokens/PushTokenModule.kt +51 -58
  22. package/build/BackgroundNotificationTasksModule.native.d.ts.map +1 -1
  23. package/build/BackgroundNotificationTasksModule.native.js +2 -2
  24. package/build/BackgroundNotificationTasksModule.native.js.map +1 -1
  25. package/build/BadgeModule.native.d.ts.map +1 -1
  26. package/build/BadgeModule.native.js +4 -3
  27. package/build/BadgeModule.native.js.map +1 -1
  28. package/build/NotificationCategoriesModule.native.d.ts.map +1 -1
  29. package/build/NotificationCategoriesModule.native.js +2 -2
  30. package/build/NotificationCategoriesModule.native.js.map +1 -1
  31. package/build/NotificationChannelGroupManager.native.d.ts.map +1 -1
  32. package/build/NotificationChannelGroupManager.native.js +2 -2
  33. package/build/NotificationChannelGroupManager.native.js.map +1 -1
  34. package/build/NotificationChannelManager.native.d.ts.map +1 -1
  35. package/build/NotificationChannelManager.native.js +2 -2
  36. package/build/NotificationChannelManager.native.js.map +1 -1
  37. package/build/NotificationPermissionsModule.native.d.ts.map +1 -1
  38. package/build/NotificationPermissionsModule.native.js +2 -2
  39. package/build/NotificationPermissionsModule.native.js.map +1 -1
  40. package/build/NotificationPresenterModule.native.d.ts.map +1 -1
  41. package/build/NotificationPresenterModule.native.js +2 -2
  42. package/build/NotificationPresenterModule.native.js.map +1 -1
  43. package/build/NotificationScheduler.native.d.ts.map +1 -1
  44. package/build/NotificationScheduler.native.js +2 -2
  45. package/build/NotificationScheduler.native.js.map +1 -1
  46. package/build/NotificationsEmitterModule.native.d.ts.map +1 -1
  47. package/build/NotificationsEmitterModule.native.js +2 -2
  48. package/build/NotificationsEmitterModule.native.js.map +1 -1
  49. package/build/NotificationsHandlerModule.native.d.ts.map +1 -1
  50. package/build/NotificationsHandlerModule.native.js +2 -2
  51. package/build/NotificationsHandlerModule.native.js.map +1 -1
  52. package/build/PushTokenManager.native.d.ts.map +1 -1
  53. package/build/PushTokenManager.native.js +2 -2
  54. package/build/PushTokenManager.native.js.map +1 -1
  55. package/build/ServerRegistrationModule.native.d.ts.map +1 -1
  56. package/build/ServerRegistrationModule.native.js +2 -2
  57. package/build/ServerRegistrationModule.native.js.map +1 -1
  58. package/expo-module.config.json +20 -0
  59. package/ios/EXNotifications/Notifications/Background/EXBackgroundRemoteNotificationConsumer.m +2 -4
  60. package/package.json +4 -4
  61. package/src/BackgroundNotificationTasksModule.native.ts +4 -2
  62. package/src/BadgeModule.native.ts +5 -3
  63. package/src/NotificationCategoriesModule.native.ts +4 -2
  64. package/src/NotificationChannelGroupManager.native.ts +4 -2
  65. package/src/NotificationChannelManager.native.ts +2 -2
  66. package/src/NotificationPermissionsModule.native.ts +4 -2
  67. package/src/NotificationPresenterModule.native.ts +2 -2
  68. package/src/NotificationScheduler.native.ts +2 -2
  69. package/src/NotificationsEmitterModule.native.ts +2 -2
  70. package/src/NotificationsHandlerModule.native.ts +2 -2
  71. package/src/PushTokenManager.native.ts +2 -2
  72. package/src/ServerRegistrationModule.native.ts +4 -2
  73. package/android/src/main/java/expo/modules/notifications/notifications/categories/ExpoNotificationCategoriesModule.java +0 -124
  74. package/android/src/main/java/expo/modules/notifications/notifications/presentation/ExpoNotificationPresentationModule.java +0 -116
  75. package/android/src/main/java/expo/modules/notifications/notifications/scheduling/NotificationScheduler.java +0 -222
  76. package/unimodule.json +0 -4
package/CHANGELOG.md CHANGED
@@ -10,6 +10,20 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.25.0 — 2023-10-17
14
+
15
+ ### 🛠 Breaking changes
16
+
17
+ - Dropped support for Android SDK 21 and 22. ([#24201](https://github.com/expo/expo/pull/24201) by [@behenate](https://github.com/behenate))
18
+
19
+ ### 🐛 Bug fixes
20
+
21
+ - Send background notifications through when the app is in the foreground ([#24684](https://github.com/expo/expo/pull/24684) by [@kadikraman](https://github.com/kadikraman))
22
+
23
+ ### 💡 Others
24
+
25
+ - Migrated codebase to use Expo Modules API. ([#24499](https://github.com/expo/expo/pull/24499) by [@lukmccall](https://github.com/lukmccall))
26
+
13
27
  ## 0.24.2 — 2023-09-18
14
28
 
15
29
  _This version does not introduce any user-facing changes._
@@ -3,15 +3,20 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.24.2'
7
-
8
- buildscript {
9
- def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
- if (expoModulesCorePlugin.exists()) {
11
- apply from: expoModulesCorePlugin
12
- applyKotlinExpoModulesCorePlugin()
6
+ version = '0.25.0'
7
+
8
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
+ if (expoModulesCorePlugin.exists()) {
10
+ apply from: expoModulesCorePlugin
11
+ applyKotlinExpoModulesCorePlugin()
12
+ // Remove this check, but keep the contents after SDK49 support is dropped
13
+ if (safeExtGet("expoProvidesDefaultConfig", false)) {
14
+ useExpoPublishing()
15
+ useCoreDependencies()
13
16
  }
17
+ }
14
18
 
19
+ buildscript {
15
20
  // Simple helper that allows the root project to override versions declared by this library.
16
21
  ext.safeExtGet = { prop, fallback ->
17
22
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
@@ -35,23 +40,44 @@ buildscript {
35
40
  }
36
41
  }
37
42
 
38
- afterEvaluate {
39
- publishing {
40
- publications {
41
- release(MavenPublication) {
42
- from components.release
43
+ // Remove this if and it's contents, when support for SDK49 is dropped
44
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
45
+ afterEvaluate {
46
+ publishing {
47
+ publications {
48
+ release(MavenPublication) {
49
+ from components.release
50
+ }
43
51
  }
44
- }
45
- repositories {
46
- maven {
47
- url = mavenLocal().url
52
+ repositories {
53
+ maven {
54
+ url = mavenLocal().url
55
+ }
48
56
  }
49
57
  }
50
58
  }
51
59
  }
52
60
 
53
61
  android {
54
- compileSdkVersion safeExtGet("compileSdkVersion", 33)
62
+ // Remove this if and it's contents, when support for SDK49 is dropped
63
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
64
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
65
+
66
+ defaultConfig {
67
+ minSdkVersion safeExtGet("minSdkVersion", 23)
68
+ targetSdkVersion safeExtGet("targetSdkVersion", 33)
69
+ }
70
+
71
+ publishing {
72
+ singleVariant("release") {
73
+ withSourcesJar()
74
+ }
75
+ }
76
+
77
+ lintOptions {
78
+ abortOnError false
79
+ }
80
+ }
55
81
 
56
82
  def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
57
83
  if (agpVersion.tokenize('.')[0].toInteger() < 8) {
@@ -67,34 +93,27 @@ android {
67
93
 
68
94
  namespace "expo.modules.notifications"
69
95
  defaultConfig {
70
- minSdkVersion safeExtGet("minSdkVersion", 21)
71
- targetSdkVersion safeExtGet("targetSdkVersion", 33)
72
96
  versionCode 21
73
- versionName '0.24.2'
97
+ versionName '0.25.0'
74
98
  }
75
99
 
76
- lintOptions {
77
- abortOnError false
78
- }
79
- publishing {
80
- singleVariant("release") {
81
- withSourcesJar()
82
- }
83
- }
84
100
  buildFeatures {
85
101
  buildConfig true
86
102
  }
87
103
  }
88
104
 
89
105
  dependencies {
90
- implementation project(':expo-modules-core')
106
+ // Remove this if and it's contents, when support for SDK49 is dropped
107
+ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
108
+ implementation project(':expo-modules-core')
109
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
110
+ }
91
111
 
92
112
  api 'androidx.core:core:1.5.0'
93
113
  api 'androidx.lifecycle:lifecycle-runtime:2.2.0'
94
114
  api 'androidx.lifecycle:lifecycle-process:2.2.0'
95
115
  api 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
96
116
 
97
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
98
117
 
99
118
  api 'com.google.firebase:firebase-messaging:22.0.0'
100
119
 
@@ -0,0 +1,22 @@
1
+ package expo.modules.notifications
2
+
3
+ import expo.modules.kotlin.exception.CodedException
4
+ import kotlin.reflect.KClass
5
+
6
+ class ModuleNotFoundException(moduleClass: KClass<*>) :
7
+ CodedException(message = "$moduleClass module not found")
8
+
9
+ class NotificationWasAlreadyHandledException(val id: String) : CodedException("Failed to handle notification $id, it has already been handled.")
10
+
11
+ fun expo.modules.kotlin.Promise.toLegacyPromise(): expo.modules.core.Promise {
12
+ val newPromise = this
13
+ return object : expo.modules.core.Promise {
14
+ override fun resolve(value: Any?) {
15
+ newPromise.resolve(value)
16
+ }
17
+
18
+ override fun reject(c: String?, m: String?, e: Throwable?) {
19
+ newPromise.reject(c ?: "unknown", m, e)
20
+ }
21
+ }
22
+ }
@@ -2,50 +2,20 @@ package expo.modules.notifications;
2
2
 
3
3
  import android.content.Context;
4
4
 
5
+ import java.util.Arrays;
6
+ import java.util.List;
7
+
5
8
  import expo.modules.core.BasePackage;
6
9
  import expo.modules.core.ExportedModule;
7
10
  import expo.modules.core.interfaces.InternalModule;
8
11
  import expo.modules.core.interfaces.SingletonModule;
9
-
10
- import java.util.Arrays;
11
- import java.util.List;
12
-
13
- import expo.modules.notifications.badge.BadgeModule;
14
- import expo.modules.notifications.serverregistration.ServerRegistrationModule;
15
12
  import expo.modules.notifications.notifications.NotificationManager;
16
- import expo.modules.notifications.notifications.background.ExpoBackgroundNotificationTasksModule;
17
13
  import expo.modules.notifications.notifications.categories.ExpoNotificationCategoriesModule;
18
14
  import expo.modules.notifications.notifications.categories.serializers.ExpoNotificationsCategoriesSerializer;
19
15
  import expo.modules.notifications.notifications.channels.AndroidXNotificationsChannelsProvider;
20
- import expo.modules.notifications.notifications.channels.NotificationChannelGroupManagerModule;
21
- import expo.modules.notifications.notifications.channels.NotificationChannelManagerModule;
22
- import expo.modules.notifications.notifications.emitting.NotificationsEmitter;
23
- import expo.modules.notifications.notifications.handling.NotificationsHandler;
24
- import expo.modules.notifications.notifications.presentation.ExpoNotificationPresentationModule;
25
- import expo.modules.notifications.notifications.scheduling.NotificationScheduler;
26
- import expo.modules.notifications.permissions.NotificationPermissionsModule;
27
16
  import expo.modules.notifications.tokens.PushTokenManager;
28
- import expo.modules.notifications.tokens.PushTokenModule;
29
17
 
30
18
  public class NotificationsPackage extends BasePackage {
31
- @Override
32
- public List<ExportedModule> createExportedModules(Context context) {
33
- return Arrays.asList(
34
- new BadgeModule(context),
35
- new PushTokenModule(context),
36
- new NotificationsEmitter(context),
37
- new NotificationsHandler(context),
38
- new NotificationScheduler(context),
39
- new ServerRegistrationModule(context),
40
- new NotificationPermissionsModule(context),
41
- new NotificationChannelManagerModule(context),
42
- new ExpoNotificationPresentationModule(context),
43
- new NotificationChannelGroupManagerModule(context),
44
- new ExpoNotificationCategoriesModule(context),
45
- new ExpoBackgroundNotificationTasksModule(context)
46
- );
47
- }
48
-
49
19
  @Override
50
20
  public List<SingletonModule> createSingletonModules(Context context) {
51
21
  return Arrays.asList(
@@ -0,0 +1,19 @@
1
+ package expo.modules.notifications
2
+
3
+ import android.os.Bundle
4
+ import android.os.Handler
5
+ import android.os.ResultReceiver
6
+
7
+ typealias ResultReceiverBody = (resultCode: Int, resultData: Bundle?) -> Unit
8
+
9
+ internal fun createDefaultResultReceiver(
10
+ handler: Handler?,
11
+ body: ResultReceiverBody,
12
+ ): ResultReceiver {
13
+ return object : ResultReceiver(handler) {
14
+ override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
15
+ super.onReceiveResult(resultCode, resultData)
16
+ body(resultCode, resultData)
17
+ }
18
+ }
19
+ }
@@ -1,20 +1,22 @@
1
1
  package expo.modules.notifications.badge
2
2
 
3
- import android.content.Context
4
- import expo.modules.core.ExportedModule
5
- import expo.modules.core.Promise
6
- import expo.modules.core.interfaces.ExpoMethod
3
+ import expo.modules.kotlin.exception.Exceptions
4
+ import expo.modules.kotlin.modules.Module
5
+ import expo.modules.kotlin.modules.ModuleDefinition
7
6
 
8
- class BadgeModule(context: Context) : ExportedModule(context) {
9
- override fun getName(): String = "ExpoBadgeModule"
7
+ class BadgeModule : Module() {
8
+ override fun definition() = ModuleDefinition {
9
+ Name("ExpoBadgeModule")
10
10
 
11
- @ExpoMethod
12
- fun getBadgeCountAsync(promise: Promise) {
13
- promise.resolve(BadgeHelper.badgeCount)
14
- }
11
+ AsyncFunction("getBadgeCountAsync") {
12
+ BadgeHelper.badgeCount
13
+ }
15
14
 
16
- @ExpoMethod
17
- fun setBadgeCountAsync(badgeCount: Int, promise: Promise) {
18
- promise.resolve(BadgeHelper.setBadgeCount(context, badgeCount))
15
+ AsyncFunction("setBadgeCountAsync") { badgeCount: Int ->
16
+ BadgeHelper.setBadgeCount(
17
+ appContext.reactContext ?: throw Exceptions.ReactContextLost(),
18
+ badgeCount
19
+ )
20
+ }
19
21
  }
20
22
  }
@@ -7,9 +7,6 @@ import android.os.Bundle;
7
7
  import android.os.PersistableBundle;
8
8
  import android.util.Log;
9
9
 
10
- import androidx.lifecycle.Lifecycle;
11
- import androidx.lifecycle.ProcessLifecycleOwner;
12
-
13
10
  import org.json.JSONException;
14
11
  import org.json.JSONObject;
15
12
 
@@ -26,7 +23,7 @@ import expo.modules.interfaces.taskManager.TaskInterface;
26
23
  import expo.modules.interfaces.taskManager.TaskManagerUtilsInterface;
27
24
 
28
25
  /**
29
- * Represents a task to be run when the app is backgrounded and receives a remote push
26
+ * Represents a task to be run when the app is receives a remote push
30
27
  * notification. Map of current tasks is maintained in {@link FirebaseMessagingDelegate}.
31
28
  */
32
29
  public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer implements TaskConsumerInterface {
@@ -59,9 +56,8 @@ public class BackgroundRemoteNotificationTaskConsumer extends TaskConsumer imple
59
56
 
60
57
  public void scheduleJob(Bundle bundle) {
61
58
  Context context = getContext();
62
- boolean isInForeground = ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
63
59
 
64
- if (context != null && mTask != null && !isInForeground) {
60
+ if (context != null && mTask != null) {
65
61
  PersistableBundle data = new PersistableBundle();
66
62
  // Bundles are not persistable, so let's convert to a JSON string
67
63
  data.putString(NOTIFICATION_KEY, bundleToJson(bundle).toString());
@@ -1,44 +1,33 @@
1
1
  package expo.modules.notifications.notifications.background
2
2
 
3
- import android.content.Context
4
- import expo.modules.core.ExportedModule
5
- import expo.modules.core.ModuleRegistry
6
- import expo.modules.core.Promise
7
- import expo.modules.core.interfaces.ExpoMethod
8
3
  import expo.modules.interfaces.taskManager.TaskManagerInterface
4
+ import expo.modules.kotlin.modules.Module
5
+ import expo.modules.kotlin.modules.ModuleDefinition
6
+ import expo.modules.notifications.ModuleNotFoundException
9
7
 
10
- class ExpoBackgroundNotificationTasksModule(context: Context?) : ExportedModule(context) {
8
+ class ExpoBackgroundNotificationTasksModule : Module() {
11
9
  private lateinit var taskManager: TaskManagerInterface
12
- override fun getName(): String = "ExpoBackgroundNotificationTasksModule"
13
10
 
14
- override fun onCreate(moduleRegistry: ModuleRegistry) {
15
- taskManager = moduleRegistry.getModule(TaskManagerInterface::class.java)
16
- }
11
+ override fun definition() = ModuleDefinition {
12
+ Name("ExpoBackgroundNotificationTasksModule")
13
+ OnCreate {
14
+ taskManager = appContext.legacyModule()
15
+ ?: throw ModuleNotFoundException(TaskManagerInterface::class)
16
+ }
17
17
 
18
- @ExpoMethod
19
- fun registerTaskAsync(taskName: String?, promise: Promise) {
20
- try {
18
+ AsyncFunction("registerTaskAsync") { taskName: String ->
21
19
  taskManager.registerTask(
22
20
  taskName,
23
21
  BackgroundRemoteNotificationTaskConsumer::class.java,
24
22
  emptyMap()
25
23
  )
26
- promise.resolve(null)
27
- } catch (e: Exception) {
28
- promise.reject(e)
29
24
  }
30
- }
31
25
 
32
- @ExpoMethod
33
- fun unregisterTaskAsync(taskName: String?, promise: Promise) {
34
- try {
26
+ AsyncFunction("unregisterTaskAsync") { taskName: String ->
35
27
  taskManager.unregisterTask(
36
28
  taskName,
37
29
  BackgroundRemoteNotificationTaskConsumer::class.java
38
30
  )
39
- promise.resolve(null)
40
- } catch (e: Exception) {
41
- promise.reject(e)
42
31
  }
43
32
  }
44
33
  }
@@ -0,0 +1,149 @@
1
+ package expo.modules.notifications.notifications.categories
2
+
3
+ import android.content.Context
4
+ import android.os.Bundle
5
+ import expo.modules.core.errors.InvalidArgumentException
6
+ import expo.modules.kotlin.Promise
7
+ import expo.modules.kotlin.exception.Exceptions
8
+ import expo.modules.kotlin.modules.Module
9
+ import expo.modules.kotlin.modules.ModuleDefinition
10
+ import expo.modules.kotlin.records.Field
11
+ import expo.modules.kotlin.records.Record
12
+ import expo.modules.kotlin.records.Required
13
+ import expo.modules.notifications.ModuleNotFoundException
14
+ import expo.modules.notifications.ResultReceiverBody
15
+ import expo.modules.notifications.createDefaultResultReceiver
16
+ import expo.modules.notifications.notifications.categories.serializers.NotificationsCategoriesSerializer
17
+ import expo.modules.notifications.notifications.model.NotificationAction
18
+ import expo.modules.notifications.notifications.model.NotificationCategory
19
+ import expo.modules.notifications.notifications.model.TextInputNotificationAction
20
+ import expo.modules.notifications.service.NotificationsService
21
+ import expo.modules.notifications.service.NotificationsService.Companion.deleteCategory
22
+ import expo.modules.notifications.service.NotificationsService.Companion.getCategories
23
+ import expo.modules.notifications.service.NotificationsService.Companion.setCategory
24
+
25
+ class NotificationActionRecord : Record {
26
+ @Field
27
+ @Required
28
+ val identifier: String = ""
29
+
30
+ @Field
31
+ @Required
32
+ val buttonTitle: String = ""
33
+
34
+ @Field
35
+ val textInput: TextInput? = null
36
+
37
+ @Field
38
+ val options = Options()
39
+
40
+ class TextInput : Record {
41
+ @Field
42
+ @Required
43
+ val placeholder: String = ""
44
+ }
45
+
46
+ class Options : Record {
47
+ @Field
48
+ val opensAppToForeground = true
49
+ }
50
+ }
51
+
52
+ open class ExpoNotificationCategoriesModule : Module() {
53
+
54
+ protected val serializer by lazy {
55
+ appContext.legacyModule<NotificationsCategoriesSerializer>()
56
+ ?: throw ModuleNotFoundException(NotificationsCategoriesSerializer::class)
57
+ }
58
+
59
+ private val context: Context
60
+ get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
61
+
62
+ override fun definition() = ModuleDefinition {
63
+ Name("ExpoNotificationCategoriesModule")
64
+
65
+ AsyncFunction("getNotificationCategoriesAsync") { promise: Promise ->
66
+ getCategories(
67
+ context,
68
+ createResultReceiver { resultCode: Int, resultData: Bundle? ->
69
+ val categories = resultData?.getParcelableArrayList<NotificationCategory>(NotificationsService.NOTIFICATION_CATEGORIES_KEY)
70
+ if (resultCode == NotificationsService.SUCCESS_CODE && categories != null) {
71
+ promise.resolve(serializeCategories(categories))
72
+ } else {
73
+ promise.reject("ERR_CATEGORIES_FETCH_FAILED", "A list of notification categories could not be fetched.", null)
74
+ }
75
+ }
76
+ )
77
+ }
78
+
79
+ AsyncFunction("setNotificationCategoryAsync", this@ExpoNotificationCategoriesModule::setNotificationCategoryAsync)
80
+
81
+ AsyncFunction("deleteNotificationCategoryAsync", this@ExpoNotificationCategoriesModule::deleteNotificationCategoryAsync)
82
+ }
83
+
84
+ private fun createResultReceiver(body: ResultReceiverBody) =
85
+ createDefaultResultReceiver(null, body)
86
+
87
+ open fun setNotificationCategoryAsync(
88
+ identifier: String,
89
+ actionArguments: List<NotificationActionRecord>,
90
+ categoryOptions: Map<String, Any?>?,
91
+ promise: Promise
92
+ ) {
93
+ val actions = mutableListOf<NotificationAction>()
94
+ for (actionMap in actionArguments) {
95
+ val textInputOptions = actionMap.textInput
96
+ if (textInputOptions != null) {
97
+ actions.add(
98
+ TextInputNotificationAction(
99
+ actionMap.identifier,
100
+ actionMap.buttonTitle,
101
+ actionMap.options.opensAppToForeground,
102
+ textInputOptions.placeholder
103
+ )
104
+ )
105
+ } else {
106
+ actions.add(
107
+ NotificationAction(
108
+ actionMap.identifier,
109
+ actionMap.buttonTitle,
110
+ actionMap.options.opensAppToForeground,
111
+ )
112
+ )
113
+ }
114
+ }
115
+ if (actions.isEmpty()) {
116
+ throw InvalidArgumentException("Invalid arguments provided for notification category. Must provide at least one action.")
117
+ }
118
+ setCategory(
119
+ context,
120
+ NotificationCategory(identifier, actions),
121
+ createResultReceiver { resultCode: Int, resultData: Bundle? ->
122
+ val category = resultData?.getParcelable<NotificationCategory>(NotificationsService.NOTIFICATION_CATEGORY_KEY)
123
+ if (resultCode == NotificationsService.SUCCESS_CODE && category != null) {
124
+ promise.resolve(serializer.toBundle(category))
125
+ } else {
126
+ promise.reject("ERR_CATEGORY_SET_FAILED", "The provided category could not be set.", null)
127
+ }
128
+ }
129
+ )
130
+ }
131
+
132
+ open fun deleteNotificationCategoryAsync(identifier: String, promise: Promise) {
133
+ deleteCategory(
134
+ context,
135
+ identifier,
136
+ createResultReceiver { resultCode: Int, resultData: Bundle? ->
137
+ if (resultCode == NotificationsService.SUCCESS_CODE) {
138
+ promise.resolve(resultData?.getBoolean(NotificationsService.SUCCEEDED_KEY))
139
+ } else {
140
+ promise.reject("ERR_CATEGORY_DELETE_FAILED", "The category could not be deleted.", null)
141
+ }
142
+ }
143
+ )
144
+ }
145
+
146
+ protected open fun serializeCategories(categories: Collection<NotificationCategory>): List<Bundle?> {
147
+ return categories.map(serializer::toBundle)
148
+ }
149
+ }
@@ -1,74 +1,67 @@
1
1
  package expo.modules.notifications.notifications.channels
2
2
 
3
- import android.content.Context
4
3
  import android.os.Build
5
- import expo.modules.core.ExportedModule
6
- import expo.modules.core.ModuleRegistry
7
- import expo.modules.core.Promise
8
4
  import expo.modules.core.arguments.ReadableArguments
9
- import expo.modules.core.interfaces.ExpoMethod
5
+ import expo.modules.kotlin.modules.Module
6
+ import expo.modules.kotlin.modules.ModuleDefinition
7
+ import expo.modules.notifications.ModuleNotFoundException
10
8
  import expo.modules.notifications.notifications.channels.managers.NotificationsChannelGroupManager
11
9
  import expo.modules.notifications.notifications.channels.serializers.NotificationsChannelGroupSerializer
12
10
 
13
11
  /**
14
12
  * An exported module responsible for exposing methods for managing notification channel groups.
15
13
  */
16
- class NotificationChannelGroupManagerModule(context: Context) : ExportedModule(context) {
14
+ class NotificationChannelGroupManagerModule : Module() {
17
15
  private lateinit var groupManager: NotificationsChannelGroupManager
18
16
  private lateinit var groupSerializer: NotificationsChannelGroupSerializer
19
17
 
20
- override fun onCreate(moduleRegistry: ModuleRegistry) {
21
- val provider = moduleRegistry.getModule(NotificationsChannelsProvider::class.java)
22
- groupManager = provider.groupManager
23
- groupSerializer = provider.groupSerializer
24
- }
18
+ override fun definition() = ModuleDefinition {
19
+ Name("ExpoNotificationChannelGroupManager")
25
20
 
26
- override fun getName(): String = "ExpoNotificationChannelGroupManager"
21
+ OnCreate {
22
+ val provider = appContext.legacyModule<NotificationsChannelsProvider>()
23
+ ?: throw ModuleNotFoundException(NotificationsChannelsProvider::class)
24
+ groupManager = provider.groupManager
25
+ groupSerializer = provider.groupSerializer
26
+ }
27
27
 
28
- @ExpoMethod
29
- fun getNotificationChannelGroupAsync(groupId: String, promise: Promise) {
30
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
31
- promise.resolve(null)
32
- return
28
+ AsyncFunction("getNotificationChannelGroupAsync") { groupId: String ->
29
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
30
+ val group = groupManager.getNotificationChannelGroup(groupId)
31
+ groupSerializer.toBundle(group)
32
+ } else {
33
+ null
34
+ }
33
35
  }
34
- val group = groupManager.getNotificationChannelGroup(groupId)
35
- promise.resolve(groupSerializer.toBundle(group))
36
- }
37
36
 
38
- @ExpoMethod
39
- fun getNotificationChannelGroupsAsync(promise: Promise) {
40
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
41
- promise.resolve(null)
42
- return
37
+ AsyncFunction("getNotificationChannelGroupsAsync") {
38
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
39
+ groupManager
40
+ .notificationChannelGroups
41
+ .map(groupSerializer::toBundle)
42
+ } else {
43
+ null
44
+ }
43
45
  }
44
- val serializedChannels = groupManager
45
- .notificationChannelGroups
46
- .map(groupSerializer::toBundle)
47
- promise.resolve(serializedChannels)
48
- }
49
46
 
50
- @ExpoMethod
51
- fun setNotificationChannelGroupAsync(groupId: String, groupOptions: ReadableArguments, promise: Promise) {
52
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
53
- promise.resolve(null)
54
- return
47
+ AsyncFunction("setNotificationChannelGroupAsync") { groupId: String, groupOptions: ReadableArguments ->
48
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
49
+ val group = groupManager.createNotificationChannelGroup(
50
+ groupId,
51
+ getNameFromOptions(groupOptions),
52
+ groupOptions
53
+ )
54
+ groupSerializer.toBundle(group)
55
+ } else {
56
+ null
57
+ }
55
58
  }
56
- val group = groupManager.createNotificationChannelGroup(
57
- groupId,
58
- getNameFromOptions(groupOptions),
59
- groupOptions
60
- )
61
- promise.resolve(groupSerializer.toBundle(group))
62
- }
63
59
 
64
- @ExpoMethod
65
- fun deleteNotificationChannelGroupAsync(groupId: String, promise: Promise) {
66
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
67
- promise.resolve(null)
68
- return
60
+ AsyncFunction("deleteNotificationChannelGroupAsync") { groupId: String ->
61
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
62
+ groupManager.deleteNotificationChannelGroup(groupId)
63
+ }
69
64
  }
70
- groupManager.deleteNotificationChannelGroup(groupId)
71
- promise.resolve(null)
72
65
  }
73
66
 
74
67
  private fun getNameFromOptions(groupOptions: ReadableArguments): String {