Skip to content
Draft
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
19 changes: 6 additions & 13 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@ def isNewArchitectureEnabled() {
apply plugin: "com.android.library"
apply plugin: "kotlin-android"


def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }

if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}
apply plugin: "com.facebook.react"

def getExtOrDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["CourierReactNative_" + name]
Expand Down Expand Up @@ -100,10 +97,8 @@ def kotlin_version = getExtOrDefault("kotlinVersion")

dependencies {

// For < 0.71, this will be from the local maven repo
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-android:0.73.7"
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

// For converting to json
Expand All @@ -115,10 +110,8 @@ dependencies {

}

if (isNewArchitectureEnabled()) {
react {
jsRootDir = file("../src/")
libraryName = "CourierReactNativeView"
codegenJavaPackageName = "com.courierreactnative"
}
react {
jsRootDir = file("../src/")
libraryName = "CourierReactNativeView"
codegenJavaPackageName = "com.courierreactnative"
}
10 changes: 5 additions & 5 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CourierReactNative_kotlinVersion=1.7.0
CourierReactNative_minSdkVersion=23
CourierReactNative_targetSdkVersion=31
CourierReactNative_compileSdkVersion=31
CourierReactNative_ndkversion=21.4.7075529
CourierReactNative_kotlinVersion=1.9.24
CourierReactNative_minSdkVersion=24
CourierReactNative_targetSdkVersion=34
CourierReactNative_compileSdkVersion=34
CourierReactNative_ndkversion=26.1.10909125
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ class CourierClientModule(
return@launch
}

if (reactActivity == null) {
val currentActivity = activity
if (currentActivity == null) {
promise.rejectMissingContext()
return@launch
}
Expand All @@ -97,7 +98,7 @@ class CourierClientModule(
client.tokens.putUserToken(
token = token,
provider = provider,
device = courierDevice ?: CourierDevice.current(reactActivity!!)
device = courierDevice ?: CourierDevice.current(currentActivity)
)
promise.resolve(null)
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ class CourierPreferencesViewManager : SimpleViewManager<CourierPreferences>() {

override fun createViewInstance(reactContext: ThemedReactContext): CourierPreferences {
themedReactContext = reactContext
val activity = reactContext.currentActivity as FragmentActivity
return CourierReactNativePreferencesView(activity)
val activity = reactContext.currentActivity as? FragmentActivity ?: reactContext.reactApplicationContext.currentActivity as? FragmentActivity
return CourierReactNativePreferencesView(activity ?: reactContext)
}

@ReactProp(name = "onScrollPreferences")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
package com.courierreactnative

import com.facebook.react.ReactPackage
import com.facebook.react.TurboReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.module.model.ReactModuleInfo
import com.facebook.react.module.model.ReactModuleInfoProvider
import com.facebook.react.uimanager.ViewManager

class CourierReactNativePackage : ReactPackage {
class CourierReactNativePackage : TurboReactPackage() {

override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(
CourierClientModule(reactContext),
CourierSharedModule(reactContext),
CourierSystemModule(reactContext),
)
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
return when (name) {
"CourierClientModule" -> CourierClientModule(reactContext)
"CourierSharedModule" -> CourierSharedModule(reactContext)
"CourierSystemModule" -> CourierSystemModule(reactContext)
else -> null
}
}

override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
return ReactModuleInfoProvider {
val modules = mutableMapOf<String, ReactModuleInfo>()
val moduleNames = listOf("CourierClientModule", "CourierSharedModule", "CourierSystemModule")
for (moduleName in moduleNames) {
modules[moduleName] = ReactModuleInfo(
moduleName,
moduleName,
false,
false,
true,
false,
false
)
}
modules
}
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class CourierSystemModule(reactContext: ReactApplicationContext): ReactNativeMod

@ReactMethod
fun registerPushNotificationClickedOnKilledState() {
reactActivity?.let { activity ->
checkIntentForPushNotificationClick(activity.intent)
activity?.let { a ->
checkIntentForPushNotificationClick(a.intent)
}
}

Expand All @@ -66,8 +66,8 @@ class CourierSystemModule(reactContext: ReactApplicationContext): ReactNativeMod
@ReactMethod
fun requestNotificationPermission(promise: Promise) {

reactActivity?.let { activity ->
Courier.shared.requestNotificationPermission(activity)
activity?.let { a ->
Courier.shared.requestNotificationPermission(a)
}

promise.resolve("unknown")
Expand All @@ -77,9 +77,9 @@ class CourierSystemModule(reactContext: ReactApplicationContext): ReactNativeMod
@ReactMethod
fun getNotificationPermissionStatus(promise: Promise) {

reactActivity?.let { context ->
activity?.let { a ->

val isGranted = Courier.shared.isPushPermissionGranted(context)
val isGranted = Courier.shared.isPushPermissionGranted(a)
val status = if (isGranted) "authorized" else "denied"
promise.resolve(status)
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.courierreactnative

import android.app.Activity
import com.courier.android.Courier
import com.facebook.react.ReactActivity
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
Expand All @@ -10,14 +10,10 @@ abstract class ReactNativeModule(val tag: String, private val name: String, reac

override fun getName() = name

val reactActivity: ReactActivity? get() = currentActivity as? ReactActivity
val activity: Activity? get() = currentActivity

init {

// User Agent is used to ensure we know the SDK
// the requests come from
Courier.agent = Utils.COURIER_AGENT

}

internal fun Promise.rejectMissingContext() {
Expand Down
32 changes: 16 additions & 16 deletions courier-react-native.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,26 @@ Pod::Spec.new do |s|
s.dependency "Courier_iOS", "5.8.0"

# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
# This automatically handles both Old and New Architecture (Turbo Modules + Fabric) setup.
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
if respond_to?(:install_modules_dependencies, true)
install_modules_dependencies(s)
else
s.dependency "React-Core"
s.dependency "React-Core"

# Don't install the dependencies when we run `pod install` in the old architecture.
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
s.pod_target_xcconfig = {
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}
s.dependency "React-RCTFabric"
s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
end
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
s.pod_target_xcconfig = {
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
}
s.dependency "React-RCTFabric"
s.dependency "React-Codegen"
s.dependency "RCT-Folly"
s.dependency "RCTRequired"
s.dependency "RCTTypeSafety"
s.dependency "ReactCommon/turbomodule/core"
end
end
end
4 changes: 4 additions & 0 deletions ios/CourierReactNative-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTViewManager.h>
#import <React/RCTEventEmitter.h>

#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridge.h>
#endif
2 changes: 1 addition & 1 deletion ios/CourierReactNativeDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Michael Miller on 8/29/23.
//

#import "RCTAppDelegate.h"
#import <React/RCTAppDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>

Expand Down
14 changes: 10 additions & 4 deletions ios/CourierReactNativeDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
@import Courier_iOS;
#import "CourierReactNativeDelegate.h"
#import <React/RCTRootView.h>
#import <React/RCTBridge.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTUtils.h>

// Conditionally import bridge headers for backward compatibility
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridge.h>
#endif

#pragma GCC diagnostic ignored "-Wprotocol"
#pragma clang diagnostic ignored "-Wprotocol"

Expand Down Expand Up @@ -49,10 +52,13 @@ - (id)init {
name:CourierForegroundOptionsDidChangeNotification
object:nil];

// RCTBridgeWillReloadNotification is only available in bridge mode.
// In bridgeless mode (New Architecture), this notification doesn't exist.
NSString *bridgeReloadNotification = @"RCTBridgeWillReloadNotification";
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onBridgeWillReload)
name:RCTBridgeWillReloadNotification
name:bridgeReloadNotification
object:nil];

[[NSNotificationCenter defaultCenter]
Expand All @@ -77,7 +83,7 @@ - (void)onReactNativeReady:(__unused NSNotification *)note
}
}

// Called when there is a reload to React Native
// Called when there is a reload to React Native (bridge mode only)
- (void)onBridgeWillReload
{
self.isReactNativeReady = NO;
Expand Down
3 changes: 3 additions & 0 deletions ios/CourierSystemModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ class CourierSystemModule: CourierReactNativeEventEmitter {
object: nil
)

// RCTBridgeWillReloadNotification is only available in bridge mode.
// In bridgeless mode (New Architecture), this notification is not posted,
// but registering for it is harmless.
notificationCenter.addObserver(
self,
selector: #selector(onBridgeWillReload),
Expand Down
36 changes: 24 additions & 12 deletions src/Modules.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
import {
NativeModules,
Platform,
TurboModuleRegistry,
UIManager,
requireNativeComponent,
} from 'react-native';

function getModule(moduleName: string): any {
// Try TurboModuleRegistry first (New Architecture / bridgeless mode)
const turboModule = TurboModuleRegistry.get(moduleName as any);
if (turboModule) {
return turboModule;
}

// Fall back to NativeModules (bridge mode / interop layer)
const bridgeModule = NativeModules[moduleName];
if (bridgeModule) {
return bridgeModule;
}

return undefined;
}

export class Modules {
static readonly LINKING_ERROR =
`The package '@trycourier/courier-react-native' doesn't seem to be linked. Make sure: \n\n` +
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
'- You rebuilt the app after installing the package\n' +
'- You are not using Expo Go\n';

static readonly Client = Modules.getNativeModule(
NativeModules.CourierClientModule
);
static readonly Shared = Modules.getNativeModule(
NativeModules.CourierSharedModule
);
static readonly System = Modules.getNativeModule(
NativeModules.CourierSystemModule
);
static readonly Client = Modules.getNativeModule('CourierClientModule');
static readonly Shared = Modules.getNativeModule('CourierSharedModule');
static readonly System = Modules.getNativeModule('CourierSystemModule');

static getNativeModule<T>(nativeModule: T | undefined): T {
static getNativeModule(moduleName: string): any {
const nativeModule = getModule(moduleName);
return nativeModule
? nativeModule
: (new Proxy(
: new Proxy(
{},
{
get() {
throw new Error(Modules.LINKING_ERROR);
},
}
) as T);
);
}

static getNativeComponent(componentName: string) {
Expand Down
Loading