Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[notifications][Android] Convert all exported modules to new API #24499

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import com.facebook.react.bridge.ReactApplicationContext
import expo.modules.adapters.react.ReactModuleRegistryProvider
import expo.modules.core.ModuleRegistry
import expo.modules.core.interfaces.RegistryLifecycleListener
import expo.modules.notifications.notifications.categories.ExpoNotificationCategoriesModule
import expo.modules.notifications.notifications.handling.NotificationsHandler
import expo.modules.notifications.notifications.scheduling.NotificationScheduler
import host.exp.exponent.utils.ScopedContext
import host.exp.exponent.kernel.ExperienceKey
import expo.modules.manifests.core.Manifest
import versioned.host.exp.exponent.modules.universal.*
import versioned.host.exp.exponent.modules.universal.notifications.ScopedServerRegistrationModule
import host.exp.exponent.kernel.ExperienceKey
import host.exp.exponent.utils.ScopedContext
import versioned.host.exp.exponent.modules.universal.ConstantsBinding
import versioned.host.exp.exponent.modules.universal.ExpoModuleRegistryAdapter
import versioned.host.exp.exponent.modules.universal.ScopedUIManagerModuleWrapper
import versioned.host.exp.exponent.modules.universal.UpdatesBinding

open class DetachedModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegistryProvider) :
ExpoModuleRegistryAdapter(moduleRegistryProvider) {
Expand Down Expand Up @@ -49,15 +48,6 @@ open class DetachedModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegi
// Overriding ScopedUIManagerModuleWrapper from ReactAdapterPackage
moduleRegistry.registerInternalModule(ScopedUIManagerModuleWrapper(reactContext))

// Certain notifications classes should share `SharedPreferences` object with the notifications services, so we don't want to use scoped context.
moduleRegistry.registerExportedModule(NotificationScheduler(scopedContext.baseContext))
moduleRegistry.registerExportedModule(ExpoNotificationCategoriesModule(scopedContext.baseContext))
moduleRegistry.registerExportedModule(NotificationsHandler(scopedContext.baseContext))
// We consciously pass scoped context to ScopedServerRegistrationModule
// so it can access legacy scoped backed-up storage and migrates
// the legacy UUID to scoped non-backed-up storage.
moduleRegistry.registerExportedModule(ScopedServerRegistrationModule(scopedContext))

// Adding other modules (not universal) to module registry as consumers.
// It allows these modules to refer to universal modules.
for (otherModule in otherModules) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package host.exp.exponent.utils

import android.Manifest
import host.exp.exponent.kernel.ExperienceKey
import javax.inject.Inject
import host.exp.exponent.kernel.services.ExpoKernelServiceRegistry
import host.exp.exponent.experience.ReactNativeActivity
import android.content.pm.PackageManager
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.provider.Settings
import com.facebook.react.modules.core.PermissionListener
import host.exp.exponent.di.NativeModuleDepsProvider
import host.exp.exponent.experience.ReactNativeActivity
import host.exp.exponent.kernel.ExperienceKey
import host.exp.exponent.kernel.services.ExpoKernelServiceRegistry
import host.exp.expoview.Exponent
import host.exp.expoview.R
import java.util.*
import javax.inject.Inject

class ScopedPermissionsRequester(private val experienceKey: ExperienceKey) {
@Inject
Expand Down Expand Up @@ -141,6 +140,7 @@ class ScopedPermissionsRequester(private val experienceKey: ExperienceKey) {
Manifest.permission.READ_MEDIA_IMAGES -> R.string.perm_read_media_images
Manifest.permission.READ_MEDIA_VIDEO -> R.string.perm_read_media_videos
Manifest.permission.READ_MEDIA_AUDIO -> R.string.perm_read_media_audio
Manifest.permission.POST_NOTIFICATIONS -> R.string.perm_notifications
else -> -1
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ import expo.modules.medialibrary.MediaLibraryModule
import expo.modules.navigationbar.NavigationBarPackage
import expo.modules.network.NetworkModule
import expo.modules.notifications.NotificationsPackage
import expo.modules.notifications.badge.BadgeModule
import expo.modules.notifications.notifications.background.ExpoBackgroundNotificationTasksModule
import expo.modules.notifications.notifications.channels.NotificationChannelGroupManagerModule
import expo.modules.notifications.notifications.channels.NotificationChannelManagerModule
import expo.modules.notifications.permissions.NotificationPermissionsModule
import expo.modules.notifications.tokens.PushTokenModule
import expo.modules.permissions.PermissionsPackage
import expo.modules.print.PrintModule
import expo.modules.random.RandomModule
Expand Down Expand Up @@ -124,6 +130,14 @@ object ExperiencePackagePicker : ModulesProvider {
MagnetometerUncalibratedModule::class.java,
PedometerModule::class.java,
// End of Sensors
// Notifications
BadgeModule::class.java,
PushTokenModule::class.java,
NotificationPermissionsModule::class.java,
NotificationChannelManagerModule::class.java,
NotificationChannelGroupManagerModule::class.java,
ExpoBackgroundNotificationTasksModule::class.java,
// End of Notifications
BatteryModule::class.java,
BackgroundFetchModule::class.java,
BarCodeScannerModule::class.java,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ import expo.modules.core.interfaces.RegistryLifecycleListener
import expo.modules.font.FontLoaderModule
import expo.modules.kotlin.ModulesProvider
import expo.modules.manifests.core.Manifest
import host.exp.exponent.utils.ScopedContext
import host.exp.exponent.kernel.ExperienceKey
import host.exp.exponent.utils.ScopedContext
import versioned.host.exp.exponent.core.modules.ExpoGoModule
import versioned.host.exp.exponent.modules.api.notifications.ScopedNotificationsCategoriesSerializer
import versioned.host.exp.exponent.modules.api.notifications.channels.ScopedNotificationsChannelsProvider
import versioned.host.exp.exponent.modules.universal.av.SharedCookiesDataSourceFactoryProvider
import versioned.host.exp.exponent.modules.universal.notifications.*
import versioned.host.exp.exponent.modules.universal.sensors.*
import java.lang.RuntimeException
import versioned.host.exp.exponent.modules.universal.notifications.ScopedExpoNotificationCategoriesModule
import versioned.host.exp.exponent.modules.universal.notifications.ScopedExpoNotificationPresentationModule
import versioned.host.exp.exponent.modules.universal.notifications.ScopedNotificationScheduler
import versioned.host.exp.exponent.modules.universal.notifications.ScopedNotificationsEmitter
import versioned.host.exp.exponent.modules.universal.notifications.ScopedNotificationsHandler
import versioned.host.exp.exponent.modules.universal.notifications.ScopedServerRegistrationModule
import versioned.host.exp.exponent.modules.universal.sensors.ScopedAccelerometerService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedGravitySensorService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedGyroscopeService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedLinearAccelerationSensorService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedMagnetometerService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedMagnetometerUncalibratedService
import versioned.host.exp.exponent.modules.universal.sensors.ScopedRotationVectorSensorService

open class ExpoModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegistryProvider?, modulesProvider: ModulesProvider? = null) :
ModuleRegistryAdapter(moduleRegistryProvider, modulesProvider), ScopedModuleRegistryAdapter {
Expand Down Expand Up @@ -52,12 +62,6 @@ open class ExpoModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegistry
moduleRegistry.registerInternalModule(UpdatesBinding(scopedContext, experienceProperties))

// Overriding expo-notifications classes
moduleRegistry.registerExportedModule(ScopedNotificationsEmitter(scopedContext, experienceKey))
moduleRegistry.registerExportedModule(ScopedNotificationsHandler(scopedContext, experienceKey))
moduleRegistry.registerExportedModule(ScopedNotificationScheduler(scopedContext, experienceKey))
moduleRegistry.registerExportedModule(ScopedExpoNotificationCategoriesModule(scopedContext, experienceKey))
moduleRegistry.registerExportedModule(ScopedExpoNotificationPresentationModule(scopedContext, experienceKey))
moduleRegistry.registerExportedModule(ScopedServerRegistrationModule(scopedContext))
moduleRegistry.registerInternalModule(ScopedNotificationsChannelsProvider(scopedContext, experienceKey))
moduleRegistry.registerInternalModule(ScopedNotificationsCategoriesSerializer())

Expand All @@ -81,18 +85,26 @@ open class ExpoModuleRegistryAdapter(moduleRegistryProvider: ReactModuleRegistry
reactContext,
moduleRegistry
) { appContext ->
appContext.registry.register(
ExpoGoModule(manifest)
)
appContext.registry.register(
ScopedSecureStoreModule(scopedContext)
)
appContext.registry.register(
object : FontLoaderModule() {
override val prefix: String
get() = "ExpoFont-"
}
)
with(appContext.registry) {
register(
ExpoGoModule(manifest),
ScopedSecureStoreModule(scopedContext),
object : FontLoaderModule() {
override val prefix: String
get() = "ExpoFont-"
}
)

// Notifications
register(
ScopedNotificationsEmitter(scopedContext, experienceKey),
ScopedNotificationsHandler(scopedContext, experienceKey),
ScopedServerRegistrationModule(),
ScopedNotificationScheduler(scopedContext, experienceKey),
ScopedExpoNotificationPresentationModule(scopedContext, experienceKey),
ScopedExpoNotificationCategoriesModule(experienceKey)
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package versioned.host.exp.exponent.modules.universal.notifications

import android.content.Context
import android.os.Bundle
import expo.modules.core.Promise
import expo.modules.kotlin.Promise
import expo.modules.notifications.notifications.categories.ExpoNotificationCategoriesModule
import expo.modules.notifications.notifications.categories.NotificationActionRecord
import expo.modules.notifications.notifications.model.NotificationCategory
import host.exp.exponent.kernel.ExperienceKey
import versioned.host.exp.exponent.modules.api.notifications.ScopedNotificationsIdUtils

class ScopedExpoNotificationCategoriesModule(
context: Context,
private val experienceKey: ExperienceKey
) : ExpoNotificationCategoriesModule(context) {
) : ExpoNotificationCategoriesModule() {
override fun setNotificationCategoryAsync(
identifier: String,
actionArguments: List<Map<String, Any>>,
categoryOptions: Map<String, Any>?,
actionArguments: List<NotificationActionRecord>,
categoryOptions: Map<String, Any?>?,
promise: Promise
) {
val scopedCategoryIdentifier = ScopedNotificationsIdUtils.getScopedCategoryId(experienceKey, identifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package versioned.host.exp.exponent.modules.universal.notifications

import android.content.Context
import android.os.Bundle
import expo.modules.core.Promise
import expo.modules.kotlin.Promise
import expo.modules.notifications.notifications.NotificationSerializer
import expo.modules.notifications.notifications.interfaces.NotificationTrigger
import expo.modules.notifications.notifications.model.Notification
Expand All @@ -15,9 +15,9 @@ import host.exp.exponent.notifications.ScopedNotificationsUtils
import host.exp.exponent.notifications.model.ScopedNotificationRequest

class ScopedExpoNotificationPresentationModule(
context: Context,
private val context: Context,
private val experienceKey: ExperienceKey
) : ExpoNotificationPresentationModule(context) {
) : ExpoNotificationPresentationModule() {
private val scopedNotificationsUtils = ScopedNotificationsUtils(context)

override fun createNotificationRequest(
Expand All @@ -37,8 +37,8 @@ class ScopedExpoNotificationPresentationModule(
override fun dismissNotificationAsync(identifier: String, promise: Promise) {
NotificationsService.getAllPresented(
context,
createResultReceiver { resultCode: Int, resultData: Bundle ->
val notifications = resultData.getParcelableArrayList<Notification>(
createResultReceiver { resultCode: Int, resultData: Bundle? ->
val notifications = resultData?.getParcelableArrayList<Notification>(
NotificationsService.NOTIFICATIONS_KEY
)
if (resultCode == NotificationsService.SUCCESS_CODE && notifications != null) {
Expand All @@ -47,9 +47,9 @@ class ScopedExpoNotificationPresentationModule(
promise.resolve(null)
return@createResultReceiver
}
doDismissNotificationAsync(identifier, promise)
super.dismissNotificationAsync(identifier, promise)
} else {
val e = resultData.getSerializable(NotificationsService.EXCEPTION_KEY) as Exception
val e = resultData?.getSerializable(NotificationsService.EXCEPTION_KEY) as? Exception
promise.reject(
"ERR_NOTIFICATIONS_FETCH_FAILED",
"A list of displayed notifications could not be fetched.",
Expand All @@ -63,8 +63,8 @@ class ScopedExpoNotificationPresentationModule(
override fun dismissAllNotificationsAsync(promise: Promise) {
NotificationsService.getAllPresented(
context,
createResultReceiver { resultCode: Int, resultData: Bundle ->
val notifications = resultData.getParcelableArrayList<Notification>(
createResultReceiver { resultCode: Int, resultData: Bundle? ->
val notifications = resultData?.getParcelableArrayList<Notification>(
NotificationsService.NOTIFICATIONS_KEY
)
if (resultCode == NotificationsService.SUCCESS_CODE && notifications != null) {
Expand All @@ -73,7 +73,7 @@ class ScopedExpoNotificationPresentationModule(
.map { it.notificationRequest.identifier }
dismissSelectedAsync(toDismiss.toTypedArray(), promise)
} else {
val e = resultData.getSerializable(NotificationsService.EXCEPTION_KEY) as Exception
val e = resultData?.getSerializable(NotificationsService.EXCEPTION_KEY) as? Exception
promise.reject(
"ERR_NOTIFICATIONS_FETCH_FAILED",
"A list of displayed notifications could not be fetched.",
Expand All @@ -84,19 +84,15 @@ class ScopedExpoNotificationPresentationModule(
)
}

private fun doDismissNotificationAsync(identifier: String, promise: Promise) {
super.dismissNotificationAsync(identifier, promise)
}

private fun dismissSelectedAsync(identifiers: Array<String>, promise: Promise) {
NotificationsService.dismiss(
context,
identifiers,
createResultReceiver { resultCode: Int, resultData: Bundle ->
createResultReceiver { resultCode: Int, resultData: Bundle? ->
if (resultCode == NotificationsService.SUCCESS_CODE) {
promise.resolve(null)
} else {
val e = resultData.getSerializable(NotificationsService.EXCEPTION_KEY) as Exception
val e = resultData?.getSerializable(NotificationsService.EXCEPTION_KEY) as? Exception
promise.reject(
"ERR_NOTIFICATIONS_DISMISSAL_FAILED",
"Notifications could not be dismissed.",
Expand Down
Loading