<lambda>null1 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
<lambda>null54 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
<lambda>null62 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
createResultReceivernull84 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
deleteNotificationCategoryAsyncnull132 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
serializeCategoriesnull146 protected open fun serializeCategories(categories: Collection<NotificationCategory>): List<Bundle?> {
147 return categories.map(serializer::toBundle)
148 }
149 }
150